]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_codegen_llvm/src/lib.rs
New upstream version 1.53.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)]
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 19use back::write::{create_informational_target_machine, create_target_machine};
5bcae85e 20
dfeec247 21pub use llvm_util::target_features;
74b04a01 22use rustc_ast::expand::allocator::AllocatorKind;
dfeec247 23use rustc_codegen_ssa::back::lto::{LtoModuleCodegen, SerializedModule, ThinModule};
fc512014
XL
24use rustc_codegen_ssa::back::write::{
25 CodegenContext, FatLTOInput, ModuleConfig, TargetMachineFactoryConfig, TargetMachineFactoryFn,
26};
a1dfa0c6 27use rustc_codegen_ssa::traits::*;
ba9703b0 28use rustc_codegen_ssa::ModuleCodegen;
74b04a01 29use rustc_codegen_ssa::{CodegenResults, CompiledModule};
29967ef6 30use rustc_data_structures::fx::FxHashMap;
ba9703b0 31use rustc_errors::{ErrorReported, FatalError, Handler};
29967ef6 32use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
ba9703b0
XL
33use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
34use rustc_middle::ty::{self, TyCtxt};
29967ef6 35use rustc_session::config::{OptLevel, OutputFilenames, PrintRequest};
ba9703b0
XL
36use rustc_session::Session;
37use rustc_span::symbol::Symbol;
38
ea8adc8c 39use std::any::Any;
e1599b0c 40use std::ffi::CStr;
ea8adc8c 41
2c00a5a8 42mod 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 49mod abi;
041b39d2 50mod allocator;
54a0048b
SL
51mod asm;
52mod attributes;
53mod base;
54a0048b 54mod builder;
54a0048b 55mod callee;
54a0048b
SL
56mod common;
57mod consts;
58mod context;
f035d41b 59mod coverageinfo;
54a0048b
SL
60mod debuginfo;
61mod declare;
54a0048b 62mod 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"]
66mod llvm_;
67pub mod llvm {
68 pub use super::llvm_::*;
69}
a1dfa0c6 70
7cac9316 71mod llvm_util;
7cac9316 72mod metadata;
94b46f34 73mod mono_item;
54a0048b
SL
74mod type_;
75mod type_of;
a1dfa0c6 76mod va_arg;
dfeec247 77mod value;
54a0048b 78
a1dfa0c6 79#[derive(Clone)]
94b46f34 80pub struct LlvmCodegenBackend(());
ea8adc8c 81
a1dfa0c6 82impl 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
126impl 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
197unsafe impl Send for LlvmCodegenBackend {} // Llvm is on a per-thread basis
198unsafe impl Sync for LlvmCodegenBackend {}
2c00a5a8 199
94b46f34 200impl LlvmCodegenBackend {
8faf50e0 201 pub fn new() -> Box<dyn CodegenBackend> {
74b04a01 202 Box::new(LlvmCodegenBackend(()))
ea8adc8c
XL
203 }
204}
205
94b46f34 206impl 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 321pub 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
327unsafe impl Send for ModuleLlvm {}
328unsafe impl Sync for ModuleLlvm {}
ea8adc8c 329
b7449926 330impl 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
374impl 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}