1 #![feature(rustc_private, never_type, decl_macro)]
2 #![allow(intra_doc_link_resolution_failure)]
6 extern crate rustc_allocator;
7 extern crate rustc_codegen_ssa;
8 extern crate rustc_codegen_utils;
9 extern crate rustc_data_structures;
10 extern crate rustc_fs_util;
11 extern crate rustc_incremental;
12 extern crate rustc_mir;
13 extern crate rustc_target;
20 use rustc::dep_graph::DepGraph;
21 use rustc::middle::cstore::MetadataLoader;
23 config::{DebugInfo, OutputFilenames, OutputType},
26 use rustc::ty::query::Providers;
27 use rustc::mir::mono::{Linkage as RLinkage, Visibility};
28 use rustc_codegen_ssa::back::linker::LinkerInfo;
29 use rustc_codegen_ssa::CrateInfo;
30 use rustc_codegen_utils::codegen_backend::CodegenBackend;
31 use rustc_codegen_utils::link::out_filename;
33 use cranelift::codegen::settings;
34 use cranelift_faerie::*;
36 use crate::constant::ConstantCx;
37 use crate::prelude::*;
59 pub use std::any::Any;
60 pub use std::collections::{HashMap, HashSet};
62 pub use syntax::ast::{FloatTy, IntTy, UintTy};
63 pub use syntax::source_map::{DUMMY_SP, Span, Pos};
66 pub use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
67 pub use rustc::mir::{self, interpret::AllocId, *};
68 pub use rustc::session::{
69 config::{CrateType, Lto},
72 pub use rustc::ty::layout::{self, Abi, LayoutOf, Scalar, Size, TyLayout, VariantIdx};
74 self, subst::Substs, FnSig, Instance, InstanceDef, ParamEnv, PolyFnSig, Ty, TyCtxt,
75 TypeAndMut, TypeFoldable,
77 pub use rustc_data_structures::{
78 fx::{FxHashMap, FxHashSet},
82 pub use rustc_mir::monomorphize::{collector, MonoItem};
84 pub use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
85 pub use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleKind};
86 pub use rustc_codegen_ssa::traits::*;
88 pub use cranelift::codegen::ir::{
89 condcodes::IntCC, function::Function, ExternalName, FuncRef, Inst, StackSlot, SourceLoc,
91 pub use cranelift::codegen::isa::CallConv;
92 pub use cranelift::codegen::Context;
93 pub use cranelift::prelude::*;
94 pub use cranelift_module::{
95 self, Backend, DataContext, DataId, FuncId, FuncOrDataId, Linkage,
98 pub use cranelift_simplejit::{SimpleJITBackend, SimpleJITBuilder};
100 pub use crate::abi::*;
101 pub use crate::base::{trans_operand, trans_place};
102 pub use crate::common::*;
103 pub use crate::debuginfo::{DebugContext, FunctionDebugContext};
104 pub use crate::trap::*;
105 pub use crate::unimpl::{unimpl, with_unimpl_span};
106 pub use crate::{Caches, CodegenCx};
109 pub struct Caches<'tcx> {
110 pub context: Context,
111 pub vtables: HashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
114 impl<'tcx> Default for Caches<'tcx> {
115 fn default() -> Self {
117 context: Context::new(),
118 vtables: HashMap::new(),
123 pub struct CodegenCx<'a, 'clif, 'tcx, B: Backend + 'static> {
124 tcx: TyCtxt<'a, 'tcx, 'tcx>,
125 module: &'clif mut Module<B>,
127 caches: Caches<'tcx>,
128 debug_context: Option<&'clif mut DebugContext<'tcx>>,
131 impl<'a, 'clif, 'tcx, B: Backend + 'static> CodegenCx<'a, 'clif, 'tcx, B> {
133 tcx: TyCtxt<'a, 'tcx, 'tcx>,
134 module: &'clif mut Module<B>,
135 debug_context: Option<&'clif mut DebugContext<'tcx>>,
140 ccx: ConstantCx::default(),
141 caches: Caches::default(),
147 self.ccx.finalize(self.tcx, self.module);
151 struct CraneliftCodegenBackend;
153 impl CodegenBackend for CraneliftCodegenBackend {
154 fn init(&self, sess: &Session) {
155 for cty in sess.opts.crate_types.iter() {
157 CrateType::Rlib | CrateType::Dylib | CrateType::Executable => {}
160 "Rustc codegen cranelift doesn't support output type {}",
167 Lto::Fat | Lto::Thin | Lto::ThinLocal => {
168 sess.warn("Rustc codegen cranelift doesn't support lto");
172 if sess.opts.cg.rpath {
173 sess.err("rpath is not yet supported");
175 if sess.opts.debugging_opts.pgo_gen.is_some() {
176 sess.err("pgo is not supported");
180 fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
181 Box::new(crate::metadata::CraneliftMetadataLoader)
184 fn provide(&self, providers: &mut Providers) {
185 rustc_codegen_utils::symbol_names::provide(providers);
186 rustc_codegen_ssa::back::symbol_export::provide(providers);
188 providers.target_features_whitelist = |_tcx, _cnum| Lrc::new(Default::default());
190 fn provide_extern(&self, providers: &mut Providers) {
191 rustc_codegen_ssa::back::symbol_export::provide_extern(providers);
194 fn codegen_crate<'a, 'tcx>(
196 tcx: TyCtxt<'a, 'tcx, 'tcx>,
197 _rx: mpsc::Receiver<Box<dyn Any + Send>>,
200 if !tcx.sess.crate_types.get().contains(&CrateType::Executable)
201 && std::env::var("SHOULD_RUN").is_ok()
204 .err("Can't JIT run non executable (SHOULD_RUN env var is set)");
207 tcx.sess.abort_if_errors();
209 let metadata = tcx.encode_metadata();
211 // TODO: move to the end of this function when compiling libcore doesn't have unimplemented stuff anymore
212 save_incremental(tcx);
213 tcx.sess.warn("Saved incremental data");
215 let mut log = if cfg!(debug_assertions) {
216 Some(File::create(concat!(env!("CARGO_MANIFEST_DIR"), "/target/out/log.txt")).unwrap())
221 if std::env::var("SHOULD_RUN").is_ok() {
222 let mut jit_module: Module<SimpleJITBackend> = Module::new(SimpleJITBuilder::new());
223 assert_eq!(pointer_ty(tcx), jit_module.target_config().pointer_type());
225 let sig = Signature {
227 AbiParam::new(jit_module.target_config().pointer_type()),
228 AbiParam::new(jit_module.target_config().pointer_type()),
230 returns: vec![AbiParam::new(
231 jit_module.target_config().pointer_type(), /*isize*/
233 call_conv: CallConv::SystemV,
235 let main_func_id = jit_module
236 .declare_function("main", Linkage::Import, &sig)
239 codegen_cgus(tcx, &mut jit_module, &mut None, &mut log);
240 crate::allocator::codegen(tcx.sess, &mut jit_module);
241 jit_module.finalize_definitions();
243 tcx.sess.abort_if_errors();
244 println!("Compiled everything");
245 println!("Rustc codegen cranelift will JIT run the executable, because the SHOULD_RUN env var is set");
247 let finalized_main: *const u8 = jit_module.get_finalized_function(main_func_id);
248 println!("🎉 Finalized everything");
250 let f: extern "C" fn(isize, *const *const u8) -> isize =
251 unsafe { ::std::mem::transmute(finalized_main) };
252 let res = f(0, 0 as *const _);
253 tcx.sess.warn(&format!("🚀 main returned {}", res));
256 ::std::process::exit(0);
258 let new_module = |name: String| {
259 let module: Module<FaerieBackend> = Module::new(
263 FaerieTrapCollection::Disabled,
264 FaerieBuilder::default_libcall_names(),
270 module.target_config().pointer_type()
275 let emit_module = |name: &str, kind: ModuleKind, mut module: Module<FaerieBackend>, debug: Option<DebugContext>| {
276 module.finalize_definitions();
277 let mut artifact = module.finish().artifact;
279 if let Some(mut debug) = debug {
280 debug.emit(&mut artifact);
284 .output_filenames(LOCAL_CRATE)
285 .temp_path(OutputType::Object, Some(name));
286 let obj = artifact.emit().unwrap();
287 std::fs::write(&tmp_file, obj).unwrap();
289 name: name.to_string(),
291 object: Some(tmp_file),
293 bytecode_compressed: None,
297 let mut faerie_module = new_module("some_file".to_string());
299 let mut debug = if tcx.sess.opts.debuginfo != DebugInfo::None {
300 let debug = DebugContext::new(tcx, faerie_module.target_config().pointer_type().bytes() as u8);
306 codegen_cgus(tcx, &mut faerie_module, &mut debug, &mut log);
308 tcx.sess.abort_if_errors();
310 let mut allocator_module = new_module("allocator_shim.o".to_string());
311 let created_alloc_shim =
312 crate::allocator::codegen(tcx.sess, &mut allocator_module);
314 return Box::new(CodegenResults {
315 crate_name: tcx.crate_name(LOCAL_CRATE),
316 modules: vec![emit_module("dummy_name", ModuleKind::Regular, faerie_module, debug)],
317 allocator_module: if created_alloc_shim {
318 Some(emit_module("allocator_shim", ModuleKind::Allocator, allocator_module, None))
322 metadata_module: CompiledModule {
323 name: "dummy_metadata".to_string(),
324 kind: ModuleKind::Metadata,
327 bytecode_compressed: None,
329 crate_hash: tcx.crate_hash(LOCAL_CRATE),
331 windows_subsystem: None, // Windows is not yet supported
332 linker_info: LinkerInfo::new(tcx),
333 crate_info: CrateInfo::new(tcx),
338 fn join_codegen_and_link(
342 _dep_graph: &DepGraph,
343 outputs: &OutputFilenames,
344 ) -> Result<(), CompileIncomplete> {
346 .downcast::<CodegenResults>()
347 .expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");
349 for &crate_type in sess.opts.crate_types.iter() {
350 let output_name = out_filename(sess, crate_type, &outputs, &res.crate_name.as_str());
352 CrateType::Rlib => link::link_rlib(sess, &res, output_name),
353 CrateType::Dylib | CrateType::Executable => {
354 link::link_natively(sess, crate_type, &res, &output_name);
356 _ => sess.fatal(&format!("Unsupported crate type: {:?}", crate_type)),
363 fn build_isa(sess: &Session) -> Box<isa::TargetIsa + 'static> {
364 use rustc::session::config::OptLevel;
366 let mut flags_builder = settings::builder();
367 flags_builder.enable("is_pic").unwrap();
368 flags_builder.set("probestack_enabled", "false").unwrap(); // ___cranelift_probestack is not provided
369 flags_builder.set("enable_verifier", if cfg!(debug_assertions) {
375 match sess.opts.optimize {
377 flags_builder.set("opt_level", "fastest").unwrap();
379 OptLevel::Less | OptLevel::Default => {}
380 OptLevel::Aggressive => {
381 flags_builder.set("opt_level", "best").unwrap();
383 OptLevel::Size | OptLevel::SizeMin => {
384 sess.warn("Optimizing for size is not supported. Just ignoring the request");
388 let flags = settings::Flags::new(flags_builder);
389 cranelift::codegen::isa::lookup(sess.target.target.llvm_target.parse().unwrap())
394 fn codegen_cgus<'a, 'tcx: 'a>(
395 tcx: TyCtxt<'a, 'tcx, 'tcx>,
396 module: &mut Module<impl Backend + 'static>,
397 debug: &mut Option<DebugContext<'tcx>>,
398 log: &mut Option<File>,
400 let (_, cgus) = tcx.collect_and_partition_mono_items(LOCAL_CRATE);
401 let mono_items = cgus
403 .map(|cgu| cgu.items().iter())
405 .map(|(&mono_item, &(linkage, vis))| (mono_item, (linkage, vis)))
406 .collect::<FxHashMap<_, (_, _)>>();
408 codegen_mono_items(tcx, module, debug.as_mut(), log, mono_items);
410 crate::main_shim::maybe_create_entry_wrapper(tcx, module);
413 fn codegen_mono_items<'a, 'tcx: 'a>(
414 tcx: TyCtxt<'a, 'tcx, 'tcx>,
415 module: &mut Module<impl Backend + 'static>,
416 debug_context: Option<&mut DebugContext<'tcx>>,
417 log: &mut Option<File>,
418 mono_items: FxHashMap<MonoItem<'tcx>, (RLinkage, Visibility)>,
420 let mut cx = CodegenCx::new(tcx, module, debug_context);
421 time("codegen mono items", move || {
422 for (mono_item, (linkage, vis)) in mono_items {
423 unimpl::try_unimpl(tcx, log, || {
424 let linkage = match (linkage, vis) {
425 (RLinkage::External, Visibility::Default) => Linkage::Export,
426 (RLinkage::Internal, Visibility::Default) => Linkage::Local,
427 // FIXME this should get external linkage, but hidden visibility,
428 // not internal linkage and default visibility
429 | (RLinkage::External, Visibility::Hidden) => Linkage::Local,
430 _ => panic!("{:?} = {:?} {:?}", mono_item, linkage, vis),
432 base::trans_mono_item(&mut cx, mono_item, linkage);
440 fn time<R>(name: &str, f: impl FnOnce() -> R) -> R {
441 println!("[{}] start", name);
442 let before = ::std::time::Instant::now();
444 let after = ::std::time::Instant::now();
445 println!("[{}] end time: {:?}", name, after - before);
449 fn save_incremental<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
450 rustc_incremental::assert_dep_graph(tcx);
451 rustc_incremental::save_dep_graph(tcx);
452 rustc_incremental::finalize_session_directory(tcx.sess, tcx.crate_hash(LOCAL_CRATE));
455 /// This is the entrypoint for a hot plugged rustc_codegen_cranelift
457 pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
458 Box::new(CraneliftCodegenBackend)