]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_llvm/lib.rs
remove unneeded deps
[rust.git] / src / librustc_codegen_llvm / lib.rs
1 //! The Rust compiler.
2 //!
3 //! # Note
4 //!
5 //! This API is completely unstable and subject to change.
6
7 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
8
9 #![feature(box_patterns)]
10 #![feature(box_syntax)]
11 #![feature(const_cstr_unchecked)]
12 #![feature(crate_visibility_modifier)]
13 #![feature(custom_attribute)]
14 #![feature(extern_types)]
15 #![feature(in_band_lifetimes)]
16 #![allow(unused_attributes)]
17 #![feature(libc)]
18 #![feature(nll)]
19 #![feature(rustc_diagnostic_macros)]
20 #![feature(optin_builtin_traits)]
21 #![feature(concat_idents)]
22 #![feature(link_args)]
23 #![feature(static_nobundle)]
24 #![feature(trusted_len)]
25 #![deny(rust_2018_idioms)]
26 #![allow(explicit_outlives_requirements)]
27
28 use back::write::{create_target_machine, create_informational_target_machine};
29 use syntax_pos::symbol::Symbol;
30
31 extern crate flate2;
32 #[macro_use] extern crate bitflags;
33 extern crate libc;
34 #[macro_use] extern crate rustc;
35 extern crate rustc_allocator;
36 extern crate rustc_target;
37 #[macro_use] extern crate rustc_data_structures;
38 extern crate rustc_incremental;
39 extern crate rustc_codegen_utils;
40 extern crate rustc_codegen_ssa;
41 extern crate rustc_fs_util;
42
43 #[macro_use] extern crate log;
44 #[macro_use] extern crate syntax;
45 extern crate syntax_pos;
46 extern crate rustc_errors as errors;
47
48 use rustc_codegen_ssa::traits::*;
49 use rustc_codegen_ssa::back::write::{CodegenContext, ModuleConfig, FatLTOInput};
50 use rustc_codegen_ssa::back::lto::{SerializedModule, LtoModuleCodegen, ThinModule};
51 use rustc_codegen_ssa::CompiledModule;
52 use errors::{FatalError, Handler};
53 use rustc::dep_graph::WorkProduct;
54 use syntax_pos::symbol::InternedString;
55 pub use llvm_util::target_features;
56 use std::any::Any;
57 use std::sync::{mpsc, Arc};
58
59 use rustc::dep_graph::DepGraph;
60 use rustc::middle::allocator::AllocatorKind;
61 use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
62 use rustc::session::Session;
63 use rustc::session::config::{OutputFilenames, OutputType, PrintRequest, OptLevel};
64 use rustc::ty::{self, TyCtxt};
65 use rustc::util::common::ErrorReported;
66 use rustc_codegen_ssa::ModuleCodegen;
67 use rustc_codegen_utils::codegen_backend::CodegenBackend;
68
69 mod error_codes;
70
71 mod back {
72     pub mod archive;
73     pub mod bytecode;
74     pub mod lto;
75     pub mod write;
76 }
77
78 mod abi;
79 mod allocator;
80 mod asm;
81 mod attributes;
82 mod base;
83 mod builder;
84 mod callee;
85 mod common;
86 mod consts;
87 mod context;
88 mod debuginfo;
89 mod declare;
90 mod intrinsic;
91
92 // The following is a work around that replaces `pub mod llvm;` and that fixes issue 53912.
93 #[path = "llvm/mod.rs"] mod llvm_; pub mod llvm { pub use super::llvm_::*; }
94
95 mod llvm_util;
96 mod metadata;
97 mod mono_item;
98 mod type_;
99 mod type_of;
100 mod value;
101 mod va_arg;
102
103 #[derive(Clone)]
104 pub struct LlvmCodegenBackend(());
105
106 impl ExtraBackendMethods for LlvmCodegenBackend {
107     fn new_metadata(&self, tcx: TyCtxt<'_, '_, '_>, mod_name: &str) -> ModuleLlvm {
108         ModuleLlvm::new_metadata(tcx, mod_name)
109     }
110
111     fn write_compressed_metadata<'b, 'gcx>(
112         &self,
113         tcx: TyCtxt<'b, 'gcx, 'gcx>,
114         metadata: &EncodedMetadata,
115         llvm_module: &mut ModuleLlvm
116     ) {
117         base::write_compressed_metadata(tcx, metadata, llvm_module)
118     }
119     fn codegen_allocator<'b, 'gcx>(
120         &self,
121         tcx: TyCtxt<'b, 'gcx, 'gcx>,
122         mods: &mut ModuleLlvm,
123         kind: AllocatorKind
124     ) {
125         unsafe { allocator::codegen(tcx, mods, kind) }
126     }
127     fn compile_codegen_unit<'a, 'tcx: 'a>(
128         &self,
129         tcx: TyCtxt<'a, 'tcx, 'tcx>,
130         cgu_name: InternedString,
131     ) {
132         base::compile_codegen_unit(tcx, cgu_name);
133     }
134     fn target_machine_factory(
135         &self,
136         sess: &Session,
137         optlvl: OptLevel,
138         find_features: bool
139     ) -> Arc<dyn Fn() ->
140         Result<&'static mut llvm::TargetMachine, String> + Send + Sync> {
141         back::write::target_machine_factory(sess, optlvl, find_features)
142     }
143     fn target_cpu<'b>(&self, sess: &'b Session) -> &'b str {
144         llvm_util::target_cpu(sess)
145     }
146 }
147
148 impl WriteBackendMethods for LlvmCodegenBackend {
149     type Module = ModuleLlvm;
150     type ModuleBuffer = back::lto::ModuleBuffer;
151     type Context = llvm::Context;
152     type TargetMachine = &'static mut llvm::TargetMachine;
153     type ThinData = back::lto::ThinData;
154     type ThinBuffer = back::lto::ThinBuffer;
155     fn print_pass_timings(&self) {
156             unsafe { llvm::LLVMRustPrintPassTimings(); }
157     }
158     fn run_fat_lto(
159         cgcx: &CodegenContext<Self>,
160         modules: Vec<FatLTOInput<Self>>,
161         cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
162     ) -> Result<LtoModuleCodegen<Self>, FatalError> {
163         back::lto::run_fat(cgcx, modules, cached_modules)
164     }
165     fn run_thin_lto(
166         cgcx: &CodegenContext<Self>,
167         modules: Vec<(String, Self::ThinBuffer)>,
168         cached_modules: Vec<(SerializedModule<Self::ModuleBuffer>, WorkProduct)>,
169     ) -> Result<(Vec<LtoModuleCodegen<Self>>, Vec<WorkProduct>), FatalError> {
170         back::lto::run_thin(cgcx, modules, cached_modules)
171     }
172     unsafe fn optimize(
173         cgcx: &CodegenContext<Self>,
174         diag_handler: &Handler,
175         module: &ModuleCodegen<Self::Module>,
176         config: &ModuleConfig,
177     ) -> Result<(), FatalError> {
178         back::write::optimize(cgcx, diag_handler, module, config)
179     }
180     unsafe fn optimize_thin(
181         cgcx: &CodegenContext<Self>,
182         thin: &mut ThinModule<Self>,
183     ) -> Result<ModuleCodegen<Self::Module>, FatalError> {
184         back::lto::optimize_thin_module(thin, cgcx)
185     }
186     unsafe fn codegen(
187         cgcx: &CodegenContext<Self>,
188         diag_handler: &Handler,
189         module: ModuleCodegen<Self::Module>,
190         config: &ModuleConfig,
191     ) -> Result<CompiledModule, FatalError> {
192         back::write::codegen(cgcx, diag_handler, module, config)
193     }
194     fn prepare_thin(
195         module: ModuleCodegen<Self::Module>
196     ) -> (String, Self::ThinBuffer) {
197         back::lto::prepare_thin(module)
198     }
199     fn serialize_module(
200         module: ModuleCodegen<Self::Module>
201     ) -> (String, Self::ModuleBuffer) {
202         (module.name, back::lto::ModuleBuffer::new(module.module_llvm.llmod()))
203     }
204     fn run_lto_pass_manager(
205         cgcx: &CodegenContext<Self>,
206         module: &ModuleCodegen<Self::Module>,
207         config: &ModuleConfig,
208         thin: bool
209     ) {
210         back::lto::run_pass_manager(cgcx, module, config, thin)
211     }
212 }
213
214 unsafe impl Send for LlvmCodegenBackend {} // Llvm is on a per-thread basis
215 unsafe impl Sync for LlvmCodegenBackend {}
216
217 impl LlvmCodegenBackend {
218     pub fn new() -> Box<dyn CodegenBackend> {
219         box LlvmCodegenBackend(())
220     }
221 }
222
223 impl CodegenBackend for LlvmCodegenBackend {
224     fn init(&self, sess: &Session) {
225         llvm_util::init(sess); // Make sure llvm is inited
226     }
227
228     fn print(&self, req: PrintRequest, sess: &Session) {
229         match req {
230             PrintRequest::RelocationModels => {
231                 println!("Available relocation models:");
232                 for &(name, _) in back::write::RELOC_MODEL_ARGS.iter() {
233                     println!("    {}", name);
234                 }
235                 println!("");
236             }
237             PrintRequest::CodeModels => {
238                 println!("Available code models:");
239                 for &(name, _) in back::write::CODE_GEN_MODEL_ARGS.iter(){
240                     println!("    {}", name);
241                 }
242                 println!("");
243             }
244             PrintRequest::TlsModels => {
245                 println!("Available TLS models:");
246                 for &(name, _) in back::write::TLS_MODEL_ARGS.iter(){
247                     println!("    {}", name);
248                 }
249                 println!("");
250             }
251             req => llvm_util::print(req, sess),
252         }
253     }
254
255     fn print_passes(&self) {
256         llvm_util::print_passes();
257     }
258
259     fn print_version(&self) {
260         llvm_util::print_version();
261     }
262
263     fn diagnostics(&self) -> &[(&'static str, &'static str)] {
264         &DIAGNOSTICS
265     }
266
267     fn target_features(&self, sess: &Session) -> Vec<Symbol> {
268         target_features(sess)
269     }
270
271     fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
272         box metadata::LlvmMetadataLoader
273     }
274
275     fn provide(&self, providers: &mut ty::query::Providers<'_>) {
276         rustc_codegen_utils::symbol_names::provide(providers);
277         rustc_codegen_ssa::back::symbol_export::provide(providers);
278         rustc_codegen_ssa::base::provide_both(providers);
279         attributes::provide(providers);
280     }
281
282     fn provide_extern(&self, providers: &mut ty::query::Providers<'_>) {
283         rustc_codegen_ssa::back::symbol_export::provide_extern(providers);
284         rustc_codegen_ssa::base::provide_both(providers);
285         attributes::provide_extern(providers);
286     }
287
288     fn codegen_crate<'b, 'tcx>(
289         &self,
290         tcx: TyCtxt<'b, 'tcx, 'tcx>,
291         metadata: EncodedMetadata,
292         need_metadata_module: bool,
293         rx: mpsc::Receiver<Box<dyn Any + Send>>
294     ) -> Box<dyn Any> {
295         box rustc_codegen_ssa::base::codegen_crate(
296             LlvmCodegenBackend(()), tcx, metadata, need_metadata_module, rx)
297     }
298
299     fn join_codegen_and_link(
300         &self,
301         ongoing_codegen: Box<dyn Any>,
302         sess: &Session,
303         dep_graph: &DepGraph,
304         outputs: &OutputFilenames,
305     ) -> Result<(), ErrorReported> {
306         use rustc::util::common::time;
307         let (codegen_results, work_products) =
308             ongoing_codegen.downcast::
309                 <rustc_codegen_ssa::back::write::OngoingCodegen<LlvmCodegenBackend>>()
310                 .expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box<Any>")
311                 .join(sess);
312         if sess.opts.debugging_opts.incremental_info {
313             rustc_codegen_ssa::back::write::dump_incremental_data(&codegen_results);
314         }
315
316         time(sess,
317              "serialize work products",
318              move || rustc_incremental::save_work_product_index(sess, &dep_graph, work_products));
319
320         sess.compile_status()?;
321
322         if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe ||
323                                                    i == OutputType::Metadata) {
324             return Ok(());
325         }
326
327         // Run the linker on any artifacts that resulted from the LLVM run.
328         // This should produce either a finished executable or library.
329         sess.profiler(|p| p.start_activity("link_crate"));
330         time(sess, "linking", || {
331             use rustc_codegen_ssa::back::link::link_binary;
332             use crate::back::archive::LlvmArchiveBuilder;
333
334             let target_cpu = crate::llvm_util::target_cpu(sess);
335             link_binary::<LlvmArchiveBuilder<'_>>(
336                 sess,
337                 &codegen_results,
338                 outputs,
339                 &codegen_results.crate_name.as_str(),
340                 target_cpu,
341             );
342         });
343         sess.profiler(|p| p.end_activity("link_crate"));
344
345         // Now that we won't touch anything in the incremental compilation directory
346         // any more, we can finalize it (which involves renaming it)
347         rustc_incremental::finalize_session_directory(sess, codegen_results.crate_hash);
348
349         Ok(())
350     }
351 }
352
353 /// This is the entrypoint for a hot plugged rustc_codegen_llvm
354 #[no_mangle]
355 pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
356     LlvmCodegenBackend::new()
357 }
358
359 pub struct ModuleLlvm {
360     llcx: &'static mut llvm::Context,
361     llmod_raw: *const llvm::Module,
362     tm: &'static mut llvm::TargetMachine,
363 }
364
365 unsafe impl Send for ModuleLlvm { }
366 unsafe impl Sync for ModuleLlvm { }
367
368 impl ModuleLlvm {
369     fn new(tcx: TyCtxt<'_, '_, '_>, mod_name: &str) -> Self {
370         unsafe {
371             let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
372             let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
373             ModuleLlvm {
374                 llmod_raw,
375                 llcx,
376                 tm: create_target_machine(tcx, false),
377             }
378         }
379     }
380
381     fn new_metadata(tcx: TyCtxt<'_, '_, '_>, mod_name: &str) -> Self {
382         unsafe {
383             let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
384             let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
385             ModuleLlvm {
386                 llmod_raw,
387                 llcx,
388                 tm: create_informational_target_machine(&tcx.sess, false),
389             }
390         }
391     }
392
393     fn parse(
394         cgcx: &CodegenContext<LlvmCodegenBackend>,
395         name: &str,
396         buffer: &back::lto::ModuleBuffer,
397         handler: &Handler,
398     ) -> Result<Self, FatalError> {
399         unsafe {
400             let llcx = llvm::LLVMRustContextCreate(cgcx.fewer_names);
401             let llmod_raw = buffer.parse(name, llcx, handler)?;
402             let tm = match (cgcx.tm_factory.0)() {
403                 Ok(m) => m,
404                 Err(e) => {
405                     handler.struct_err(&e).emit();
406                     return Err(FatalError)
407                 }
408             };
409
410             Ok(ModuleLlvm {
411                 llmod_raw,
412                 llcx,
413                 tm,
414             })
415         }
416     }
417
418     fn llmod(&self) -> &llvm::Module {
419         unsafe {
420             &*self.llmod_raw
421         }
422     }
423 }
424
425 impl Drop for ModuleLlvm {
426     fn drop(&mut self) {
427         unsafe {
428             llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
429             llvm::LLVMRustDisposeTargetMachine(&mut *(self.tm as *mut _));
430         }
431     }
432 }
433
434 __build_diagnostic_array! { librustc_codegen_llvm, DIAGNOSTICS }