]> git.lizzy.rs Git - rust.git/blobdiff - src/lib.rs
Fold `vtable_trait_upcasting_coercion_new_vptr_slot` logic into obligation processing.
[rust.git] / src / lib.rs
index 93144ae09a0486358507bee5e7b1dd533a0b98ac..4ef53663ca0d95219549c88c440ecf9a0b50522a 100644 (file)
@@ -1,12 +1,12 @@
-#![feature(rustc_private, decl_macro, type_alias_impl_trait, associated_type_bounds, never_type)]
-#![allow(intra_doc_link_resolution_failure)]
+#![feature(rustc_private, decl_macro, never_type, hash_drain_filter, vec_into_raw_parts, once_cell)]
 #![warn(rust_2018_idioms)]
 #![warn(unused_lifetimes)]
+#![warn(unreachable_pub)]
 
-extern crate flate2;
-#[cfg(feature = "jit")]
-extern crate libc;
+extern crate snap;
+#[macro_use]
 extern crate rustc_middle;
+extern crate rustc_ast;
 extern crate rustc_codegen_ssa;
 extern crate rustc_data_structures;
 extern crate rustc_errors;
 extern crate rustc_hir;
 extern crate rustc_incremental;
 extern crate rustc_index;
+extern crate rustc_interface;
+extern crate rustc_metadata;
 extern crate rustc_mir;
 extern crate rustc_session;
 extern crate rustc_span;
-extern crate rustc_symbol_mangling;
 extern crate rustc_target;
-extern crate rustc_ast;
 
 // This prevents duplicating functions and statics that are already part of the host rustc process.
 #[allow(unused_extern_crates)]
 
 use std::any::Any;
 
+use rustc_codegen_ssa::traits::CodegenBackend;
+use rustc_codegen_ssa::CodegenResults;
 use rustc_errors::ErrorReported;
-use rustc_middle::dep_graph::{DepGraph, WorkProduct, WorkProductId};
-use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader};
-use rustc_session::Session;
+use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
+use rustc_middle::middle::cstore::EncodedMetadata;
 use rustc_session::config::OutputFilenames;
-use rustc_middle::ty::query::Providers;
-use rustc_codegen_ssa::CodegenResults;
-use rustc_codegen_ssa::traits::CodegenBackend;
+use rustc_session::Session;
 
+use cranelift_codegen::isa::TargetIsa;
 use cranelift_codegen::settings::{self, Configurable};
 
-use crate::constant::ConstantCx;
+pub use crate::config::*;
 use crate::prelude::*;
 
 mod abi;
 mod allocator;
 mod analyze;
 mod archive;
-mod atomic_shim;
-mod base;
 mod backend;
+mod base;
 mod cast;
 mod codegen_i128;
 mod common;
+mod compiler_builtins;
+mod config;
 mod constant;
 mod debuginfo;
 mod discriminant;
 mod driver;
+mod inline_asm;
 mod intrinsics;
 mod linkage;
 mod main_shim;
@@ -63,7 +65,7 @@
 mod optimize;
 mod pointer;
 mod pretty_clif;
