]> git.lizzy.rs Git - rust.git/blob - src/lib.rs
Re-use cranelift_codegen::ir::Function for every function
[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
4 extern crate flate2;
5 extern crate tempfile;
6 extern crate rustc;
7 extern crate rustc_codegen_ssa;
8 extern crate rustc_codegen_utils;
9 extern crate rustc_data_structures;
10 extern crate rustc_driver;
11 extern crate rustc_fs_util;
12 extern crate rustc_incremental;
13 extern crate rustc_index;
14 extern crate rustc_mir;
15 extern crate rustc_session;
16 extern crate rustc_target;
17 extern crate syntax;
18
19 use std::any::Any;
20
21 use rustc::dep_graph::DepGraph;
22 use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
23 use rustc::session::config::OutputFilenames;
24 use rustc::ty::query::Providers;
25 use rustc::util::common::ErrorReported;
26 use rustc_codegen_utils::codegen_backend::CodegenBackend;
27
28 use cranelift_codegen::settings;
29
30 use crate::constant::ConstantCx;
31 use crate::prelude::*;
32
33 mod abi;
34 mod allocator;
35 mod analyze;
36 mod archive;
37 mod base;
38 mod backend;
39 mod cast;
40 mod codegen_i128;
41 mod common;
42 mod constant;
43 mod debuginfo;
44 mod discriminant;
45 mod driver;
46 mod intrinsics;
47 mod linkage;
48 mod main_shim;
49 mod metadata;
50 mod num;
51 mod optimize;
52 mod pointer;
53 mod pretty_clif;
54 mod target_features_whitelist;
55 mod trap;
56 mod unimpl;
57 mod unsize;
58 mod value_and_place;
59 mod vtable;
60
61 mod prelude {
62     pub use std::any::Any;
63     pub use std::collections::{HashMap, HashSet};
64     pub use std::convert::{TryFrom, TryInto};
65
66     pub use syntax::ast::{FloatTy, IntTy, UintTy};
67     pub use syntax::source_map::{Pos, Span};
68
69     pub use rustc::bug;
70     pub use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
71     pub use rustc::mir::{self, interpret::AllocId, mono::MonoItem, *};
72     pub use rustc::session::{
73         config::{CrateType, Lto},
74         Session,
75     };
76     pub use rustc::ty::layout::{self, Abi, LayoutOf, Scalar, Size, TyLayout, VariantIdx};
77     pub use rustc::ty::{
78         self, FnSig, Instance, InstanceDef, ParamEnv, PolyFnSig, Ty, TyCtxt, TypeAndMut,
79         TypeFoldable,
80     };
81
82     pub use rustc_data_structures::{
83         fx::{FxHashMap, FxHashSet},
84         sync::Lrc,
85     };
86
87     pub use rustc_index::vec::Idx;
88
89     pub use rustc_mir::monomorphize::collector;
90
91     pub use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
92     pub use rustc_codegen_ssa::traits::*;
93     pub use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleKind};
94
95     pub use cranelift_codegen::Context;
96     pub use cranelift_codegen::ir::{AbiParam, Ebb, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc, StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value};
97     pub use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
98     pub use cranelift_codegen::ir::function::Function;
99     pub use cranelift_codegen::ir::immediates::{Ieee32, Ieee64};
100     pub use cranelift_codegen::ir::types;
101     pub use cranelift_codegen::isa::{self, CallConv};
102     pub use cranelift_codegen::settings::{self, Configurable};
103     pub use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
104     pub use cranelift_module::{
105         self, Backend, DataContext, DataId, FuncId, FuncOrDataId, Linkage, Module,
106     };
107
108     pub use crate::abi::*;
109     pub use crate::base::{trans_operand, trans_place};
110     pub use crate::cast::*;
111     pub use crate::common::*;
112     pub use crate::debuginfo::{DebugContext, FunctionDebugContext};
113     pub use crate::pointer::Pointer;
114     pub use crate::trap::*;
115     pub use crate::unimpl::unimpl;
116     pub use crate::value_and_place::{CPlace, CPlaceInner, CValue};
117     pub use crate::CodegenCx;
118
119     pub struct PrintOnPanic<F: Fn() -> String>(pub F);
120     impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
121         fn drop(&mut self) {
122             if ::std::thread::panicking() {
123                 println!("{}", (self.0)());
124             }
125         }
126     }
127 }
128
129 pub struct CodegenCx<'clif, 'tcx, B: Backend + 'static> {
130     tcx: TyCtxt<'tcx>,
131     module: &'clif mut Module<B>,
132     constants_cx: ConstantCx,
133     cached_context: Context,
134     vtables: HashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
135     debug_context: Option<&'clif mut DebugContext<'tcx>>,
136 }
137
138 impl<'clif, 'tcx, B: Backend + 'static> CodegenCx<'clif, 'tcx, B> {
139     fn new(
140         tcx: TyCtxt<'tcx>,
141         module: &'clif mut Module<B>,
142         debug_context: Option<&'clif mut DebugContext<'tcx>>,
143     ) -> Self {
144         CodegenCx {
145             tcx,
146             module,
147             constants_cx: ConstantCx::default(),
148             cached_context: Context::new(),
149             vtables: HashMap::new(),
150             debug_context,
151         }
152     }
153
154     fn finalize(self) {
155         self.constants_cx.finalize(self.tcx, self.module);
156     }
157 }
158
159 struct CraneliftCodegenBackend;
160
161 impl CodegenBackend for CraneliftCodegenBackend {
162     fn init(&self, _sess: &Session) {}
163
164     fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
165         Box::new(crate::metadata::CraneliftMetadataLoader)
166     }
167
168     fn provide(&self, providers: &mut Providers) {
169         providers.target_features_whitelist = |tcx, cnum| {
170             assert_eq!(cnum, LOCAL_CRATE);
171             if tcx.sess.opts.actually_rustdoc {
172                 // rustdoc needs to be able to document functions that use all the features, so
173                 // whitelist them all
174                 tcx.arena.alloc(
175                     target_features_whitelist::all_known_features()
176                         .map(|(a, b)| (a.to_string(), b))
177                         .collect(),
178                 )
179             } else {
180                 tcx.arena.alloc(
181                     target_features_whitelist::target_feature_whitelist(tcx.sess)
182                         .iter()
183                         .map(|&(a, b)| (a.to_string(), b))
184                         .collect(),
185                 )
186             }
187         };
188     }
189     fn provide_extern(&self, _providers: &mut Providers) {}
190
191     fn codegen_crate<'tcx>(
192         &self,
193         tcx: TyCtxt<'tcx>,
194         metadata: EncodedMetadata,
195         need_metadata_module: bool,
196     ) -> Box<dyn Any> {
197         rustc_codegen_utils::check_for_rustc_errors_attr(tcx);
198
199         let res = driver::codegen_crate(tcx, metadata, need_metadata_module);
200
201         rustc_incremental::assert_module_sources::assert_module_sources(tcx);
202         rustc_codegen_utils::symbol_names_test::report_symbol_names(tcx);
203
204         res
205     }
206
207     fn join_codegen_and_link(
208         &self,
209         res: Box<dyn Any>,
210         sess: &Session,
211         _dep_graph: &DepGraph,
212         outputs: &OutputFilenames,
213     ) -> Result<(), ErrorReported> {
214         use rustc_codegen_ssa::back::link::link_binary;
215
216         let codegen_results = *res
217             .downcast::<CodegenResults>()
218             .expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");
219
220         let _timer = sess.prof.generic_activity("link_crate");
221
222         rustc::util::common::time(sess, "linking", || {
223             let target_cpu = crate::target_triple(sess).to_string();
224             link_binary::<crate::archive::ArArchiveBuilder<'_>>(
225                 sess,
226                 &codegen_results,
227                 outputs,
228                 &codegen_results.crate_name.as_str(),
229                 &target_cpu,
230             );
231         });
232
233         Ok(())
234     }
235 }
236
237 fn target_triple(sess: &Session) -> target_lexicon::Triple {
238     sess.target.target.llvm_target.parse().unwrap()
239 }
240
241 fn build_isa(sess: &Session, enable_pic: bool) -> Box<dyn isa::TargetIsa + 'static> {
242     let mut flags_builder = settings::builder();
243     if enable_pic {
244         flags_builder.enable("is_pic").unwrap();
245     } else {
246         flags_builder.set("is_pic", "false").unwrap();
247     }
248     flags_builder.set("probestack_enabled", "false").unwrap(); // __cranelift_probestack is not provided
249     flags_builder
250         .set(
251             "enable_verifier",
252             if cfg!(debug_assertions) {
253                 "true"
254             } else {
255                 "false"
256             },
257         )
258         .unwrap();
259
260     // FIXME(CraneStation/cranelift#732) fix LICM in presence of jump tables
261     /*
262     use rustc::session::config::OptLevel;
263     match sess.opts.optimize {
264         OptLevel::No => {
265             flags_builder.set("opt_level", "fastest").unwrap();
266         }
267         OptLevel::Less | OptLevel::Default => {}
268         OptLevel::Aggressive => {
269             flags_builder.set("opt_level", "best").unwrap();
270         }
271         OptLevel::Size | OptLevel::SizeMin => {
272             sess.warn("Optimizing for size is not supported. Just ignoring the request");
273         }
274     }*/
275
276     let target_triple = crate::target_triple(sess);
277     let flags = settings::Flags::new(flags_builder);
278     cranelift_codegen::isa::lookup(target_triple)
279         .unwrap()
280         .finish(flags)
281 }
282
283 /// This is the entrypoint for a hot plugged rustc_codegen_cranelift
284 #[no_mangle]
285 pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
286     Box::new(CraneliftCodegenBackend)
287 }