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