-mod target_features_whitelist;
+mod toolchain;
 mod trap;
 mod unsize;
 mod value_and_place;
 mod prelude {
     pub(crate) use std::convert::{TryFrom, TryInto};
 
-    pub(crate) use rustc_ast::ast::{FloatTy, IntTy, UintTy};
     pub(crate) use rustc_span::Span;
 
-    pub(crate) use rustc_middle::bug;
     pub(crate) use rustc_hir::def_id::{DefId, LOCAL_CRATE};
+    pub(crate) use rustc_middle::bug;
     pub(crate) use rustc_middle::mir::{self, *};
     pub(crate) use rustc_middle::ty::layout::{self, TyAndLayout};
-    pub(crate) use rustc_target::abi::{Abi, LayoutOf, Scalar, Size, VariantIdx};
     pub(crate) use rustc_middle::ty::{
-        self, FnSig, Instance, InstanceDef, ParamEnv, Ty, TyCtxt, TypeAndMut, TypeFoldable,
+        self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut,
+        TypeFoldable, UintTy,
     };
+    pub(crate) use rustc_target::abi::{Abi, LayoutOf, Scalar, Size, VariantIdx};
 
     pub(crate) use rustc_data_structures::fx::FxHashMap;
 
     pub(crate) use rustc_index::vec::Idx;
 
-    pub(crate) use cranelift_codegen::Context;
-    pub(crate) use cranelift_codegen::entity::EntitySet;
-    pub(crate) use cranelift_codegen::ir::{AbiParam, Block, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc, StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value};
     pub(crate) use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
     pub(crate) use cranelift_codegen::ir::function::Function;
     pub(crate) use cranelift_codegen::ir::types;
+    pub(crate) use cranelift_codegen::ir::{
+        AbiParam, Block, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc,
+        StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value,
+    };
     pub(crate) use cranelift_codegen::isa::{self, CallConv};
+    pub(crate) use cranelift_codegen::Context;
     pub(crate) use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
-    pub(crate) use cranelift_module::{
-        self, Backend, DataContext, DataId, FuncId, Linkage, Module,
-    };
+    pub(crate) use cranelift_module::{self, DataContext, FuncId, Linkage, Module};
 
     pub(crate) use crate::abi::*;
-    pub(crate) use crate::base::{trans_operand, trans_place};
+    pub(crate) use crate::base::{codegen_operand, codegen_place};
     pub(crate) use crate::cast::*;
     pub(crate) use crate::common::*;
     pub(crate) use crate::debuginfo::{DebugContext, UnwindContext};
@@ -119,173 +121,126 @@ fn drop(&mut self) {
     }
 }
 
-struct CodegenCx<'tcx, B: Backend + 'static> {
+/// The codegen context holds any information shared between the codegen of individual functions
+/// inside a single codegen unit with the exception of the Cranelift [`Module`](cranelift_module::Module).
+struct CodegenCx<'tcx> {
     tcx: TyCtxt<'tcx>,
-    module: Module<B>,
-    constants_cx: ConstantCx,
+    global_asm: String,
     cached_context: Context,
-    vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
     debug_context: Option<DebugContext<'tcx>>,
-    unwind_context: UnwindContext<'tcx>,
+    unwind_context: UnwindContext,
 }
 
-impl<'tcx, B: Backend + 'static> CodegenCx<'tcx, B> {
+impl<'tcx> CodegenCx<'tcx> {
     fn new(
         tcx: TyCtxt<'tcx>,
-        module: Module<B>,
+        backend_config: BackendConfig,
+        isa: &dyn TargetIsa,
         debug_info: bool,
     ) -> Self {
-        let unwind_context = UnwindContext::new(tcx, module.isa());
-        let debug_context = if debug_info {
-            Some(DebugContext::new(
-                tcx,
-                module.isa(),
-            ))
-        } else {
-            None
-        };
+        assert_eq!(pointer_ty(tcx), isa.pointer_type());
+
+        let unwind_context =
+            UnwindContext::new(tcx, isa, matches!(backend_config.codegen_mode, CodegenMode::Aot));
+        let debug_context = if debug_info { Some(DebugContext::new(tcx, isa)) } else { None };
         CodegenCx {
             tcx,
-            module,
-            constants_cx: ConstantCx::default(),
+            global_asm: String::new(),
             cached_context: Context::new(),
-            vtables: FxHashMap::default(),
             debug_context,
             unwind_context,
         }
     }
-
-    fn finalize(mut self) -> (Module<B>, Option<DebugContext<'tcx>>, UnwindContext<'tcx>) {
-        self.constants_cx.finalize(self.tcx, &mut self.module);
-        (self.module, self.debug_context, self.unwind_context)
-    }
 }
 
