]> git.lizzy.rs Git - rust.git/blobdiff - src/lib.rs
Rollup merge of #81618 - bjorn3:sync_cg_clif-2021-02-01, r=bjorn3
[rust.git] / src / lib.rs
index c0a2433ceeb4bc421e933d1ce96bf123ffc4e0b1..170750461cace0a60c10e8f98e0d3f848a7831ea 100644 (file)
@@ -1,31 +1,51 @@
-#![feature(rustc_private, decl_macro, type_alias_impl_trait, associated_type_bounds, never_type)]
-#![allow(intra_doc_link_resolution_failure)]
-
-extern crate flate2;
-extern crate tempfile;
-extern crate rustc;
+#![feature(
+    rustc_private,
+    decl_macro,
+    type_alias_impl_trait,
+    associated_type_bounds,
+    never_type,
+    try_blocks,
+    hash_drain_filter,
+    str_split_once
+)]
+#![warn(rust_2018_idioms)]
+#![warn(unused_lifetimes)]
+#![warn(unreachable_pub)]
+
+#[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_codegen_utils;
 extern crate rustc_data_structures;
-extern crate rustc_driver;
+extern crate rustc_errors;
 extern crate rustc_fs_util;
+extern crate rustc_hir;
 extern crate rustc_incremental;
 extern crate rustc_index;
-extern crate rustc_mir;
 extern crate rustc_session;
+extern crate rustc_span;
 extern crate rustc_target;
-extern crate syntax;
+
+// This prevents duplicating functions and statics that are already part of the host rustc process.
+#[allow(unused_extern_crates)]
+extern crate rustc_driver;
 
 use std::any::Any;
+use std::str::FromStr;
 
-use rustc::dep_graph::DepGraph;
-use rustc::middle::cstore::{EncodedMetadata, MetadataLoader};
-use rustc::session::config::OutputFilenames;
-use rustc::ty::query::Providers;
-use rustc::util::common::ErrorReported;
-use rustc_codegen_utils::codegen_backend::CodegenBackend;
+use rustc_codegen_ssa::traits::CodegenBackend;
+use rustc_codegen_ssa::CodegenResults;
+use rustc_errors::ErrorReported;
+use rustc_middle::dep_graph::{WorkProduct, WorkProductId};
+use rustc_middle::middle::cstore::{EncodedMetadata, MetadataLoader};
+use rustc_middle::ty::query::Providers;
+use rustc_session::config::OutputFilenames;
+use rustc_session::Session;
 
-use cranelift_codegen::settings;
+use cranelift_codegen::settings::{self, Configurable};
 
 use crate::constant::ConstantCx;
 use crate::prelude::*;
@@ -34,8 +54,9 @@
 mod allocator;
 mod analyze;
 mod archive;
-mod base;
+mod atomic_shim;
 mod backend;
+mod base;
 mod cast;
 mod codegen_i128;
 mod common;
@@ -43,6 +64,7 @@
 mod debuginfo;
 mod discriminant;
 mod driver;
+mod inline_asm;
 mod intrinsics;
 mod linkage;
 mod main_shim;
 mod optimize;
 mod pointer;
 mod pretty_clif;
-mod target_features_whitelist;
+mod toolchain;
 mod trap;
