]> git.lizzy.rs Git - rust.git/blob - src/lib.rs
Rustup to rustc 1.49.0-nightly (beb5ae474 2020-10-04)
[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     hash_drain_filter
9 )]
10 #![warn(rust_2018_idioms)]
11 #![warn(unused_lifetimes)]
12
13 #[cfg(feature = "jit")]
14 extern crate libc;
15 extern crate snap;
16 #[macro_use]
17 extern crate rustc_middle;
18 extern crate rustc_ast;
19 extern crate rustc_codegen_ssa;
20 extern crate rustc_data_structures;
21 extern crate rustc_errors;
22 extern crate rustc_fs_util;
23 extern crate rustc_hir;
24 extern crate rustc_incremental;
25 extern crate rustc_index;
26 extern crate rustc_mir;
27 extern crate rustc_session;
28 extern crate rustc_span;
29 extern crate rustc_symbol_mangling;
30 extern crate rustc_target;
31
32 // This prevents duplicating functions and statics that are already part of the host rustc process.
33 #[allow(unused_extern_crates)]
34 extern crate rustc_driver;
35
36 use std::any::Any;
37
38 use rustc_codegen_ssa::traits::CodegenBackend;
39 use rustc_codegen_ssa::CodegenResults;
40 use rustc_errors::ErrorReported;
41 use rustc_middle::dep_graph::{DepGraph, WorkProduct, WorkProductId};
42 use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader};
43 use rustc_middle::ty::query::Providers;
44 use rustc_session::config::OutputFilenames;
45 use rustc_session::Session;
46
47 use cranelift_codegen::settings::{self, Configurable};
48
49 use crate::constant::ConstantCx;
50 use crate::prelude::*;
51
52 mod abi;
53 mod allocator;
54 mod analyze;
55 mod archive;
56 mod atomic_shim;
57 mod backend;
58 mod base;
59 mod cast;
60 mod codegen_i128;
61 mod common;
62 mod constant;
63 mod debuginfo;
64 mod discriminant;
65 mod driver;
66 mod inline_asm;
67 mod intrinsics;
68 mod linkage;
69 mod main_shim;
70 mod metadata;
71 mod num;
72 mod optimize;
73 mod pointer;
74 mod pretty_clif;
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 #[derive(Copy, Clone, Debug)]
184 pub struct BackendConfig {
185     pub use_jit: bool,
186 }
187
188 pub struct CraneliftCodegenBackend {
189     pub config: BackendConfig,
190 }
191
192 impl CodegenBackend for CraneliftCodegenBackend {
193     fn init(&self, sess: &Session) {
194         if sess.lto() != rustc_session::config::Lto::No && sess.opts.cg.embed_bitcode {
195             sess.warn("LTO is not supported. You may get a linker error.");
196         }
197     }
198
199     fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
200         Box::new(crate::metadata::CraneliftMetadataLoader)
201     }
202
203     fn provide(&self, providers: &mut Providers) {
204         providers.supported_target_features = |tcx, cnum| {
205             assert_eq!(cnum, LOCAL_CRATE);
206             if tcx.sess.opts.actually_rustdoc {
207                 // rustdoc needs to be able to document functions that use all the features, so
208                 // whitelist them all
209                 rustc_codegen_ssa::target_features::all_known_features()
210                     .map(|(a, b)| (a.to_string(), b))
211                     .collect()
212             } else {
213                 rustc_codegen_ssa::target_features::supported_target_features(tcx.sess)
214                     .iter()
215                     .map(|&(a, b)| (a.to_string(), b))
216                     .collect()
217             }
218         };
219     }
220     fn provide_extern(&self, _providers: &mut Providers) {}
221
222     fn target_features(&self, _sess: &Session) -> Vec<rustc_span::Symbol> {
223         vec![]
224     }
225
226     fn codegen_crate<'tcx>(
227         &self,
228         tcx: TyCtxt<'tcx>,
229         metadata: EncodedMetadata,
230         need_metadata_module: bool,
231     ) -> Box<dyn Any> {
232         let res = driver::codegen_crate(tcx, metadata, need_metadata_module, self.config);
233
234         rustc_symbol_mangling::test::report_symbol_names(tcx);
235
236         res
237     }
238
239     fn join_codegen(
240         &self,
241         ongoing_codegen: Box<dyn Any>,
242         sess: &Session,
243         dep_graph: &DepGraph,
244     ) -> Result<Box<dyn Any>, ErrorReported> {
245         let (codegen_results, work_products) = *ongoing_codegen
246             .downcast::<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)>()
247             .unwrap();
248
249         sess.time("serialize_work_products", move || {
250             rustc_incremental::save_work_product_index(sess, &dep_graph, work_products)
251         });
252
253         Ok(Box::new(codegen_results))
254     }
255
256     fn link(
257         &self,
258         sess: &Session,
259         res: Box<dyn Any>,
260         outputs: &OutputFilenames,
261     ) -> Result<(), ErrorReported> {
262         use rustc_codegen_ssa::back::link::link_binary;
263
264         sess.abort_if_errors();
265
266         let codegen_results = *res
267             .downcast::<CodegenResults>()
268             .expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");
269
270         let _timer = sess.prof.generic_activity("link_crate");
271
272         sess.time("linking", || {
273             let target_cpu = crate::target_triple(sess).to_string();
274             link_binary::<crate::archive::ArArchiveBuilder<'_>>(
275                 sess,
276                 &codegen_results,
277                 outputs,
278                 &codegen_results.crate_name.as_str(),
279                 &target_cpu,
280             );
281         });
282
283         rustc_incremental::finalize_session_directory(sess, codegen_results.crate_hash);
284
285         Ok(())
286     }
287 }
288
289 fn target_triple(sess: &Session) -> target_lexicon::Triple {
290     sess.target.target.llvm_target.parse().unwrap()
291 }
292
293 fn build_isa(sess: &Session, enable_pic: bool) -> Box<dyn isa::TargetIsa + 'static> {
294     use target_lexicon::BinaryFormat;
295
296     let target_triple = crate::target_triple(sess);
297
298     let mut flags_builder = settings::builder();
299     if enable_pic {
300         flags_builder.enable("is_pic").unwrap();
301     } else {
302         flags_builder.set("is_pic", "false").unwrap();
303     }
304     flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
305     flags_builder
306         .set(
307             "enable_verifier",
308             if cfg!(debug_assertions) {
309                 "true"
310             } else {
311                 "false"
312             },
313         )
314         .unwrap();
315
316     let tls_model = match target_triple.binary_format {
317         BinaryFormat::Elf => "elf_gd",
318         BinaryFormat::Macho => "macho",
319         BinaryFormat::Coff => "coff",
320         _ => "none",
321     };
322     flags_builder.set("tls_model", tls_model).unwrap();
323
324     flags_builder.set("enable_simd", "true").unwrap();
325
326     // FIXME(CraneStation/cranelift#732) fix LICM in presence of jump tables
327     /*
328     use rustc_session::config::OptLevel;
329     match sess.opts.optimize {
330         OptLevel::No => {
331             flags_builder.set("opt_level", "none").unwrap();
332         }
333         OptLevel::Less | OptLevel::Default => {}
334         OptLevel::Aggressive => {
335             flags_builder.set("opt_level", "speed_and_size").unwrap();
336         }
337         OptLevel::Size | OptLevel::SizeMin => {
338             sess.warn("Optimizing for size is not supported. Just ignoring the request");
339         }
340     }*/
341
342     let flags = settings::Flags::new(flags_builder);
343
344     let mut isa_builder = cranelift_codegen::isa::lookup(target_triple).unwrap();
345     // Don't use "haswell", as it implies `has_lzcnt`.macOS CI is still at Ivy Bridge EP, so `lzcnt`
346     // is interpreted as `bsr`.
347     isa_builder.enable("nehalem").unwrap();
348     isa_builder.finish(flags)
349 }
350
351 /// This is the entrypoint for a hot plugged rustc_codegen_cranelift
352 #[no_mangle]
353 pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
354     Box::new(CraneliftCodegenBackend {
355         config: BackendConfig {
356             use_jit: false,
357         }
358     })
359 }