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