]> git.lizzy.rs Git - rust.git/blob - src/lib.rs
0d545ebb9af07dc04c01a4535c05f9fa96952860
[rust.git] / src / lib.rs
1 #![feature(rustc_private, never_type, decl_macro)]
2 #![allow(intra_doc_link_resolution_failure)]
3
4 extern crate rustc;
5 extern crate rustc_allocator;
6 extern crate rustc_codegen_ssa;
7 extern crate rustc_codegen_utils;
8 extern crate rustc_data_structures;
9 extern crate rustc_fs_util;
10 extern crate rustc_incremental;
11 extern crate rustc_mir;
12 extern crate rustc_target;
13 extern crate syntax;
14
15 use std::any::Any;
16 use std::sync::mpsc;
17
18 use rustc::dep_graph::DepGraph;
19 use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
20 use rustc::session::config::OutputFilenames;
21 use rustc::ty::query::Providers;
22 use rustc::util::common::ErrorReported;
23 use rustc_codegen_utils::codegen_backend::CodegenBackend;
24
25 use cranelift::codegen::settings;
26
27 use crate::constant::ConstantCx;
28 use crate::prelude::*;
29
30 mod abi;
31 mod allocator;
32 mod analyze;
33 mod archive;
34 mod base;
35 mod common;
36 mod constant;
37 mod debuginfo;
38 mod driver;
39 mod intrinsics;
40 mod linkage;
41 mod main_shim;
42 mod metadata;
43 mod pretty_clif;
44 mod trap;
45 mod unimpl;
46 mod unsize;
47 mod vtable;
48
49 mod prelude {
50     pub use std::any::Any;
51     pub use std::collections::{HashMap, HashSet};
52     pub use std::convert::TryInto;
53
54     pub use syntax::ast::{FloatTy, IntTy, UintTy};
55     pub use syntax::source_map::{Pos, Span, DUMMY_SP};
56
57     pub use rustc::bug;
58     pub use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
59     pub use rustc::mir::{self, interpret::AllocId, mono::MonoItem, *};
60     pub use rustc::session::{
61         config::{CrateType, Lto},
62         Session,
63     };
64     pub use rustc::ty::layout::{self, Abi, LayoutOf, Scalar, Size, TyLayout, VariantIdx};
65     pub use rustc::ty::{
66         self, FnSig, Instance, InstanceDef, ParamEnv, PolyFnSig, Ty, TyCtxt,
67         TypeAndMut, TypeFoldable,
68     };
69     pub use rustc_data_structures::{
70         fx::{FxHashMap, FxHashSet},
71         indexed_vec::Idx,
72         sync::Lrc,
73     };
74     pub use rustc_mir::monomorphize::collector;
75
76     pub use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
77     pub use rustc_codegen_ssa::traits::*;
78     pub use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleKind};
79
80     pub use cranelift::codegen::ir::{
81         condcodes::IntCC, function::Function, ExternalName, FuncRef, Inst, SourceLoc, StackSlot,
82     };
83     pub use cranelift::codegen::isa::CallConv;
84     pub use cranelift::codegen::Context;
85     pub use cranelift::prelude::*;
86     pub use cranelift_module::{
87         self, Backend, DataContext, DataId, FuncId, FuncOrDataId, Linkage, Module,
88     };
89
90     pub use crate::abi::*;
91     pub use crate::base::{trans_operand, trans_place};
92     pub use crate::common::*;
93     pub use crate::debuginfo::{DebugContext, FunctionDebugContext};
94     pub use crate::trap::*;
95     pub use crate::unimpl::{unimpl, with_unimpl_span};
96     pub use crate::{Caches, CodegenCx};
97
98     pub struct PrintOnPanic<F: Fn() -> String>(pub F);
99     impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
100         fn drop(&mut self) {
101             if ::std::thread::panicking() {
102                 println!("{}", (self.0)());
103             }
104         }
105     }
106 }
107
108 pub struct Caches<'tcx> {
109     pub context: Context,
110     pub vtables: HashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
111 }
112
113 impl<'tcx> Default for Caches<'tcx> {
114     fn default() -> Self {
115         Caches {
116             context: Context::new(),
117             vtables: HashMap::new(),
118         }
119     }
120 }
121
122 pub struct CodegenCx<'a, 'clif, 'tcx, B: Backend + 'static> {
123     tcx: TyCtxt<'a, 'tcx, 'tcx>,
124     module: &'clif mut Module<B>,
125     ccx: ConstantCx,
126     caches: Caches<'tcx>,
127     debug_context: Option<&'clif mut DebugContext<'tcx>>,
128 }
129
130 impl<'a, 'clif, 'tcx, B: Backend + 'static> CodegenCx<'a, 'clif, 'tcx, B> {
131     fn new(
132         tcx: TyCtxt<'a, 'tcx, 'tcx>,
133         module: &'clif mut Module<B>,
134         debug_context: Option<&'clif mut DebugContext<'tcx>>,
135     ) -> Self {
136         CodegenCx {
137             tcx,
138             module,
139             ccx: ConstantCx::default(),
140             caches: Caches::default(),
141             debug_context,
142         }
143     }
144
145     fn finalize(self) {
146         self.ccx.finalize(self.tcx, self.module);
147     }
148 }
149
150 struct CraneliftCodegenBackend;
151
152 impl CodegenBackend for CraneliftCodegenBackend {
153     fn init(&self, sess: &Session) {
154         for cty in sess.opts.crate_types.iter() {
155             match *cty {
156                 CrateType::Rlib | CrateType::Dylib | CrateType::Executable => {}
157                 _ => {
158                     sess.warn(&format!(
159                         "Rustc codegen cranelift doesn't support output type {}",
160                         cty
161                     ));
162                 }
163             }
164         }
165         match sess.lto() {
166             Lto::Fat | Lto::Thin | Lto::ThinLocal => {
167                 sess.warn("Rustc codegen cranelift doesn't support lto");
168             }
169             Lto::No => {}
170         }
171         if sess.opts.cg.rpath {
172             sess.err("rpath is not yet supported");
173         }
174         if sess.opts.debugging_opts.pgo_gen.enabled() {
175             sess.err("pgo is not supported");
176         }
177     }
178
179     fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
180         Box::new(crate::metadata::CraneliftMetadataLoader)
181     }
182
183     fn provide(&self, providers: &mut Providers) {
184         rustc_codegen_utils::symbol_names::provide(providers);
185         rustc_codegen_ssa::back::symbol_export::provide(providers);
186
187         providers.target_features_whitelist = |tcx, _cnum| tcx.arena.alloc(FxHashMap::default());
188     }
189     fn provide_extern(&self, providers: &mut Providers) {
190         rustc_codegen_ssa::back::symbol_export::provide_extern(providers);
191     }
192
193     fn codegen_crate<'a, 'tcx>(
194         &self,
195         tcx: TyCtxt<'a, 'tcx, 'tcx>,
196         metadata: EncodedMetadata,
197         need_metadata_module: bool,
198         _rx: mpsc::Receiver<Box<dyn Any + Send>>,
199     ) -> Box<dyn Any> {
200         driver::codegen_crate(tcx, metadata, need_metadata_module)
201     }
202
203     fn join_codegen_and_link(
204         &self,
205         res: Box<dyn Any>,
206         sess: &Session,
207         _dep_graph: &DepGraph,
208         outputs: &OutputFilenames,
209     ) -> Result<(), ErrorReported> {
210         use rustc_codegen_ssa::back::link::link_binary;
211
212         let codegen_results = *res
213             .downcast::<CodegenResults>()
214             .expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");
215
216         let target_cpu = ::target_lexicon::HOST.to_string();
217         link_binary::<crate::archive::ArArchiveBuilder<'_>>(
218             sess,
219             &codegen_results,
220             outputs,
221             &codegen_results.crate_name.as_str(),
222             &target_cpu,
223         );
224
225         Ok(())
226     }
227 }
228
229 fn target_triple(sess: &Session) -> target_lexicon::Triple {
230     let mut target = &*sess.target.target.llvm_target;
231
232     // FIXME add support for x86_64-apple-macosx10.7.0 to target-lexicon
233     if target.starts_with("x86_64-apple-macosx") {
234         target = "x86_64-apple-darwin";
235     }
236
237     target.parse().unwrap()
238 }
239
240 fn build_isa(sess: &Session) -> Box<dyn isa::TargetIsa + 'static> {
241     let mut flags_builder = settings::builder();
242     flags_builder.enable("is_pic").unwrap();
243     flags_builder.set("probestack_enabled", "false").unwrap(); // ___cranelift_probestack is not provided
244         flags_builder.set("enable_verifier", if cfg!(debug_assertions) {
245         "true"
246     } else {
247         "false"
248     }).unwrap();
249
250     // FIXME enable again when https://github.com/CraneStation/cranelift/issues/664 is fixed
251     /*
252     use rustc::session::config::OptLevel;
253     match sess.opts.optimize {
254         OptLevel::No => {
255             flags_builder.set("opt_level", "fastest").unwrap();
256         }
257         OptLevel::Less | OptLevel::Default => {}
258         OptLevel::Aggressive => {
259             flags_builder.set("opt_level", "best").unwrap();
260         }
261         OptLevel::Size | OptLevel::SizeMin => {
262             sess.warn("Optimizing for size is not supported. Just ignoring the request");
263         }
264     }*/
265
266     let target_triple = target_triple(sess);
267     let flags = settings::Flags::new(flags_builder);
268     cranelift::codegen::isa::lookup(target_triple)
269         .unwrap()
270         .finish(flags)
271 }
272
273 /// This is the entrypoint for a hot plugged rustc_codegen_cranelift
274 #[no_mangle]
275 pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
276     Box::new(CraneliftCodegenBackend)
277 }