]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_llvm/lib.rs
Account for --remap-path-prefix in save-analysis
[rust.git] / src / librustc_codegen_llvm / lib.rs
1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 //! The Rust compiler.
12 //!
13 //! # Note
14 //!
15 //! This API is completely unstable and subject to change.
16
17 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
18       html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
19       html_root_url = "https://doc.rust-lang.org/nightly/")]
20
21 #![feature(box_patterns)]
22 #![feature(box_syntax)]
23 #![feature(crate_visibility_modifier)]
24 #![feature(custom_attribute)]
25 #![feature(extern_types)]
26 #![feature(fs_read_write)]
27 #![feature(in_band_lifetimes)]
28 #![allow(unused_attributes)]
29 #![feature(libc)]
30 #![feature(quote)]
31 #![feature(range_contains)]
32 #![feature(rustc_diagnostic_macros)]
33 #![feature(slice_sort_by_cached_key)]
34 #![feature(optin_builtin_traits)]
35 #![feature(concat_idents)]
36 #![feature(link_args)]
37 #![feature(static_nobundle)]
38
39 use back::write::create_target_machine;
40 use rustc::dep_graph::WorkProduct;
41 use syntax_pos::symbol::Symbol;
42
43 #[macro_use] extern crate bitflags;
44 extern crate flate2;
45 extern crate libc;
46 #[macro_use] extern crate rustc;
47 extern crate jobserver;
48 extern crate num_cpus;
49 extern crate rustc_mir;
50 extern crate rustc_allocator;
51 extern crate rustc_apfloat;
52 extern crate rustc_target;
53 #[macro_use] extern crate rustc_data_structures;
54 extern crate rustc_demangle;
55 extern crate rustc_incremental;
56 extern crate rustc_llvm;
57 extern crate rustc_platform_intrinsics as intrinsics;
58 extern crate rustc_codegen_utils;
59
60 #[macro_use] extern crate log;
61 #[macro_use] extern crate syntax;
62 extern crate syntax_pos;
63 extern crate rustc_errors as errors;
64 extern crate serialize;
65 extern crate cc; // Used to locate MSVC
66 extern crate tempfile;
67
68 use back::bytecode::RLIB_BYTECODE_EXTENSION;
69
70 pub use llvm_util::target_features;
71
72 use std::any::Any;
73 use std::path::PathBuf;
74 use std::sync::mpsc;
75 use rustc_data_structures::sync::Lrc;
76
77 use rustc::dep_graph::DepGraph;
78 use rustc::hir::def_id::CrateNum;
79 use rustc::middle::cstore::MetadataLoader;
80 use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource};
81 use rustc::middle::lang_items::LangItem;
82 use rustc::session::{Session, CompileIncomplete};
83 use rustc::session::config::{OutputFilenames, OutputType, PrintRequest};
84 use rustc::ty::{self, TyCtxt};
85 use rustc::util::time_graph;
86 use rustc::util::nodemap::{FxHashSet, FxHashMap};
87 use rustc::util::profiling::ProfileCategory;
88 use rustc_mir::monomorphize;
89 use rustc_codegen_utils::codegen_backend::CodegenBackend;
90
91 mod diagnostics;
92
93 mod back {
94     pub use rustc_codegen_utils::symbol_names;
95     mod archive;
96     pub mod bytecode;
97     mod command;
98     pub mod linker;
99     pub mod link;
100     mod lto;
101     pub mod symbol_export;
102     pub mod write;
103     mod rpath;
104     pub mod wasm;
105 }
106
107 mod abi;
108 mod allocator;
109 mod asm;
110 mod attributes;
111 mod base;
112 mod builder;
113 mod callee;
114 mod common;
115 mod consts;
116 mod context;
117 mod debuginfo;
118 mod declare;
119 mod glue;
120 mod intrinsic;
121 pub mod llvm;
122 mod llvm_util;
123 mod metadata;
124 mod meth;
125 mod mir;
126 mod mono_item;
127 mod type_;
128 mod type_of;
129 mod value;
130
131 pub struct LlvmCodegenBackend(());
132
133 impl !Send for LlvmCodegenBackend {} // Llvm is on a per-thread basis
134 impl !Sync for LlvmCodegenBackend {}
135
136 impl LlvmCodegenBackend {
137     pub fn new() -> Box<dyn CodegenBackend> {
138         box LlvmCodegenBackend(())
139     }
140 }
141
142 impl CodegenBackend for LlvmCodegenBackend {
143     fn init(&self, sess: &Session) {
144         llvm_util::init(sess); // Make sure llvm is inited
145     }
146
147     fn print(&self, req: PrintRequest, sess: &Session) {
148         match req {
149             PrintRequest::RelocationModels => {
150                 println!("Available relocation models:");
151                 for &(name, _) in back::write::RELOC_MODEL_ARGS.iter() {
152                     println!("    {}", name);
153                 }
154                 println!("");
155             }
156             PrintRequest::CodeModels => {
157                 println!("Available code models:");
158                 for &(name, _) in back::write::CODE_GEN_MODEL_ARGS.iter(){
159                     println!("    {}", name);
160                 }
161                 println!("");
162             }
163             PrintRequest::TlsModels => {
164                 println!("Available TLS models:");
165                 for &(name, _) in back::write::TLS_MODEL_ARGS.iter(){
166                     println!("    {}", name);
167                 }
168                 println!("");
169             }
170             req => llvm_util::print(req, sess),
171         }
172     }
173
174     fn print_passes(&self) {
175         llvm_util::print_passes();
176     }
177
178     fn print_version(&self) {
179         llvm_util::print_version();
180     }
181
182     fn diagnostics(&self) -> &[(&'static str, &'static str)] {
183         &DIAGNOSTICS
184     }
185
186     fn target_features(&self, sess: &Session) -> Vec<Symbol> {
187         target_features(sess)
188     }
189
190     fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
191         box metadata::LlvmMetadataLoader
192     }
193
194     fn provide(&self, providers: &mut ty::query::Providers) {
195         back::symbol_names::provide(providers);
196         back::symbol_export::provide(providers);
197         base::provide(providers);
198         attributes::provide(providers);
199     }
200
201     fn provide_extern(&self, providers: &mut ty::query::Providers) {
202         back::symbol_export::provide_extern(providers);
203         base::provide_extern(providers);
204         attributes::provide_extern(providers);
205     }
206
207     fn codegen_crate<'a, 'tcx>(
208         &self,
209         tcx: TyCtxt<'a, 'tcx, 'tcx>,
210         rx: mpsc::Receiver<Box<dyn Any + Send>>
211     ) -> Box<dyn Any> {
212         box base::codegen_crate(tcx, rx)
213     }
214
215     fn join_codegen_and_link(
216         &self,
217         ongoing_codegen: Box<dyn Any>,
218         sess: &Session,
219         dep_graph: &DepGraph,
220         outputs: &OutputFilenames,
221     ) -> Result<(), CompileIncomplete>{
222         use rustc::util::common::time;
223         let (ongoing_codegen, work_products) =
224             ongoing_codegen.downcast::<::back::write::OngoingCodegen>()
225                 .expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box<Any>")
226                 .join(sess);
227         if sess.opts.debugging_opts.incremental_info {
228             back::write::dump_incremental_data(&ongoing_codegen);
229         }
230
231         time(sess,
232              "serialize work products",
233              move || rustc_incremental::save_work_product_index(sess, &dep_graph, work_products));
234
235         sess.compile_status()?;
236
237         if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe ||
238                                                    i == OutputType::Metadata) {
239             return Ok(());
240         }
241
242         // Run the linker on any artifacts that resulted from the LLVM run.
243         // This should produce either a finished executable or library.
244         sess.profiler(|p| p.start_activity(ProfileCategory::Linking));
245         time(sess, "linking", || {
246             back::link::link_binary(sess, &ongoing_codegen,
247                                     outputs, &ongoing_codegen.crate_name.as_str());
248         });
249         sess.profiler(|p| p.end_activity(ProfileCategory::Linking));
250
251         // Now that we won't touch anything in the incremental compilation directory
252         // any more, we can finalize it (which involves renaming it)
253         rustc_incremental::finalize_session_directory(sess, ongoing_codegen.link.crate_hash);
254
255         Ok(())
256     }
257 }
258
259 /// This is the entrypoint for a hot plugged rustc_codegen_llvm
260 #[no_mangle]
261 pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
262     LlvmCodegenBackend::new()
263 }
264
265 struct ModuleCodegen {
266     /// The name of the module. When the crate may be saved between
267     /// compilations, incremental compilation requires that name be
268     /// unique amongst **all** crates.  Therefore, it should contain
269     /// something unique to this crate (e.g., a module path) as well
270     /// as the crate name and disambiguator.
271     name: String,
272     llmod_id: String,
273     source: ModuleSource,
274     kind: ModuleKind,
275 }
276
277 #[derive(Copy, Clone, Debug, PartialEq)]
278 enum ModuleKind {
279     Regular,
280     Metadata,
281     Allocator,
282 }
283
284 impl ModuleCodegen {
285     fn llvm(&self) -> Option<&ModuleLlvm> {
286         match self.source {
287             ModuleSource::Codegened(ref llvm) => Some(llvm),
288             ModuleSource::Preexisting(_) => None,
289         }
290     }
291
292     fn into_compiled_module(self,
293                                 emit_obj: bool,
294                                 emit_bc: bool,
295                                 emit_bc_compressed: bool,
296                                 outputs: &OutputFilenames) -> CompiledModule {
297         let pre_existing = match self.source {
298             ModuleSource::Preexisting(_) => true,
299             ModuleSource::Codegened(_) => false,
300         };
301         let object = if emit_obj {
302             Some(outputs.temp_path(OutputType::Object, Some(&self.name)))
303         } else {
304             None
305         };
306         let bytecode = if emit_bc {
307             Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name)))
308         } else {
309             None
310         };
311         let bytecode_compressed = if emit_bc_compressed {
312             Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name))
313                     .with_extension(RLIB_BYTECODE_EXTENSION))
314         } else {
315             None
316         };
317
318         CompiledModule {
319             llmod_id: self.llmod_id,
320             name: self.name.clone(),
321             kind: self.kind,
322             pre_existing,
323             object,
324             bytecode,
325             bytecode_compressed,
326         }
327     }
328 }
329
330 #[derive(Debug)]
331 struct CompiledModule {
332     name: String,
333     llmod_id: String,
334     kind: ModuleKind,
335     pre_existing: bool,
336     object: Option<PathBuf>,
337     bytecode: Option<PathBuf>,
338     bytecode_compressed: Option<PathBuf>,
339 }
340
341 enum ModuleSource {
342     /// Copy the `.o` files or whatever from the incr. comp. directory.
343     Preexisting(WorkProduct),
344
345     /// Rebuild from this LLVM module.
346     Codegened(ModuleLlvm),
347 }
348
349 struct ModuleLlvm {
350     llcx: &'static mut llvm::Context,
351     llmod_raw: *const llvm::Module,
352     tm: &'static mut llvm::TargetMachine,
353 }
354
355 unsafe impl Send for ModuleLlvm { }
356 unsafe impl Sync for ModuleLlvm { }
357
358 impl ModuleLlvm {
359     fn new(sess: &Session, mod_name: &str) -> Self {
360         unsafe {
361             let llcx = llvm::LLVMRustContextCreate(sess.fewer_names());
362             let llmod_raw = context::create_module(sess, llcx, mod_name) as *const _;
363
364             ModuleLlvm {
365                 llmod_raw,
366                 llcx,
367                 tm: create_target_machine(sess, false),
368             }
369         }
370     }
371
372     fn llmod(&self) -> &llvm::Module {
373         unsafe {
374             &*self.llmod_raw
375         }
376     }
377 }
378
379 impl Drop for ModuleLlvm {
380     fn drop(&mut self) {
381         unsafe {
382             llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
383             llvm::LLVMRustDisposeTargetMachine(&mut *(self.tm as *mut _));
384         }
385     }
386 }
387
388 struct CodegenResults {
389     crate_name: Symbol,
390     modules: Vec<CompiledModule>,
391     allocator_module: Option<CompiledModule>,
392     metadata_module: CompiledModule,
393     link: rustc::middle::cstore::LinkMeta,
394     metadata: rustc::middle::cstore::EncodedMetadata,
395     windows_subsystem: Option<String>,
396     linker_info: back::linker::LinkerInfo,
397     crate_info: CrateInfo,
398 }
399
400 /// Misc info we load from metadata to persist beyond the tcx
401 struct CrateInfo {
402     panic_runtime: Option<CrateNum>,
403     compiler_builtins: Option<CrateNum>,
404     profiler_runtime: Option<CrateNum>,
405     sanitizer_runtime: Option<CrateNum>,
406     is_no_builtins: FxHashSet<CrateNum>,
407     native_libraries: FxHashMap<CrateNum, Lrc<Vec<NativeLibrary>>>,
408     crate_name: FxHashMap<CrateNum, String>,
409     used_libraries: Lrc<Vec<NativeLibrary>>,
410     link_args: Lrc<Vec<String>>,
411     used_crate_source: FxHashMap<CrateNum, Lrc<CrateSource>>,
412     used_crates_static: Vec<(CrateNum, LibSource)>,
413     used_crates_dynamic: Vec<(CrateNum, LibSource)>,
414     wasm_imports: FxHashMap<String, String>,
415     lang_item_to_crate: FxHashMap<LangItem, CrateNum>,
416     missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
417 }
418
419 __build_diagnostic_array! { librustc_codegen_llvm, DIAGNOSTICS }