-struct CraneliftCodegenBackend;
+pub struct CraneliftCodegenBackend {
+    pub config: Option<BackendConfig>,
+}
 
 impl CodegenBackend for CraneliftCodegenBackend {
     fn init(&self, sess: &Session) {
-        if sess.lto() != rustc_session::config::Lto::No && sess.opts.cg.embed_bitcode {
-            sess.warn("LTO is not supported. You may get a linker error.");
+        use rustc_session::config::Lto;
+        match sess.lto() {
+            Lto::No | Lto::ThinLocal => {}
+            Lto::Thin | Lto::Fat => sess.warn("LTO is not supported. You may get a linker error."),
         }
     }
 
-    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
-        Box::new(crate::metadata::CraneliftMetadataLoader)
-    }
-
-    fn provide(&self, providers: &mut Providers<'_>) {
-        providers.target_features_whitelist = |tcx, cnum| {
-            assert_eq!(cnum, LOCAL_CRATE);
-            if tcx.sess.opts.actually_rustdoc {
-                // rustdoc needs to be able to document functions that use all the features, so
-                // whitelist them all
-                target_features_whitelist::all_known_features()
-                    .chain(Some(("cg_clif", None)))
-                    .map(|(a, b)| (a.to_string(), b))
-                    .collect()
-            } else {
-                target_features_whitelist::target_feature_whitelist(tcx.sess)
-                    .iter()
-                    .chain(&Some(("cg_clif", None)))
-                    .map(|&(a, b)| (a.to_string(), b))
-                    .collect()
-            }
-        };
+    fn target_features(&self, _sess: &Session) -> Vec<rustc_span::Symbol> {
+        vec![]
     }
-    fn provide_extern(&self, _providers: &mut Providers<'_>) {}
 
-    fn target_features(&self, _sess: &Session) -> Vec<rustc_span::Symbol> {
-        vec![rustc_span::Symbol::intern("cg_clif")]
+    fn print_version(&self) {
+        println!("Cranelift version: {}", cranelift_codegen::VERSION);
     }
 
-    fn codegen_crate<'tcx>(
+    fn codegen_crate(
         &self,
-        tcx: TyCtxt<'tcx>,
+        tcx: TyCtxt<'_>,
         metadata: EncodedMetadata,
         need_metadata_module: bool,
     ) -> Box<dyn Any> {
-        let res = driver::codegen_crate(tcx, metadata, need_metadata_module);
-
-        rustc_symbol_mangling::test::report_symbol_names(tcx);
-
-        res
+        tcx.sess.abort_if_errors();
+        let config = if let Some(config) = self.config.clone() {
+            config
+        } else {
+            if !tcx.sess.unstable_options() && !tcx.sess.opts.cg.llvm_args.is_empty() {
+                tcx.sess.fatal("`-Z unstable-options` must be passed to allow configuring cg_clif");
+            }
+            BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
+                .unwrap_or_else(|err| tcx.sess.fatal(&err))
+        };
+        match config.codegen_mode {
+            CodegenMode::Aot => driver::aot::run_aot(tcx, config, metadata, need_metadata_module),
+            CodegenMode::Jit | CodegenMode::JitLazy => {
+                #[cfg(feature = "jit")]
+                let _: ! = driver::jit::run_jit(tcx, config);
+
+                #[cfg(not(feature = "jit"))]
+                tcx.sess.fatal("jit support was disabled when compiling rustc_codegen_cranelift");
+            }
+        }
     }
 
     fn join_codegen(
         &self,
         ongoing_codegen: Box<dyn Any>,
-        sess: &Session,
-        dep_graph: &DepGraph,
-    ) -> Result<Box<dyn Any>, ErrorReported> {
-        let (codegen_results, work_products) = *ongoing_codegen.downcast::<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)>().unwrap();
-
-        sess.time("serialize_work_products", move || {
-            rustc_incremental::save_work_product_index(sess, &dep_graph, work_products)
-        });
-
-        Ok(Box::new(codegen_results))
+        _sess: &Session,
+    ) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorReported> {
+        Ok(*ongoing_codegen
+            .downcast::<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)>()
+            .unwrap())
     }
 
     fn link(
         &self,
         sess: &Session,
-        res: Box<dyn Any>,
+        codegen_results: CodegenResults,
         outputs: &OutputFilenames,
     ) -> Result<(), ErrorReported> {
         use rustc_codegen_ssa::back::link::link_binary;
 
-        sess.abort_if_errors();
-
-        let codegen_results = *res
-            .downcast::<CodegenResults>()
-            .expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");
-
-        let _timer = sess.prof.generic_activity("link_crate");
-
-        sess.time("linking", || {
-            let target_cpu = crate::target_triple(sess).to_string();
-            link_binary::<crate::archive::ArArchiveBuilder<'_>>(
-                sess,
-                &codegen_results,
-                outputs,
-                &codegen_results.crate_name.as_str(),
-                &target_cpu,
-            );
-        });
-
-        rustc_incremental::finalize_session_directory(sess, codegen_results.crate_hash);
-
-        Ok(())
+        link_binary::<crate::archive::ArArchiveBuilder<'_>>(sess, &codegen_results, outputs)
     }
 }
 
 fn target_triple(sess: &Session) -> target_lexicon::Triple {
-    sess.target.target.llvm_target.parse().unwrap()
+    match sess.target.llvm_target.parse() {
+        Ok(triple) => triple,
+        Err(err) => sess.fatal(&format!("target not recognized: {}", err)),
+    }
 }
 
