]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_llvm/lib.rs
Added definition of type trait
[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(in_band_lifetimes)]
27 #![allow(unused_attributes)]
28 #![feature(libc)]
29 #![feature(nll)]
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 extern crate rustc_fs_util;
60
61 #[macro_use] extern crate log;
62 #[macro_use] extern crate syntax;
63 extern crate syntax_pos;
64 extern crate rustc_errors as errors;
65 extern crate serialize;
66 extern crate cc; // Used to locate MSVC
67 extern crate tempfile;
68 extern crate memmap;
69
70 use back::bytecode::RLIB_BYTECODE_EXTENSION;
71 use interfaces::{Backend, CommonWriteMethods};
72 use value::Value;
73 use type_::Type;
74
75 pub use llvm_util::target_features;
76 use std::any::Any;
77 use std::sync::mpsc;
78 use std::marker::PhantomData;
79 use rustc_data_structures::sync::Lrc;
80
81 use rustc::dep_graph::DepGraph;
82 use rustc::hir::def_id::CrateNum;
83 use rustc::middle::cstore::MetadataLoader;
84 use rustc::middle::cstore::{NativeLibrary, CrateSource, LibSource};
85 use rustc::middle::lang_items::LangItem;
86 use rustc::session::{Session, CompileIncomplete};
87 use rustc::session::config::{OutputFilenames, OutputType, PrintRequest};
88 use rustc::ty::{self, TyCtxt};
89 use rustc::util::time_graph;
90 use rustc::util::nodemap::{FxHashSet, FxHashMap};
91 use rustc::util::profiling::ProfileCategory;
92 use rustc_mir::monomorphize;
93 use rustc_codegen_utils::{CompiledModule, ModuleKind};
94 use rustc_codegen_utils::codegen_backend::CodegenBackend;
95 use rustc_data_structures::svh::Svh;
96
97 mod diagnostics;
98
99 mod back {
100     mod archive;
101     pub mod bytecode;
102     pub mod link;
103     pub mod lto;
104     pub mod write;
105     mod rpath;
106     pub mod wasm;
107 }
108
109 mod interfaces;
110
111 mod abi;
112 mod allocator;
113 mod asm;
114 mod attributes;
115 mod base;
116 mod builder;
117 mod callee;
118 mod common;
119 mod consts;
120 mod context;
121 mod debuginfo;
122 mod declare;
123 mod glue;
124 mod intrinsic;
125
126 // The following is a work around that replaces `pub mod llvm;` and that fixes issue 53912.
127 #[path = "llvm/mod.rs"] mod llvm_; pub mod llvm { pub use super::llvm_::*; }
128
129 mod llvm_util;
130 mod metadata;
131 mod meth;
132 mod mir;
133 mod mono_item;
134 mod type_;
135 mod type_of;
136 mod value;
137
138 pub struct LlvmCodegenBackend(());
139
140 impl !Send for LlvmCodegenBackend {} // Llvm is on a per-thread basis
141 impl !Sync for LlvmCodegenBackend {}
142
143 impl LlvmCodegenBackend {
144     pub fn new() -> Box<dyn CodegenBackend> {
145         box LlvmCodegenBackend(())
146     }
147 }
148
149 impl CodegenBackend for LlvmCodegenBackend {
150     fn init(&self, sess: &Session) {
151         llvm_util::init(sess); // Make sure llvm is inited
152     }
153
154     fn print(&self, req: PrintRequest, sess: &Session) {
155         match req {
156             PrintRequest::RelocationModels => {
157                 println!("Available relocation models:");
158                 for &(name, _) in back::write::RELOC_MODEL_ARGS.iter() {
159                     println!("    {}", name);
160                 }
161                 println!("");
162             }
163             PrintRequest::CodeModels => {
164                 println!("Available code models:");
165                 for &(name, _) in back::write::CODE_GEN_MODEL_ARGS.iter(){
166                     println!("    {}", name);
167                 }
168                 println!("");
169             }
170             PrintRequest::TlsModels => {
171                 println!("Available TLS models:");
172                 for &(name, _) in back::write::TLS_MODEL_ARGS.iter(){
173                     println!("    {}", name);
174                 }
175                 println!("");
176             }
177             req => llvm_util::print(req, sess),
178         }
179     }
180
181     fn print_passes(&self) {
182         llvm_util::print_passes();
183     }
184
185     fn print_version(&self) {
186         llvm_util::print_version();
187     }
188
189     fn diagnostics(&self) -> &[(&'static str, &'static str)] {
190         &DIAGNOSTICS
191     }
192
193     fn target_features(&self, sess: &Session) -> Vec<Symbol> {
194         target_features(sess)
195     }
196
197     fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
198         box metadata::LlvmMetadataLoader
199     }
200
201     fn provide(&self, providers: &mut ty::query::Providers) {
202         rustc_codegen_utils::symbol_export::provide(providers);
203         rustc_codegen_utils::symbol_names::provide(providers);
204         base::provide_both(providers);
205         attributes::provide(providers);
206     }
207
208     fn provide_extern(&self, providers: &mut ty::query::Providers) {
209         rustc_codegen_utils::symbol_export::provide_extern(providers);
210         base::provide_both(providers);
211         attributes::provide_extern(providers);
212     }
213
214     fn codegen_crate<'a, 'tcx>(
215         &self,
216         tcx: TyCtxt<'a, 'tcx, 'tcx>,
217         rx: mpsc::Receiver<Box<dyn Any + Send>>
218     ) -> Box<dyn Any> {
219         box base::codegen_crate(tcx, rx)
220     }
221
222     fn join_codegen_and_link(
223         &self,
224         ongoing_codegen: Box<dyn Any>,
225         sess: &Session,
226         dep_graph: &DepGraph,
227         outputs: &OutputFilenames,
228     ) -> Result<(), CompileIncomplete>{
229         use rustc::util::common::time;
230         let (ongoing_codegen, work_products) =
231             ongoing_codegen.downcast::<::back::write::OngoingCodegen>()
232                 .expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box<Any>")
233                 .join(sess);
234         if sess.opts.debugging_opts.incremental_info {
235             back::write::dump_incremental_data(&ongoing_codegen);
236         }
237
238         time(sess,
239              "serialize work products",
240              move || rustc_incremental::save_work_product_index(sess, &dep_graph, work_products));
241
242         sess.compile_status()?;
243
244         if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe ||
245                                                    i == OutputType::Metadata) {
246             return Ok(());
247         }
248
249         // Run the linker on any artifacts that resulted from the LLVM run.
250         // This should produce either a finished executable or library.
251         sess.profiler(|p| p.start_activity(ProfileCategory::Linking));
252         time(sess, "linking", || {
253             back::link::link_binary(sess, &ongoing_codegen,
254                                     outputs, &ongoing_codegen.crate_name.as_str());
255         });
256         sess.profiler(|p| p.end_activity(ProfileCategory::Linking));
257
258         // Now that we won't touch anything in the incremental compilation directory
259         // any more, we can finalize it (which involves renaming it)
260         rustc_incremental::finalize_session_directory(sess, ongoing_codegen.crate_hash);
261
262         Ok(())
263     }
264 }
265
266 /// This is the entrypoint for a hot plugged rustc_codegen_llvm
267 #[no_mangle]
268 pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
269     LlvmCodegenBackend::new()
270 }
271
272 struct ModuleCodegen {
273     /// The name of the module. When the crate may be saved between
274     /// compilations, incremental compilation requires that name be
275     /// unique amongst **all** crates.  Therefore, it should contain
276     /// something unique to this crate (e.g., a module path) as well
277     /// as the crate name and disambiguator.
278     /// We currently generate these names via CodegenUnit::build_cgu_name().
279     name: String,
280     module_llvm: ModuleLlvm<'static>,
281     kind: ModuleKind,
282 }
283
284 struct CachedModuleCodegen {
285     name: String,
286     source: WorkProduct,
287 }
288
289 impl ModuleCodegen {
290     fn into_compiled_module(self,
291                             emit_obj: bool,
292                             emit_bc: bool,
293                             emit_bc_compressed: bool,
294                             outputs: &OutputFilenames) -> CompiledModule {
295         let object = if emit_obj {
296             Some(outputs.temp_path(OutputType::Object, Some(&self.name)))
297         } else {
298             None
299         };
300         let bytecode = if emit_bc {
301             Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name)))
302         } else {
303             None
304         };
305         let bytecode_compressed = if emit_bc_compressed {
306             Some(outputs.temp_path(OutputType::Bitcode, Some(&self.name))
307                         .with_extension(RLIB_BYTECODE_EXTENSION))
308         } else {
309             None
310         };
311
312         CompiledModule {
313             name: self.name.clone(),
314             kind: self.kind,
315             object,
316             bytecode,
317             bytecode_compressed,
318         }
319     }
320 }
321
322 struct ModuleLlvm<'ll> {
323     llcx: &'static mut llvm::Context,
324     llmod_raw: *const llvm::Module,
325     tm: &'static mut llvm::TargetMachine,
326     phantom: PhantomData<&'ll ()>
327 }
328
329 impl<'ll> Backend for ModuleLlvm<'ll> {
330     type Value = &'ll Value;
331     type BasicBlock = &'ll llvm::BasicBlock;
332     type Type = &'ll Type;
333     type TypeKind = llvm::TypeKind;
334     type Context = &'ll llvm::Context;
335 }
336
337 unsafe impl Send for ModuleLlvm<'ll> { }
338 unsafe impl Sync for ModuleLlvm<'ll> { }
339
340 impl ModuleLlvm<'ll> {
341     fn new(sess: &Session, mod_name: &str) -> Self {
342         unsafe {
343             let llcx = llvm::LLVMRustContextCreate(sess.fewer_names());
344             let llmod_raw = context::create_module(sess, llcx, mod_name) as *const _;
345
346             ModuleLlvm {
347                 llmod_raw,
348                 llcx,
349                 tm: create_target_machine(sess, false),
350                 phantom: PhantomData
351             }
352         }
353     }
354
355     fn llmod(&self) -> &llvm::Module {
356         unsafe {
357             &*self.llmod_raw
358         }
359     }
360 }
361
362 impl CommonWriteMethods for ModuleLlvm<'ll> {
363     fn val_ty(&self, v: &'ll Value) -> &'ll Type {
364         common::val_ty(v)
365     }
366
367     fn c_bytes_in_context(&self, llcx: &'ll llvm::Context, bytes: &[u8]) -> &'ll Value {
368         common::c_bytes_in_context(llcx, bytes)
369     }
370
371     fn c_struct_in_context(
372         &self,
373         llcx: &'a llvm::Context,
374         elts: &[&'a Value],
375         packed: bool,
376     ) -> &'a Value {
377         common::c_struct_in_context(llcx, elts, packed)
378     }
379 }
380
381 impl Drop for ModuleLlvm<'ll> {
382     fn drop(&mut self) {
383         unsafe {
384             llvm::LLVMContextDispose(&mut *(self.llcx as *mut _));
385             llvm::LLVMRustDisposeTargetMachine(&mut *(self.tm as *mut _));
386         }
387     }
388 }
389
390 struct CodegenResults {
391     crate_name: Symbol,
392     modules: Vec<CompiledModule>,
393     allocator_module: Option<CompiledModule>,
394     metadata_module: CompiledModule,
395     crate_hash: Svh,
396     metadata: rustc::middle::cstore::EncodedMetadata,
397     windows_subsystem: Option<String>,
398     linker_info: rustc_codegen_utils::linker::LinkerInfo,
399     crate_info: CrateInfo,
400 }
401
402 /// Misc info we load from metadata to persist beyond the tcx
403 struct CrateInfo {
404     panic_runtime: Option<CrateNum>,
405     compiler_builtins: Option<CrateNum>,
406     profiler_runtime: Option<CrateNum>,
407     sanitizer_runtime: Option<CrateNum>,
408     is_no_builtins: FxHashSet<CrateNum>,
409     native_libraries: FxHashMap<CrateNum, Lrc<Vec<NativeLibrary>>>,
410     crate_name: FxHashMap<CrateNum, String>,
411     used_libraries: Lrc<Vec<NativeLibrary>>,
412     link_args: Lrc<Vec<String>>,
413     used_crate_source: FxHashMap<CrateNum, Lrc<CrateSource>>,
414     used_crates_static: Vec<(CrateNum, LibSource)>,
415     used_crates_dynamic: Vec<(CrateNum, LibSource)>,
416     wasm_imports: FxHashMap<String, String>,
417     lang_item_to_crate: FxHashMap<LangItem, CrateNum>,
418     missing_lang_items: FxHashMap<CrateNum, Vec<LangItem>>,
419 }
420
421 __build_diagnostic_array! { librustc_codegen_llvm, DIAGNOSTICS }