-mod unimpl;
 mod unsize;
 mod value_and_place;
 mod vtable;
 
 mod prelude {
-    pub use std::any::Any;
-    pub use std::collections::{HashMap, HashSet};
-    pub use std::convert::{TryFrom, TryInto};
-
-    pub use syntax::ast::{FloatTy, IntTy, UintTy};
-    pub use syntax::source_map::{Pos, Span};
-
-    pub use rustc::bug;
-    pub use rustc::hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
-    pub use rustc::mir::{self, interpret::AllocId, mono::MonoItem, *};
-    pub use rustc::session::{
-        config::{CrateType, Lto},
-        Session,
-    };
-    pub use rustc::ty::layout::{self, Abi, LayoutOf, Scalar, Size, TyLayout, VariantIdx};
-    pub use rustc::ty::{
-        self, FnSig, Instance, InstanceDef, ParamEnv, PolyFnSig, Ty, TyCtxt, TypeAndMut,
-        TypeFoldable,
-    };
+    pub(crate) use std::convert::{TryFrom, TryInto};
 
-    pub use rustc_data_structures::{
-        fx::{FxHashMap, FxHashSet},
-        sync::Lrc,
-    };
+    pub(crate) use rustc_span::Span;
 
-    pub use rustc_index::vec::Idx;
-
-    pub use rustc_mir::monomorphize::collector;
-
-    pub use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
-    pub use rustc_codegen_ssa::traits::*;
-    pub use rustc_codegen_ssa::{CodegenResults, CompiledModule, ModuleKind};
-
-    pub use cranelift_codegen::Context;
-    pub use cranelift_codegen::ir::{AbiParam, Ebb, ExternalName, FuncRef, Inst, InstBuilder, MemFlags, Signature, SourceLoc, StackSlot, StackSlotData, StackSlotKind, TrapCode, Type, Value};
-    pub use cranelift_codegen::ir::condcodes::{FloatCC, IntCC};
-    pub use cranelift_codegen::ir::function::Function;
-    pub use cranelift_codegen::ir::immediates::{Ieee32, Ieee64};
-    pub use cranelift_codegen::ir::types;
-    pub use cranelift_codegen::isa::{self, CallConv};
-    pub use cranelift_codegen::settings::{self, Configurable};
-    pub use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext, Variable};
-    pub use cranelift_module::{
-        self, Backend, DataContext, DataId, FuncId, FuncOrDataId, Linkage, Module,
+    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_middle::ty::{
+        self, FloatTy, Instance, InstanceDef, IntTy, ParamEnv, Ty, TyCtxt, TypeAndMut,
+        TypeFoldable, UintTy,
     };
+    pub(crate) use rustc_target::abi::{Abi, LayoutOf, Scalar, Size, VariantIdx};
 
-    pub use crate::abi::*;
-    pub use crate::base::{trans_operand, trans_place};
-    pub use crate::cast::*;
-    pub use crate::common::*;
-    pub use crate::debuginfo::{DebugContext, FunctionDebugContext};
-    pub use crate::pointer::Pointer;
-    pub use crate::trap::*;
-    pub use crate::unimpl::unimpl;
-    pub use crate::value_and_place::{CPlace, CPlaceInner, CValue};
-    pub use crate::{Caches, CodegenCx};
-
-    pub struct PrintOnPanic<F: Fn() -> String>(pub F);
-    impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
-        fn drop(&mut self) {
-            if ::std::thread::panicking() {
-                println!("{}", (self.0)());
-            }
-        }
-    }
-}
+    pub(crate) use rustc_data_structures::fx::FxHashMap;
 
-pub struct Caches<'tcx> {
-    pub context: Context,
-    pub vtables: HashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
+    pub(crate) use rustc_index::vec::Idx;
+
+    pub(crate) use cranelift_codegen::entity::EntitySet;
+    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, DataContext, DataId, FuncId, Linkage, Module};
+
+    pub(crate) use crate::abi::*;
+    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};
+    pub(crate) use crate::pointer::Pointer;
+    pub(crate) use crate::trap::*;
+    pub(crate) use crate::value_and_place::{CPlace, CPlaceInner, CValue};
 }
 
-impl Default for Caches<'_> {
-    fn default() -> Self {
-        Caches {
-            context: Context::new(),
-            vtables: HashMap::new(),
+struct PrintOnPanic<F: Fn() -> String>(F);
+impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
+    fn drop(&mut self) {
+        if ::std::thread::panicking() {
+            println!("{}", (self.0)());
         }
     }
 }
 
-pub struct CodegenCx<'clif, 'tcx, B: Backend + 'static> {
+struct CodegenCx<'tcx, M: Module> {
     tcx: TyCtxt<'tcx>,
-    module: &'clif mut Module<B>,
+    module: M,
+    global_asm: String,
     constants_cx: ConstantCx,
-    caches: Caches<'tcx>,
-    debug_context: Option<&'clif mut DebugContext<'tcx>>,
+    cached_context: Context,
+    vtables: FxHashMap<(Ty<'tcx>, Option<ty::PolyExistentialTraitRef<'tcx>>), DataId>,
+    debug_context: Option<DebugContext<'tcx>>,
+    unwind_context: UnwindContext<'tcx>,
 }
 
