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