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