-impl<'clif, 'tcx, B: Backend + 'static> CodegenCx<'clif, 'tcx, B> {
-    fn new(
-        tcx: TyCtxt<'tcx>,
-        module: &'clif mut Module<B>,
-        debug_context: Option<&'clif mut DebugContext<'tcx>>,
-    ) -> Self {
+impl<'tcx, M: Module> CodegenCx<'tcx, M> {
+    fn new(tcx: TyCtxt<'tcx>, module: M, debug_info: bool, pic_eh_frame: bool) -> Self {
+        let unwind_context = UnwindContext::new(tcx, module.isa(), pic_eh_frame);
+        let debug_context = if debug_info {
+            Some(DebugContext::new(tcx, module.isa()))
+        } else {
+            None
+        };
         CodegenCx {
             tcx,
             module,
+            global_asm: String::new(),
             constants_cx: ConstantCx::default(),
-            caches: Caches::default(),
+            cached_context: Context::new(),
+            vtables: FxHashMap::default(),
             debug_context,
+            unwind_context,
         }
     }
 
-    fn finalize(self) {
-        self.constants_cx.finalize(self.tcx, self.module);
+    fn finalize(mut self) -> (M, String, Option<DebugContext<'tcx>>, UnwindContext<'tcx>) {
+        self.constants_cx.finalize(self.tcx, &mut self.module);
+        (
+            self.module,
+            self.global_asm,
+            self.debug_context,
+            self.unwind_context,
+        )
     }
 }
 
-struct CraneliftCodegenBackend;
+#[derive(Copy, Clone, Debug)]
+pub enum CodegenMode {
+    Aot,
+    Jit,
+    JitLazy,
+}
 
-impl CodegenBackend for CraneliftCodegenBackend {
-    fn init(&self, _sess: &Session) {}
+impl Default for CodegenMode {
+    fn default() -> Self {
+        CodegenMode::Aot
+    }
+}
 
-    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
-        Box::new(crate::metadata::CraneliftMetadataLoader)
+impl FromStr for CodegenMode {
+    type Err = String;
+
+    fn from_str(s: &str) -> Result<Self, Self::Err> {
+        match s {
+            "aot" => Ok(CodegenMode::Aot),
+            "jit" => Ok(CodegenMode::Jit),
+            "jit-lazy" => Ok(CodegenMode::JitLazy),
+            _ => Err(format!("Unknown codegen mode `{}`", s)),
+        }
     }
+}
+
+#[derive(Copy, Clone, Debug, Default)]
+pub struct BackendConfig {
+    pub codegen_mode: CodegenMode,
+}
 
-    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
-                tcx.arena.alloc(
-                    target_features_whitelist::all_known_features()
-                        .map(|(a, b)| (a.to_string(), b))
-                        .collect(),
-                )
+impl BackendConfig {
+    fn from_opts(opts: &[String]) -> Result<Self, String> {
+        let mut config = BackendConfig::default();
+        for opt in opts {
+            if let Some((name, value)) = opt.split_once('=') {
+                match name {
+                    "mode" => config.codegen_mode = value.parse()?,
+                    _ => return Err(format!("Unknown option `{}`", name)),
+                }
             } else {
-                tcx.arena.alloc(
-                    target_features_whitelist::target_feature_whitelist(tcx.sess)
-                        .iter()
-                        .map(|&(a, b)| (a.to_string(), b))
-                        .collect(),
-                )
+                return Err(format!("Invalid option `{}`", opt));
             }
-        };
+        }
+        Ok(config)
+    }
+}
+
+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.");
+        }
     }
+
+    fn metadata_loader(&self) -> Box<dyn MetadataLoader + Sync> {
+        Box::new(crate::metadata::CraneliftMetadataLoader)
+    }
+
+    fn provide(&self, _providers: &mut Providers) {}
     fn provide_extern(&self, _providers: &mut Providers) {}
 