-fn build_isa(sess: &Session, enable_pic: bool) -> Box<dyn isa::TargetIsa + 'static> {
+fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::TargetIsa + 'static> {
     use target_lexicon::BinaryFormat;
 
     let target_triple = crate::target_triple(sess);
 
     let mut flags_builder = settings::builder();
-    if enable_pic {
-        flags_builder.enable("is_pic").unwrap();
-    } else {
-        flags_builder.set("is_pic", "false").unwrap();
-    }
+    flags_builder.enable("is_pic").unwrap();
     flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
-    flags_builder
-        .set(
-            "enable_verifier",
-            if cfg!(debug_assertions) {
-                "true"
-            } else {
-                "false"
-            },
-        )
-        .unwrap();
+    let enable_verifier = if backend_config.enable_verifier { "true" } else { "false" };
+    flags_builder.set("enable_verifier", enable_verifier).unwrap();
 
     let tls_model = match target_triple.binary_format {
         BinaryFormat::Elf => "elf_gd",
@@ -295,30 +250,63 @@ fn build_isa(sess: &Session, enable_pic: bool) -> Box<dyn isa::TargetIsa + 'stat
     };
     flags_builder.set("tls_model", tls_model).unwrap();
 
-    // FIXME(CraneStation/cranelift#732) fix LICM in presence of jump tables
-    /*
+    flags_builder.set("enable_simd", "true").unwrap();
+
+    flags_builder.set("enable_llvm_abi_extensions", "true").unwrap();
+
+    flags_builder.set("regalloc", &backend_config.regalloc).unwrap();
+
     use rustc_session::config::OptLevel;
     match sess.opts.optimize {
         OptLevel::No => {
             flags_builder.set("opt_level", "none").unwrap();
         }
         OptLevel::Less | OptLevel::Default => {}
-        OptLevel::Aggressive => {
+        OptLevel::Size | OptLevel::SizeMin | OptLevel::Aggressive => {
             flags_builder.set("opt_level", "speed_and_size").unwrap();
         }
-        OptLevel::Size | OptLevel::SizeMin => {
-            sess.warn("Optimizing for size is not supported. Just ignoring the request");
-        }
-    }*/
+    }
 
     let flags = settings::Flags::new(flags_builder);
-    cranelift_codegen::isa::lookup(target_triple)
-        .unwrap()
-        .finish(flags)
+
+    let variant = cranelift_codegen::isa::BackendVariant::MachInst;
+
+    let isa_builder = match sess.opts.cg.target_cpu.as_deref() {
+        Some("native") => {
+            let builder = cranelift_native::builder_with_options(variant, true).unwrap();
+            builder
+        }
+        Some(value) => {
+            let mut builder =
+                cranelift_codegen::isa::lookup_variant(target_triple.clone(), variant)
+                    .unwrap_or_else(|err| {
+                        sess.fatal(&format!("can't compile for {}: {}", target_triple, err));
+                    });
+            if let Err(_) = builder.enable(value) {
+                sess.fatal("the specified target cpu isn't currently supported by Cranelift.");
+            }
+            builder
+        }
+        None => {
+            let mut builder =
+                cranelift_codegen::isa::lookup_variant(target_triple.clone(), variant)
+                    .unwrap_or_else(|err| {
+                        sess.fatal(&format!("can't compile for {}: {}", target_triple, err));
+                    });
+            if target_triple.architecture == target_lexicon::Architecture::X86_64 {
+                // Don't use "haswell" as the default, as it implies `has_lzcnt`.
+                // macOS CI is still at Ivy Bridge EP, so `lzcnt` is interpreted as `bsr`.
+                builder.enable("nehalem").unwrap();
+            }
+            builder
+        }
+    };
+
+    isa_builder.finish(flags)
 }
 
 /// This is the entrypoint for a hot plugged rustc_codegen_cranelift
 #[no_mangle]
 pub fn __rustc_codegen_backend() -> Box<dyn CodegenBackend> {
-    Box::new(CraneliftCodegenBackend)
+    Box::new(CraneliftCodegenBackend { config: None })
 }