]> git.lizzy.rs Git - rust.git/blob - src/lib.rs
Fix dylib metadata writing
[rust.git] / src / lib.rs
1 #![feature(
2     rustc_private,
3     decl_macro,
4     type_alias_impl_trait,
5     associated_type_bounds,
6     never_type,
7     try_blocks
8 )]
9 #![warn(rust_2018_idioms)]
10 #![warn(unused_lifetimes)]
11
12 #[cfg(feature = "jit")]
13 extern crate libc;
14 extern crate snap;
15 #[macro_use]
16 extern crate rustc_middle;
17 extern crate rustc_ast;
18 extern crate rustc_codegen_ssa;
19 extern crate rustc_data_structures;
20 extern crate rustc_errors;
21 extern crate rustc_fs_util;
22 extern crate rustc_hir;
23 extern crate rustc_incremental;
24 extern crate rustc_index;
25 extern crate rustc_mir;
26 extern crate rustc_session;
27 extern crate rustc_span;
28 extern crate rustc_symbol_mangling;
29 extern crate rustc_target;
30
31 // This prevents duplicating functions and statics that are already part of the host rustc process.
32 #[allow(unused_extern_crates)]
33 extern crate rustc_driver;
34
35 use std::any::Any;
36
37 use rustc_codegen_ssa::traits::CodegenBackend;
38 use rustc_codegen_ssa::CodegenResults;
39 use rustc_errors::ErrorReported;
40 use rustc_middle::dep_graph::{DepGraph, WorkProduct, WorkProductId};
41 use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader};
42 use rustc_middle::ty::query::Providers;
43 use rustc_session::config::OutputFilenames;
44 use rustc_session::Session;
45
46 use cranelift_codegen::settings::{self, Configurable};
47
48 use crate::constant::ConstantCx;
49 use crate::prelude::*;
50
51 mod abi;
52 mod allocator;
53 mod analyze;
54 mod archive;
55 mod atomic_shim;
56 mod backend;
57 mod base;
58 mod cast;
59 mod codegen_i128;
60 mod common;
61 mod constant;
62 mod debuginfo;
63 mod discriminant;
64 mod driver;
65 mod inline_asm;
66 mod intrinsics;
67 mod linkage;
68 mod main_shim;
69 mod metadata;
70 mod num;
71 mod optimize;
72 mod pointer;
73 mod pretty_clif;
74 mod target_features_whitelist;
75 mod toolchain;
76 mod trap;
77 mod unsize;
78 mod value_and_place;
79 mod vtable;
80
81 mod prelude {
82     pub(crate) use std::convert::{TryFrom, TryInto};
83
84     pub(crate) use rustc_ast::ast::{FloatTy, IntTy, UintTy};
85     pub(crate) use rustc_span::Span;
86
87     pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE};
88     pub(crate) use rustc_middle::bug;
89     pub(crate) use rustc_middle::mir::{self, *};
90     pub(crate) use rustc_middle::ty::layout::{self, TyAndLayout};
91     pub(crate) use rustc_middle::ty::{
92         self, FnSig, Instance, InstanceDef, ParamEnv, Ty, TyCtxt, TypeAndMut, TypeFoldable,
93     };
94     pub(crate) use rustc_target::abi::{Abi, LayoutOf, Scalar, Size, VariantIdx};
95
96     pub(crate) use rustc_data_structures::fx::FxHashMap;
97
98     pub(crate) use rustc_index::vec::Idx;
99
100     pub(crate) use cranelift_codegen::entity::EntitySet;
101     pub(crate) use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
102     pub(crate) use cranelift_codegen::ir::function::Function;
103     pub(crate) use cranelift_codegen::ir::types;
104     pub(crate) use cranelift_codegen::ir::{
105         AbiParam, Block, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc,
106         StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value,
107     };
108     pub(crate) use cranelift_codegen::isa::{self, CallConv};
109     pub(crate) use cranelift_codegen::Context;
110     pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
111     pub(crate) use cranelift_module::{
112         self, Backend, DataContext, DataId, FuncId, Linkage, Module,
113     };
114
115     pub(crate) use crate::abi::*;
116     pub(crate) use crate::base::{trans_operand, trans_place};
117     pub(crate) use crate::cast::*;
118     pub(crate) use crate::common::*;
119     pub(crate) use crate::debuginfo::{DebugContext, UnwindContext};
120     pub(crate) use crate::pointer::Pointer;
121     pub(crate) use crate::trap::*;
122     pub(crate) use crate::value_and_place::{CPlace, CPlaceInner, CValue};
123 }
124
125 struct PrintOnPanic<F: Fn() -> String>(F);
126 impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
127     fn drop(&mut self) {
128         if ::std::thread::panicking() {
129             println!("{}", (self.0)());
130         }
131     }
132 }
133
134 struct CodegenCx<'tcx, B: Backend + 'static> {
135     tcx: TyCtxt<'tcx>,
136     module: Module<B>,
137     global_asm: String,
138     constants_cx: ConstantCx,
139     cached_context: Context,
140     vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
141     debug_context: Option<DebugContext<'tcx>>,
142     unwind_context: UnwindContext<'tcx>,
143 }
144
145 impl<'tcx, B: Backend + 'static> CodegenCx<'tcx, B> {
146     fn new(tcx: TyCtxt<'tcx>, module: Module<B>, debug_info: bool) -> Self {
147         let unwind_context = UnwindContext::new(tcx, module.isa());
148         let debug_context = if debug_info {
149             Some(DebugContext::new(tcx, module.isa()))
150         } else {
151             None
152         };
153         CodegenCx {
154             tcx,
155             module,
156             global_asm: String::new(),
157             constants_cx: ConstantCx::default(),
158             cached_context: Context::new(),
159             vtables: FxHashMap::default(),
160             debug_context,
161             unwind_context,
162         }
163     }
164
165     fn finalize(
166         mut self,
167     ) -> (
168         Module<B>,
169         String,
170         Option<DebugContext<'tcx>>,
171         UnwindContext<'tcx>,
172     ) {
173         self.constants_cx.finalize(self.tcx, &mut self.module);
174         (
175             self.module,
176             self.global_asm,
177             self.debug_context,
178             self.unwind_context,
179         )
180     }
181 }
182
183 struct CraneliftCodegenBackend;
184
185 impl CodegenBackend for CraneliftCodegenBackend {
186     fn init(&self, sess: &Session) {
187         if sess.lto() != rustc_session::config::Lto::No && sess.opts.cg.embed_bitcode {
188             sess.warn("LTO is not supported. You may get a linker error.");
189         }
190     }
191
192     fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
193         Box::new(crate::metadata::CraneliftMetadataLoader)
194     }
195
196     fn provide(&self, providers: &mut Providers) {
197         providers.supported_target_features = |tcx, cnum| {
198             assert_eq!(cnum, LOCAL_CRATE);
199             if tcx.sess.opts.actually_rustdoc {
200                 // rustdoc needs to be able to document functions that use all the features, so
201                 // whitelist them all
202                 target_features_whitelist::all_known_features()
203                     .map(|(a, b)| (a.to_string(), b))
204                     .collect()
205             } else {
206                 target_features_whitelist::supported_target_features(tcx.sess)
207                     .iter()
208                     .map(|&(a, b)| (a.to_string(), b))
209                     .collect()
210             }
211         };
212     }
213     fn provide_extern(&self, _providers: &mut Providers) {}
214
215     fn target_features(&self, _sess: &Session) -> Vec<rustc_span::Symbol> {
216         vec![]
217     }
218
219     fn codegen_crate<'tcx>(
220         &self,
221         tcx: TyCtxt<'tcx>,
222         metadata: EncodedMetadata,
223         need_metadata_module: bool,
224     ) -> Box<dyn Any> {
225         let res = driver::codegen_crate(tcx, metadata, need_metadata_module);
226
227         rustc_symbol_mangling::test::report_symbol_names(tcx);
228
229         res
230     }
231
232     fn join_codegen(
233         &self,
234         ongoing_codegen: Box<dyn Any>,
235         sess: &Session,
236         dep_graph: &DepGraph,
237     ) -> Result<Box<dyn Any>, ErrorReported> {
238         let (codegen_results, work_products) = *ongoing_codegen
239             .downcast::<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)>()
240             .unwrap();
241
242         sess.time("serialize_work_products", move || {
243             rustc_incremental::save_work_product_index(sess, &dep_graph, work_products)
244         });
245
246         Ok(Box::new(codegen_results))
247     }
248
249     fn link(
250         &self,
251         sess: &Session,
252         res: Box<dyn Any>,
253         outputs: &OutputFilenames,
254     ) -> Result<(), ErrorReported> {
255         use rustc_codegen_ssa::back::link::link_binary;
256
257         sess.abort_if_errors();
258
259         let codegen_results = *res
260             .downcast::<CodegenResults>()
261             .expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");
262
263         let _timer = sess.prof.generic_activity("link_crate");
264
265         sess.time("linking", || {
266             let target_cpu = crate::target_triple(sess).to_string();
267             link_binary::<crate::archive::ArArchiveBuilder<'_>>(
268                 sess,
269                 &codegen_results,
270                 outputs,
271                 &codegen_results.crate_name.as_str(),
272                 &target_cpu,
273             );
274         });
275
276         rustc_incremental::finalize_session_directory(sess, codegen_results.crate_hash);
277
278         Ok(())
279     }
280 }
281
282 fn target_triple(sess: &Session) -> target_lexicon::Triple {
283     sess.target.target.llvm_target.parse().unwrap()
284 }
285
286 fn build_isa(sess: &Session, enable_pic: bool) -> Box<dyn isa::TargetIsa + 'static> {
287     use target_lexicon::BinaryFormat;
288
289     let target_triple = crate::target_triple(sess);
290
291     let mut flags_builder = settings::builder();
292     if enable_pic {
293         flags_builder.enable("is_pic").unwrap();
294     } else {
295         flags_builder.set("is_pic", "false").unwrap();
296     }
297     flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
298     flags_builder
299         .set(
300             "enable_verifier",
301             if cfg!(debug_assertions) {
302                 "true"
303             } else {
304                 "false"
305             },
306         )
307         .unwrap();
308
309     let tls_model = match target_triple.binary_format {
310         BinaryFormat::Elf => "elf_gd",
311         BinaryFormat::Macho => "macho",
312         BinaryFormat::Coff => "coff",
313         _ => "none",
314     };
315     flags_builder.set("tls_model", tls_model).unwrap();
316
317     flags_builder.set("enable_simd", "true").unwrap();
318
319     // FIXME(CraneStation/cranelift#732) fix LICM in presence of jump tables
320     /*
321     use rustc_session::config::OptLevel;
322     match sess.opts.optimize {
323         OptLevel::No => {
324             flags_builder.set("opt_level", "none").unwrap();
325         }
326         OptLevel::Less | OptLevel::Default => {}
327         OptLevel::Aggressive => {
328             flags_builder.set("opt_level", "speed_and_size").unwrap();
329         }
330         OptLevel::Size | OptLevel::SizeMin => {
331             sess.warn("Optimizing for size is not supported. Just ignoring the request");
332         }
333     }*/
334
335     let flags = settings::Flags::new(flags_builder);
336
337     let mut isa_builder = cranelift_codegen::isa::lookup(target_triple).unwrap();
338     // Don't use "haswell", as it implies `has_lzcnt`.macOS CI is still at Ivy Bridge EP, so `lzcnt`
339     // is interpreted as `bsr`.
340     isa_builder.enable("nehalem").unwrap();
341     isa_builder.finish(flags)
342 }
343
344 /// This is the entrypoint for a hot plugged rustc_codegen_cranelift
345 #[no_mangle]
346 pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
347     Box::new(CraneliftCodegenBackend)
348 }