]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | //! The Rust compiler. |
2 | //! | |
3 | //! # Note | |
4 | //! | |
5 | //! This API is completely unstable and subject to change. | |
6 | ||
1b1a35ee | 7 | #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")] |
60c5eb7d | 8 | #![feature(bool_to_option)] |
dc9dc135 | 9 | #![feature(const_cstr_unchecked)] |
b7449926 | 10 | #![feature(crate_visibility_modifier)] |
cdc7bbd5 | 11 | #![feature(extended_key_value_attributes)] |
b7449926 XL |
12 | #![feature(extern_types)] |
13 | #![feature(in_band_lifetimes)] | |
cdc7bbd5 | 14 | #![feature(iter_zip)] |
0bf4aa26 | 15 | #![feature(nll)] |
cdc7bbd5 | 16 | #![cfg_attr(bootstrap, feature(or_patterns))] |
dfeec247 | 17 | #![recursion_limit = "256"] |
c34b1796 | 18 | |
dfeec247 | 19 | use back::write::{create_informational_target_machine, create_target_machine}; |
5bcae85e | 20 | |
dfeec247 | 21 | pub use llvm_util::target_features; |
74b04a01 | 22 | use rustc_ast::expand::allocator::AllocatorKind; |
dfeec247 | 23 | use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule}; |
fc512014 XL |
24 | use rustc_codegen_ssa::back::write::{ |
25 | CodegenContext, FatLTOInput, ModuleConfig, TargetMachineFactoryConfig, TargetMachineFactoryFn, | |
26 | }; | |
a1dfa0c6 | 27 | use rustc_codegen_ssa::traits::*; |
ba9703b0 | 28 | use rustc_codegen_ssa::ModuleCodegen; |
74b04a01 | 29 | use rustc_codegen_ssa::{CodegenResults, CompiledModule}; |
29967ef6 | 30 | use rustc_data_structures::fx::FxHashMap; |
ba9703b0 | 31 | use rustc_errors::{ErrorReported, FatalError, Handler}; |
29967ef6 | 32 | use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; |
ba9703b0 XL |
33 | use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn}; |
34 | use rustc_middle::ty::{self, TyCtxt}; | |
29967ef6 | 35 | use rustc_session::config::{OptLevel, OutputFilenames, PrintRequest}; |
ba9703b0 XL |
36 | use rustc_session::Session; |
37 | use rustc_span::symbol::Symbol; | |
38 | ||
ea8adc8c | 39 | use std::any::Any; |
e1599b0c | 40 | use std::ffi::CStr; |
ea8adc8c | 41 | |
2c00a5a8 | 42 | mod back { |
48663c56 | 43 | pub mod archive; |
b7449926 | 44 | pub mod lto; |
74b04a01 | 45 | mod profiling; |
1a4d82fc | 46 | pub mod write; |
1a4d82fc JJ |
47 | } |
48 | ||
54a0048b | 49 | mod abi; |
041b39d2 | 50 | mod allocator; |
54a0048b SL |
51 | mod asm; |
52 | mod attributes; | |
53 | mod base; | |
54a0048b | 54 | mod builder; |
54a0048b | 55 | mod callee; |
54a0048b SL |
56 | mod common; |
57 | mod consts; | |
58 | mod context; | |
f035d41b | 59 | mod coverageinfo; |
54a0048b SL |
60 | mod debuginfo; |
61 | mod declare; | |
54a0048b | 62 | mod intrinsic; |
a1dfa0c6 XL |
63 | |
64 | // The following is a work around that replaces `pub mod llvm;` and that fixes issue 53912. | |
dfeec247 XL |
65 | #[path = "llvm/mod.rs"] |
66 | mod llvm_; | |
67 | pub mod llvm { | |
68 | pub use super::llvm_::*; | |
69 | } | |
a1dfa0c6 | 70 | |
7cac9316 | 71 | mod llvm_util; |
7cac9316 | 72 | mod metadata; |
94b46f34 | 73 | mod mono_item; |
54a0048b SL |
74 | mod type_; |
75 | mod type_of; | |
a1dfa0c6 | 76 | mod va_arg; |
dfeec247 | 77 | mod value; |
54a0048b | 78 | |
a1dfa0c6 | 79 | #[derive(Clone)] |
94b46f34 | 80 | pub struct LlvmCodegenBackend(()); |
ea8adc8c | 81 | |
a1dfa0c6 | 82 | impl ExtraBackendMethods for LlvmCodegenBackend { |
dc9dc135 | 83 | fn new_metadata(&self, tcx: TyCtxt<'_>, mod_name: &str) -> ModuleLlvm { |
532ac7d7 | 84 | ModuleLlvm::new_metadata(tcx, mod_name) |
a1dfa0c6 | 85 | } |
532ac7d7 | 86 | |
dc9dc135 | 87 | fn write_compressed_metadata<'tcx>( |
a1dfa0c6 | 88 | &self, |
dc9dc135 | 89 | tcx: TyCtxt<'tcx>, |
48663c56 | 90 | metadata: &EncodedMetadata, |
dc9dc135 | 91 | llvm_module: &mut ModuleLlvm, |
48663c56 XL |
92 | ) { |
93 | base::write_compressed_metadata(tcx, metadata, llvm_module) | |
a1dfa0c6 | 94 | } |
dc9dc135 | 95 | fn codegen_allocator<'tcx>( |
9fa01778 | 96 | &self, |
dc9dc135 | 97 | tcx: TyCtxt<'tcx>, |
9fa01778 | 98 | mods: &mut ModuleLlvm, |
dc9dc135 | 99 | kind: AllocatorKind, |
29967ef6 | 100 | has_alloc_error_handler: bool, |
9fa01778 | 101 | ) { |
29967ef6 | 102 | unsafe { allocator::codegen(tcx, mods, kind, has_alloc_error_handler) } |
a1dfa0c6 | 103 | } |
e74abb32 | 104 | fn compile_codegen_unit( |
dfeec247 XL |
105 | &self, |
106 | tcx: TyCtxt<'_>, | |
e74abb32 | 107 | cgu_name: Symbol, |
dfeec247 XL |
108 | ) -> (ModuleCodegen<ModuleLlvm>, u64) { |
109 | base::compile_codegen_unit(tcx, cgu_name) | |
a1dfa0c6 XL |
110 | } |
111 | fn target_machine_factory( | |
112 | &self, | |
113 | sess: &Session, | |
9fa01778 | 114 | optlvl: OptLevel, |
fc512014 | 115 | ) -> TargetMachineFactoryFn<Self> { |
f9f354fc | 116 | back::write::target_machine_factory(sess, optlvl) |
a1dfa0c6 XL |
117 | } |
118 | fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str { | |
119 | llvm_util::target_cpu(sess) | |
120 | } | |
29967ef6 XL |
121 | fn tune_cpu<'b>(&self, sess: &'b Session) -> Option<&'b str> { |
122 | llvm_util::tune_cpu(sess) | |
123 | } | |
a1dfa0c6 XL |
124 | } |
125 | ||
126 | impl WriteBackendMethods for LlvmCodegenBackend { | |
127 | type Module = ModuleLlvm; | |
128 | type ModuleBuffer = back::lto::ModuleBuffer; | |
129 | type Context = llvm::Context; | |
130 | type TargetMachine = &'static mut llvm::TargetMachine; | |
131 | type ThinData = back::lto::ThinData; | |
132 | type ThinBuffer = back::lto::ThinBuffer; | |
133 | fn print_pass_timings(&self) { | |
dfeec247 XL |
134 | unsafe { |
135 | llvm::LLVMRustPrintPassTimings(); | |
136 | } | |
a1dfa0c6 | 137 | } |
1b1a35ee XL |
138 | fn run_link( |
139 | cgcx: &CodegenContext<Self>, | |
140 | diag_handler: &Handler, | |
141 | modules: Vec<ModuleCodegen<Self::Module>>, | |
142 | ) -> Result<ModuleCodegen<Self::Module>, FatalError> { | |
143 | back::write::link(cgcx, diag_handler, modules) | |
144 | } | |
0731742a | 145 | fn run_fat_lto( |
a1dfa0c6 | 146 | cgcx: &CodegenContext<Self>, |
9fa01778 XL |
147 | modules: Vec<FatLTOInput<Self>>, |
148 | cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>, | |
0731742a | 149 | ) -> Result<LtoModuleCodegen<Self>, FatalError> { |
532ac7d7 | 150 | back::lto::run_fat(cgcx, modules, cached_modules) |
0731742a XL |
151 | } |
152 | fn run_thin_lto( | |
153 | cgcx: &CodegenContext<Self>, | |
154 | modules: Vec<(String, Self::ThinBuffer)>, | |
a1dfa0c6 | 155 | cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>, |
a1dfa0c6 | 156 | ) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> { |
532ac7d7 | 157 | back::lto::run_thin(cgcx, modules, cached_modules) |
a1dfa0c6 XL |
158 | } |
159 | unsafe fn optimize( | |
160 | cgcx: &CodegenContext<Self>, | |
161 | diag_handler: &Handler, | |
162 | module: &ModuleCodegen<Self::Module>, | |
163 | config: &ModuleConfig, | |
a1dfa0c6 | 164 | ) -> Result<(), FatalError> { |
5869c6ff | 165 | Ok(back::write::optimize(cgcx, diag_handler, module, config)) |
a1dfa0c6 XL |
166 | } |
167 | unsafe fn optimize_thin( | |
168 | cgcx: &CodegenContext<Self>, | |
169 | thin: &mut ThinModule<Self>, | |
a1dfa0c6 | 170 | ) -> Result<ModuleCodegen<Self::Module>, FatalError> { |
532ac7d7 | 171 | back::lto::optimize_thin_module(thin, cgcx) |
a1dfa0c6 XL |
172 | } |
173 | unsafe fn codegen( | |
174 | cgcx: &CodegenContext<Self>, | |
175 | diag_handler: &Handler, | |
176 | module: ModuleCodegen<Self::Module>, | |
177 | config: &ModuleConfig, | |
a1dfa0c6 | 178 | ) -> Result<CompiledModule, FatalError> { |
532ac7d7 | 179 | back::write::codegen(cgcx, diag_handler, module, config) |
a1dfa0c6 | 180 | } |
dfeec247 | 181 | fn prepare_thin(module: ModuleCodegen<Self::Module>) -> (String, Self::ThinBuffer) { |
9fa01778 XL |
182 | back::lto::prepare_thin(module) |
183 | } | |
dfeec247 | 184 | fn serialize_module(module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer) { |
9fa01778 | 185 | (module.name, back::lto::ModuleBuffer::new(module.module_llvm.llmod())) |
0731742a | 186 | } |
a1dfa0c6 XL |
187 | fn run_lto_pass_manager( |
188 | cgcx: &CodegenContext<Self>, | |
189 | module: &ModuleCodegen<Self::Module>, | |
190 | config: &ModuleConfig, | |
dfeec247 | 191 | thin: bool, |
a1dfa0c6 XL |
192 | ) { |
193 | back::lto::run_pass_manager(cgcx, module, config, thin) | |
194 | } | |
195 | } | |
196 | ||
197 | unsafe impl Send for LlvmCodegenBackend {} // Llvm is on a per-thread basis | |
198 | unsafe impl Sync for LlvmCodegenBackend {} | |
2c00a5a8 | 199 | |
94b46f34 | 200 | impl LlvmCodegenBackend { |
8faf50e0 | 201 | pub fn new() -> Box<dyn CodegenBackend> { |
74b04a01 | 202 | Box::new(LlvmCodegenBackend(())) |
ea8adc8c XL |
203 | } |
204 | } | |
205 | ||
94b46f34 | 206 | impl CodegenBackend for LlvmCodegenBackend { |
2c00a5a8 XL |
207 | fn init(&self, sess: &Session) { |
208 | llvm_util::init(sess); // Make sure llvm is inited | |
209 | } | |
210 | ||
211 | fn print(&self, req: PrintRequest, sess: &Session) { | |
212 | match req { | |
213 | PrintRequest::RelocationModels => { | |
214 | println!("Available relocation models:"); | |
f9f354fc XL |
215 | for name in |
216 | &["static", "pic", "dynamic-no-pic", "ropi", "rwpi", "ropi-rwpi", "default"] | |
217 | { | |
2c00a5a8 XL |
218 | println!(" {}", name); |
219 | } | |
e1599b0c | 220 | println!(); |
2c00a5a8 XL |
221 | } |
222 | PrintRequest::CodeModels => { | |
223 | println!("Available code models:"); | |
f9f354fc | 224 | for name in &["tiny", "small", "kernel", "medium", "large"] { |
2c00a5a8 XL |
225 | println!(" {}", name); |
226 | } | |
e1599b0c | 227 | println!(); |
2c00a5a8 XL |
228 | } |
229 | PrintRequest::TlsModels => { | |
230 | println!("Available TLS models:"); | |
f9f354fc | 231 | for name in &["global-dynamic", "local-dynamic", "initial-exec", "local-exec"] { |
2c00a5a8 XL |
232 | println!(" {}", name); |
233 | } | |
e1599b0c | 234 | println!(); |
2c00a5a8 XL |
235 | } |
236 | req => llvm_util::print(req, sess), | |
237 | } | |
238 | } | |
239 | ||
240 | fn print_passes(&self) { | |
241 | llvm_util::print_passes(); | |
242 | } | |
243 | ||
244 | fn print_version(&self) { | |
245 | llvm_util::print_version(); | |
246 | } | |
247 | ||
2c00a5a8 XL |
248 | fn target_features(&self, sess: &Session) -> Vec<Symbol> { |
249 | target_features(sess) | |
250 | } | |
ea8adc8c | 251 | |
e74abb32 | 252 | fn metadata_loader(&self) -> Box<MetadataLoaderDyn> { |
74b04a01 | 253 | Box::new(metadata::LlvmMetadataLoader) |
ea8adc8c XL |
254 | } |
255 | ||
f035d41b | 256 | fn provide(&self, providers: &mut ty::query::Providers) { |
29967ef6 | 257 | attributes::provide_both(providers); |
ea8adc8c XL |
258 | } |
259 | ||
f035d41b | 260 | fn provide_extern(&self, providers: &mut ty::query::Providers) { |
29967ef6 | 261 | attributes::provide_both(providers); |
ea8adc8c XL |
262 | } |
263 | ||
dc9dc135 | 264 | fn codegen_crate<'tcx>( |
2c00a5a8 | 265 | &self, |
dc9dc135 | 266 | tcx: TyCtxt<'tcx>, |
48663c56 XL |
267 | metadata: EncodedMetadata, |
268 | need_metadata_module: bool, | |
8faf50e0 | 269 | ) -> Box<dyn Any> { |
74b04a01 | 270 | Box::new(rustc_codegen_ssa::base::codegen_crate( |
dfeec247 XL |
271 | LlvmCodegenBackend(()), |
272 | tcx, | |
273 | metadata, | |
274 | need_metadata_module, | |
74b04a01 | 275 | )) |
ea8adc8c XL |
276 | } |
277 | ||
74b04a01 | 278 | fn join_codegen( |
2c00a5a8 | 279 | &self, |
8faf50e0 | 280 | ongoing_codegen: Box<dyn Any>, |
ea8adc8c | 281 | sess: &Session, |
29967ef6 | 282 | ) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorReported> { |
dfeec247 XL |
283 | let (codegen_results, work_products) = ongoing_codegen |
284 | .downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<LlvmCodegenBackend>>() | |
285 | .expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box<Any>") | |
286 | .join(sess); | |
ea8adc8c | 287 | |
29967ef6 XL |
288 | sess.time("llvm_dump_timing_file", || { |
289 | if sess.opts.debugging_opts.llvm_time_trace { | |
290 | llvm_util::time_trace_profiler_finish("llvm_timings.json"); | |
291 | } | |
dfeec247 | 292 | }); |
2c00a5a8 | 293 | |
29967ef6 | 294 | Ok((codegen_results, work_products)) |
74b04a01 XL |
295 | } |
296 | ||
297 | fn link( | |
298 | &self, | |
299 | sess: &Session, | |
29967ef6 | 300 | codegen_results: CodegenResults, |
74b04a01 XL |
301 | outputs: &OutputFilenames, |
302 | ) -> Result<(), ErrorReported> { | |
5869c6ff XL |
303 | use crate::back::archive::LlvmArchiveBuilder; |
304 | use rustc_codegen_ssa::back::link::link_binary; | |
305 | ||
2c00a5a8 XL |
306 | // Run the linker on any artifacts that resulted from the LLVM run. |
307 | // This should produce either a finished executable or library. | |
5869c6ff XL |
308 | let target_cpu = crate::llvm_util::target_cpu(sess); |
309 | link_binary::<LlvmArchiveBuilder<'_>>( | |
310 | sess, | |
311 | &codegen_results, | |
312 | outputs, | |
313 | &codegen_results.crate_name.as_str(), | |
314 | target_cpu, | |
315 | ); | |
2c00a5a8 | 316 | |
2c00a5a8 | 317 | Ok(()) |
ea8adc8c XL |
318 | } |
319 | } | |
320 | ||
a1dfa0c6 | 321 | pub struct ModuleLlvm { |
b7449926 XL |
322 | llcx: &'static mut llvm::Context, |
323 | llmod_raw: *const llvm::Module, | |
324 | tm: &'static mut llvm::TargetMachine, | |
54a0048b SL |
325 | } |
326 | ||
dfeec247 XL |
327 | unsafe impl Send for ModuleLlvm {} |
328 | unsafe impl Sync for ModuleLlvm {} | |
ea8adc8c | 329 | |
b7449926 | 330 | impl ModuleLlvm { |
dc9dc135 | 331 | fn new(tcx: TyCtxt<'_>, mod_name: &str) -> Self { |
b7449926 | 332 | unsafe { |
9fa01778 XL |
333 | let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names()); |
334 | let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _; | |
fc512014 | 335 | ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx, mod_name) } |
b7449926 XL |
336 | } |
337 | } | |
338 | ||
dc9dc135 | 339 | fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self { |
532ac7d7 XL |
340 | unsafe { |
341 | let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names()); | |
342 | let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _; | |
f9f354fc | 343 | ModuleLlvm { llmod_raw, llcx, tm: create_informational_target_machine(tcx.sess) } |
532ac7d7 XL |
344 | } |
345 | } | |
346 | ||
9fa01778 XL |
347 | fn parse( |
348 | cgcx: &CodegenContext<LlvmCodegenBackend>, | |
e1599b0c XL |
349 | name: &CStr, |
350 | buffer: &[u8], | |
9fa01778 XL |
351 | handler: &Handler, |
352 | ) -> Result<Self, FatalError> { | |
353 | unsafe { | |
354 | let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names); | |
e1599b0c | 355 | let llmod_raw = back::lto::parse_module(llcx, name, buffer, handler)?; |
5869c6ff | 356 | let tm_factory_config = TargetMachineFactoryConfig::new(&cgcx, name.to_str().unwrap()); |
fc512014 | 357 | let tm = match (cgcx.tm_factory)(tm_factory_config) { |
9fa01778 XL |
358 | Ok(m) => m, |
359 | Err(e) => { | |
360 | handler.struct_err(&e).emit(); | |
dfeec247 | 361 | return Err(FatalError); |
9fa01778 XL |
362 | } |
363 | }; | |
364 | ||
dfeec247 | 365 | Ok(ModuleLlvm { llmod_raw, llcx, tm }) |
9fa01778 XL |
366 | } |
367 | } | |
368 | ||
b7449926 | 369 | fn llmod(&self) -> &llvm::Module { |
dfeec247 | 370 | unsafe { &*self.llmod_raw } |
b7449926 XL |
371 | } |
372 | } | |
373 | ||
ea8adc8c XL |
374 | impl Drop for ModuleLlvm { |
375 | fn drop(&mut self) { | |
376 | unsafe { | |
b7449926 XL |
377 | llvm::LLVMContextDispose(&mut *(self.llcx as *mut _)); |
378 | llvm::LLVMRustDisposeTargetMachine(&mut *(self.tm as *mut _)); | |
ea8adc8c XL |
379 | } |
380 | } | |
381 | } |