+    fn target_features(&self, _sess: &Session) -> Vec<rustc_span::Symbol> {
+        vec![]
+    }
+
     fn codegen_crate<'tcx>(
         &self,
         tcx: TyCtxt<'tcx>,
         metadata: EncodedMetadata,
         need_metadata_module: bool,
     ) -> Box<dyn Any> {
-        rustc_codegen_utils::check_for_rustc_errors_attr(tcx);
-
-        let res = driver::codegen_crate(tcx, metadata, need_metadata_module);
-
-        rustc_incremental::assert_module_sources::assert_module_sources(tcx);
-        rustc_codegen_utils::symbol_names_test::report_symbol_names(tcx);
+        let config = if let Some(config) = self.config {
+            config
+        } else {
+            BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
+                .unwrap_or_else(|err| tcx.sess.fatal(&err))
+        };
+        let res = driver::codegen_crate(tcx, metadata, need_metadata_module, config);
 
         res
     }
 
-    fn join_codegen_and_link(
+    fn join_codegen(
+        &self,
+        ongoing_codegen: Box<dyn Any>,
+        _sess: &Session,
+    ) -> Result<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>), ErrorReported> {
+        Ok(*ongoing_codegen
+            .downcast::<(CodegenResults, FxHashMap<WorkProductId, WorkProduct>)>()
+            .unwrap())
+    }
+
+    fn link(
         &self,
-        res: Box<dyn Any>,
         sess: &Session,
-        _dep_graph: &DepGraph,
+        codegen_results: CodegenResults,
         outputs: &OutputFilenames,
     ) -> Result<(), ErrorReported> {
         use rustc_codegen_ssa::back::link::link_binary;
 
-        let codegen_results = *res
-            .downcast::<CodegenResults>()
-            .expect("Expected CraneliftCodegenBackend's CodegenResult, found Box<Any>");
-
-        let _timer = sess.prof.generic_activity("link_crate");
-
-        rustc::util::common::time(sess, "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,
-            );
-        });
+        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,
+        );
 
         Ok(())
     }
 }
 
 fn target_triple(sess: &Session) -> target_lexicon::Triple {
-    sess.target.target.llvm_target.parse().unwrap()
+    sess.target.llvm_target.parse().unwrap()
 }
 
-fn build_isa(sess: &Session, enable_pic: bool) -> Box<dyn isa::TargetIsa + 'static> {
+fn build_isa(sess: &Session) -> 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.set("probestack_enabled", "false").unwrap(); // __cranelift_probestack is not provided
+    flags_builder.enable("is_pic").unwrap();
+    flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
     flags_builder
         .set(
             "enable_verifier",
@@ -269,31 +313,46 @@ fn build_isa(sess: &Session, enable_pic: bool) -> Box<dyn isa::TargetIsa + 'stat
         )
         .unwrap();
 
-    // FIXME(CraneStation/cranelift#732) fix LICM in presence of jump tables
-    /*
-    use rustc::session::config::OptLevel;
+    let tls_model = match target_triple.binary_format {
+        BinaryFormat::Elf => "elf_gd",
+        BinaryFormat::Macho => "macho",
+        BinaryFormat::Coff => "coff",
+        _ => "none",
+    };
+    flags_builder.set("tls_model", tls_model).unwrap();
+
+    flags_builder.set("enable_simd", "true").unwrap();
+
+    use rustc_session::config::OptLevel;
     match sess.opts.optimize {
         OptLevel::No => {
-            flags_builder.set("opt_level", "fastest").unwrap();
+            flags_builder.set("opt_level", "none").unwrap();
         }
         OptLevel::Less | OptLevel::Default => {}
         OptLevel::Aggressive => {
-            flags_builder.set("opt_level", "best").unwrap();
+            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 target_triple = crate::target_triple(sess);
     let flags = settings::Flags::new(flags_builder);
-    cranelift_codegen::isa::lookup(target_triple)
-        .unwrap()
-        .finish(flags)
+
+    let variant = if cfg!(feature = "oldbe") {
+        cranelift_codegen::isa::BackendVariant::Legacy
+    } else {
+        cranelift_codegen::isa::BackendVariant::MachInst
+    };
+    let mut isa_builder = cranelift_codegen::isa::lookup_variant(target_triple, variant).unwrap();
+    // Don't use "haswell", as it implies `has_lzcnt`.macOS CI is still at Ivy Bridge EP, so `lzcnt`
+    // is interpreted as `bsr`.
+    isa_builder.enable("nehalem").unwrap();
+    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 })
 }