]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_llvm/src/lib.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / compiler / rustc_codegen_llvm / src / lib.rs
CommitLineData
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/")]
064997fb 8#![feature(hash_raw_entry)]
5e7ed085 9#![feature(let_chains)]
b7449926 10#![feature(extern_types)]
5e7ed085 11#![feature(once_cell)]
5e7ed085 12#![feature(iter_intersperse)]
dfeec247 13#![recursion_limit = "256"]
5e7ed085
FG
14#![allow(rustc::potential_query_instability)]
15
16#[macro_use]
17extern crate rustc_macros;
f2b60f7d
FG
18#[macro_use]
19extern crate tracing;
c34b1796 20
dfeec247 21use back::write::{create_informational_target_machine, create_target_machine};
5bcae85e 22
dfeec247 23pub use llvm_util::target_features;
74b04a01 24use rustc_ast::expand::allocator::AllocatorKind;
dfeec247 25use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
fc512014
XL
26use rustc_codegen_ssa::back::write::{
27 CodegenContext, FatLTOInput, ModuleConfig, TargetMachineFactoryConfig, TargetMachineFactoryFn,
28};
a1dfa0c6 29use rustc_codegen_ssa::traits::*;
ba9703b0 30use rustc_codegen_ssa::ModuleCodegen;
74b04a01 31use rustc_codegen_ssa::{CodegenResults, CompiledModule};
29967ef6 32use rustc_data_structures::fx::FxHashMap;
5e7ed085 33use rustc_errors::{ErrorGuaranteed, FatalError, Handler};
c295e0f8 34use rustc_metadata::EncodedMetadata;
29967ef6 35use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
5e7ed085 36use rustc_middle::ty::query::Providers;
17df50a5 37use rustc_middle::ty::TyCtxt;
29967ef6 38use rustc_session::config::{OptLevel, OutputFilenames, PrintRequest};
ba9703b0
XL
39use rustc_session::Session;
40use rustc_span::symbol::Symbol;
41
ea8adc8c 42use std::any::Any;
e1599b0c 43use std::ffi::CStr;
ea8adc8c 44
2c00a5a8 45mod back {
48663c56 46 pub mod archive;
b7449926 47 pub mod lto;
74b04a01 48 mod profiling;
1a4d82fc 49 pub mod write;
1a4d82fc
JJ
50}
51
54a0048b 52mod abi;
041b39d2 53mod allocator;
54a0048b
SL
54mod asm;
55mod attributes;
56mod base;
54a0048b 57mod builder;
54a0048b 58mod callee;
54a0048b
SL
59mod common;
60mod consts;
61mod context;
f035d41b 62mod coverageinfo;
54a0048b
SL
63mod debuginfo;
64mod declare;
54a0048b 65mod intrinsic;
a1dfa0c6
XL
66
67// The following is a work around that replaces `pub mod llvm;` and that fixes issue 53912.
dfeec247
XL
68#[path = "llvm/mod.rs"]
69mod llvm_;
70pub mod llvm {
71 pub use super::llvm_::*;
72}
a1dfa0c6 73
7cac9316 74mod llvm_util;
94b46f34 75mod mono_item;
54a0048b
SL
76mod type_;
77mod type_of;
a1dfa0c6 78mod va_arg;
dfeec247 79mod value;
54a0048b 80
a1dfa0c6 81#[derive(Clone)]
94b46f34 82pub struct LlvmCodegenBackend(());
ea8adc8c 83
3c0e092e
XL
84struct TimeTraceProfiler {
85 enabled: bool,
86}
87
88impl TimeTraceProfiler {
89 fn new(enabled: bool) -> Self {
90 if enabled {
91 unsafe { llvm::LLVMTimeTraceProfilerInitialize() }
92 }
93 TimeTraceProfiler { enabled }
94 }
95}
96
97impl Drop for TimeTraceProfiler {
98 fn drop(&mut self) {
99 if self.enabled {
100 unsafe { llvm::LLVMTimeTraceProfilerFinishThread() }
101 }
102 }
103}
104
a1dfa0c6 105impl ExtraBackendMethods for LlvmCodegenBackend {
dc9dc135 106 fn codegen_allocator<'tcx>(
9fa01778 107 &self,
dc9dc135 108 tcx: TyCtxt<'tcx>,
c295e0f8 109 module_name: &str,
dc9dc135 110 kind: AllocatorKind,
29967ef6 111 has_alloc_error_handler: bool,
04454e1e
FG
112 ) -> ModuleLlvm {
113 let mut module_llvm = ModuleLlvm::new_metadata(tcx, module_name);
114 unsafe {
115 allocator::codegen(tcx, &mut module_llvm, module_name, kind, has_alloc_error_handler);
116 }
117 module_llvm
a1dfa0c6 118 }
e74abb32 119 fn compile_codegen_unit(
dfeec247
XL
120 &self,
121 tcx: TyCtxt<'_>,
e74abb32 122 cgu_name: Symbol,
dfeec247
XL
123 ) -> (ModuleCodegen<ModuleLlvm>, u64) {
124 base::compile_codegen_unit(tcx, cgu_name)
a1dfa0c6
XL
125 }
126 fn target_machine_factory(
127 &self,
128 sess: &Session,
9fa01778 129 optlvl: OptLevel,
5e7ed085 130 target_features: &[String],
fc512014 131 ) -> TargetMachineFactoryFn<Self> {
5e7ed085 132 back::write::target_machine_factory(sess, optlvl, target_features)
a1dfa0c6 133 }
3c0e092e
XL
134
135 fn spawn_thread<F, T>(time_trace: bool, f: F) -> std::thread::JoinHandle<T>
136 where
137 F: FnOnce() -> T,
138 F: Send + 'static,
139 T: Send + 'static,
140 {
141 std::thread::spawn(move || {
142 let _profiler = TimeTraceProfiler::new(time_trace);
143 f()
144 })
145 }
146
147 fn spawn_named_thread<F, T>(
148 time_trace: bool,
149 name: String,
150 f: F,
151 ) -> std::io::Result<std::thread::JoinHandle<T>>
152 where
153 F: FnOnce() -> T,
154 F: Send + 'static,
155 T: Send + 'static,
156 {
157 std::thread::Builder::new().name(name).spawn(move || {
158 let _profiler = TimeTraceProfiler::new(time_trace);
159 f()
160 })
161 }
a1dfa0c6
XL
162}
163
164impl WriteBackendMethods for LlvmCodegenBackend {
165 type Module = ModuleLlvm;
166 type ModuleBuffer = back::lto::ModuleBuffer;
a1dfa0c6
XL
167 type TargetMachine = &'static mut llvm::TargetMachine;
168 type ThinData = back::lto::ThinData;
169 type ThinBuffer = back::lto::ThinBuffer;
170 fn print_pass_timings(&self) {
dfeec247
XL
171 unsafe {
172 llvm::LLVMRustPrintPassTimings();
173 }
a1dfa0c6 174 }
1b1a35ee
XL
175 fn run_link(
176 cgcx: &CodegenContext<Self>,
177 diag_handler: &Handler,
178 modules: Vec<ModuleCodegen<Self::Module>>,
179 ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
180 back::write::link(cgcx, diag_handler, modules)
181 }
0731742a 182 fn run_fat_lto(
a1dfa0c6 183 cgcx: &CodegenContext<Self>,
9fa01778
XL
184 modules: Vec<FatLTOInput<Self>>,
185 cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
0731742a 186 ) -> Result<LtoModuleCodegen<Self>, FatalError> {
532ac7d7 187 back::lto::run_fat(cgcx, modules, cached_modules)
0731742a
XL
188 }
189 fn run_thin_lto(
190 cgcx: &CodegenContext<Self>,
191 modules: Vec<(String, Self::ThinBuffer)>,
a1dfa0c6 192 cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
a1dfa0c6 193 ) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
532ac7d7 194 back::lto::run_thin(cgcx, modules, cached_modules)
a1dfa0c6
XL
195 }
196 unsafe fn optimize(
197 cgcx: &CodegenContext<Self>,
198 diag_handler: &Handler,
199 module: &ModuleCodegen<Self::Module>,
200 config: &ModuleConfig,
a1dfa0c6 201 ) -> Result<(), FatalError> {
17df50a5 202 back::write::optimize(cgcx, diag_handler, module, config)
a1dfa0c6 203 }
04454e1e
FG
204 fn optimize_fat(
205 cgcx: &CodegenContext<Self>,
206 module: &mut ModuleCodegen<Self::Module>,
207 ) -> Result<(), FatalError> {
208 let diag_handler = cgcx.create_diag_handler();
209 back::lto::run_pass_manager(cgcx, &diag_handler, module, false)
210 }
a1dfa0c6
XL
211 unsafe fn optimize_thin(
212 cgcx: &CodegenContext<Self>,
04454e1e 213 thin: ThinModule<Self>,
a1dfa0c6 214 ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
532ac7d7 215 back::lto::optimize_thin_module(thin, cgcx)
a1dfa0c6
XL
216 }
217 unsafe fn codegen(
218 cgcx: &CodegenContext<Self>,
219 diag_handler: &Handler,
220 module: ModuleCodegen<Self::Module>,
221 config: &ModuleConfig,
a1dfa0c6 222 ) -> Result<CompiledModule, FatalError> {
532ac7d7 223 back::write::codegen(cgcx, diag_handler, module, config)
a1dfa0c6 224 }
dfeec247 225 fn prepare_thin(module: ModuleCodegen<Self::Module>) -> (String, Self::ThinBuffer) {
9fa01778
XL
226 back::lto::prepare_thin(module)
227 }
dfeec247 228 fn serialize_module(module: ModuleCodegen<Self::Module>) -> (String, Self::ModuleBuffer) {
9fa01778 229 (module.name, back::lto::ModuleBuffer::new(module.module_llvm.llmod()))
0731742a 230 }
a1dfa0c6
XL
231}
232
233unsafe impl Send for LlvmCodegenBackend {} // Llvm is on a per-thread basis
234unsafe impl Sync for LlvmCodegenBackend {}
2c00a5a8 235
94b46f34 236impl LlvmCodegenBackend {
8faf50e0 237 pub fn new() -> Box<dyn CodegenBackend> {
74b04a01 238 Box::new(LlvmCodegenBackend(()))
ea8adc8c
XL
239 }
240}
241
94b46f34 242impl CodegenBackend for LlvmCodegenBackend {
2c00a5a8
XL
243 fn init(&self, sess: &Session) {
244 llvm_util::init(sess); // Make sure llvm is inited
245 }
246
5e7ed085
FG
247 fn provide(&self, providers: &mut Providers) {
248 providers.global_backend_features =
249 |tcx, ()| llvm_util::global_llvm_features(tcx.sess, true)
250 }
251
2c00a5a8
XL
252 fn print(&self, req: PrintRequest, sess: &Session) {
253 match req {
254 PrintRequest::RelocationModels => {
255 println!("Available relocation models:");
c295e0f8
XL
256 for name in &[
257 "static",
258 "pic",
259 "pie",
260 "dynamic-no-pic",
261 "ropi",
262 "rwpi",
263 "ropi-rwpi",
264 "default",
265 ] {
2c00a5a8
XL
266 println!(" {}", name);
267 }
e1599b0c 268 println!();
2c00a5a8
XL
269 }
270 PrintRequest::CodeModels => {
271 println!("Available code models:");
f9f354fc 272 for name in &["tiny", "small", "kernel", "medium", "large"] {
2c00a5a8
XL
273 println!(" {}", name);
274 }
e1599b0c 275 println!();
2c00a5a8
XL
276 }
277 PrintRequest::TlsModels => {
278 println!("Available TLS models:");
f9f354fc 279 for name in &["global-dynamic", "local-dynamic", "initial-exec", "local-exec"] {
2c00a5a8
XL
280 println!(" {}", name);
281 }
e1599b0c 282 println!();
2c00a5a8 283 }
3c0e092e
XL
284 PrintRequest::StackProtectorStrategies => {
285 println!(
286 r#"Available stack protector strategies:
287 all
288 Generate stack canaries in all functions.
289
290 strong
291 Generate stack canaries in a function if it either:
292 - has a local variable of `[T; N]` type, regardless of `T` and `N`
293 - takes the address of a local variable.
294
295 (Note that a local variable being borrowed is not equivalent to its
296 address being taken: e.g. some borrows may be removed by optimization,
297 while by-value argument passing may be implemented with reference to a
298 local stack variable in the ABI.)
299
300 basic
923072b8
FG
301 Generate stack canaries in functions with local variables of `[T; N]`
302 type, where `T` is byte-sized and `N` >= 8.
3c0e092e
XL
303
304 none
305 Do not generate stack canaries.
306"#
307 );
308 }
2c00a5a8
XL
309 req => llvm_util::print(req, sess),
310 }
311 }
312
313 fn print_passes(&self) {
314 llvm_util::print_passes();
315 }
316
317 fn print_version(&self) {
318 llvm_util::print_version();
319 }
320
064997fb
FG
321 fn target_features(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
322 target_features(sess, allow_unstable)
2c00a5a8 323 }
ea8adc8c 324
dc9dc135 325 fn codegen_crate<'tcx>(
2c00a5a8 326 &self,
dc9dc135 327 tcx: TyCtxt<'tcx>,
48663c56
XL
328 metadata: EncodedMetadata,
329 need_metadata_module: bool,
8faf50e0 330 ) -> Box<dyn Any> {
74b04a01 331 Box::new(rustc_codegen_ssa::base::codegen_crate(
dfeec247
XL
332 LlvmCodegenBackend(()),
333 tcx,
17df50a5 334 crate::llvm_util::target_cpu(tcx.sess).to_string(),
dfeec247
XL
335 metadata,
336 need_metadata_module,
74b04a01 337 ))
ea8adc8c
XL
338 }
339
74b04a01 340 fn join_codegen(
2c00a5a8 341 &self,
8faf50e0 342 ongoing_codegen: Box<dyn Any>,
ea8adc8c 343 sess: &Session,
a2a8927a 344 outputs: &OutputFilenames,
5e7ed085 345 ) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorGuaranteed> {
dfeec247
XL
346 let (codegen_results, work_products) = ongoing_codegen
347 .downcast::<rustc_codegen_ssa::back::write::OngoingCodegen<LlvmCodegenBackend>>()
348 .expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box<Any>")
349 .join(sess);
ea8adc8c 350
29967ef6 351 sess.time("llvm_dump_timing_file", || {
064997fb 352 if sess.opts.unstable_opts.llvm_time_trace {
a2a8927a
XL
353 let file_name = outputs.with_extension("llvm_timings.json");
354 llvm_util::time_trace_profiler_finish(&file_name);
29967ef6 355 }
dfeec247 356 });
2c00a5a8 357
29967ef6 358 Ok((codegen_results, work_products))
74b04a01
XL
359 }
360
361 fn link(
362 &self,
363 sess: &Session,
29967ef6 364 codegen_results: CodegenResults,
74b04a01 365 outputs: &OutputFilenames,
5e7ed085 366 ) -> Result<(), ErrorGuaranteed> {
064997fb 367 use crate::back::archive::LlvmArchiveBuilderBuilder;
5869c6ff
XL
368 use rustc_codegen_ssa::back::link::link_binary;
369
2c00a5a8
XL
370 // Run the linker on any artifacts that resulted from the LLVM run.
371 // This should produce either a finished executable or library.
064997fb 372 link_binary(sess, &LlvmArchiveBuilderBuilder, &codegen_results, outputs)
ea8adc8c
XL
373 }
374}
375
a1dfa0c6 376pub struct ModuleLlvm {
b7449926
XL
377 llcx: &'static mut llvm::Context,
378 llmod_raw: *const llvm::Module,
379 tm: &'static mut llvm::TargetMachine,
54a0048b
SL
380}
381
dfeec247
XL
382unsafe impl Send for ModuleLlvm {}
383unsafe impl Sync for ModuleLlvm {}
ea8adc8c 384
b7449926 385impl ModuleLlvm {
dc9dc135 386 fn new(tcx: TyCtxt<'_>, mod_name: &str) -> Self {
b7449926 387 unsafe {
9fa01778
XL
388 let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
389 let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
fc512014 390 ModuleLlvm { llmod_raw, llcx, tm: create_target_machine(tcx, mod_name) }
b7449926
XL
391 }
392 }
393
dc9dc135 394 fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self {
532ac7d7
XL
395 unsafe {
396 let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
397 let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
f9f354fc 398 ModuleLlvm { llmod_raw, llcx, tm: create_informational_target_machine(tcx.sess) }
532ac7d7
XL
399 }
400 }
401
9fa01778
XL
402 fn parse(
403 cgcx: &CodegenContext<LlvmCodegenBackend>,
e1599b0c
XL
404 name: &CStr,
405 buffer: &[u8],
9fa01778
XL
406 handler: &Handler,
407 ) -> Result<Self, FatalError> {
408 unsafe {
409 let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
e1599b0c 410 let llmod_raw = back::lto::parse_module(llcx, name, buffer, handler)?;
c295e0f8 411 let tm_factory_config = TargetMachineFactoryConfig::new(cgcx, name.to_str().unwrap());
fc512014 412 let tm = match (cgcx.tm_factory)(tm_factory_config) {
9fa01778
XL
413 Ok(m) => m,
414 Err(e) => {
415 handler.struct_err(&e).emit();
dfeec247 416 return Err(FatalError);
9fa01778
XL
417 }
418 };
419
dfeec247 420 Ok(ModuleLlvm { llmod_raw, llcx, tm })
9fa01778
XL
421 }
422 }
423
b7449926 424 fn llmod(&self) -> &llvm::Module {
dfeec247 425 unsafe { &*self.llmod_raw }
b7449926
XL
426 }
427}
428
ea8adc8c
XL
429impl Drop for ModuleLlvm {
430 fn drop(&mut self) {
431 unsafe {
b7449926 432 llvm::LLVMRustDisposeTargetMachine(&mut *(self.tm as *mut _));
94222f64 433 llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
ea8adc8c
XL
434 }
435 }
436}