Sync rustc_codegen_cranelift 'ddd4ce25535cf71203ba3700896131ce55fde795'

This commit is contained in:
Erin Power
2021-04-30 14:49:58 +02:00
43 changed files with 784 additions and 1243 deletions

View File

@@ -1,4 +1,4 @@
#![feature(rustc_private, decl_macro, never_type, hash_drain_filter)]
#![feature(rustc_private, decl_macro, never_type, hash_drain_filter, vec_into_raw_parts)]
#![warn(rust_2018_idioms)]
#![warn(unused_lifetimes)]
#![warn(unreachable_pub)]
@@ -23,7 +23,6 @@ extern crate rustc_target;
extern crate rustc_driver;
use std::any::Any;
use std::str::FromStr;
use rustc_codegen_ssa::traits::CodegenBackend;
use rustc_codegen_ssa::CodegenResults;
@@ -34,9 +33,10 @@ use rustc_middle::ty::query::Providers;
use rustc_session::config::OutputFilenames;
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;
@@ -49,6 +49,7 @@ mod cast;
mod codegen_i128;
mod common;
mod compiler_builtins;
mod config;
mod constant;
mod debuginfo;
mod discriminant;
@@ -87,7 +88,6 @@ mod prelude {
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;
@@ -119,95 +119,36 @@ impl<F: Fn() -> String> Drop for PrintOnPanic<F> {
}
}
struct CodegenCx<'m, 'tcx: 'm> {
/// 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: &'m mut dyn Module,
global_asm: String,
constants_cx: ConstantCx,
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<'m, 'tcx> CodegenCx<'m, 'tcx> {
impl<'tcx> CodegenCx<'tcx> {
fn new(
tcx: TyCtxt<'tcx>,
backend_config: BackendConfig,
module: &'m mut dyn Module,
isa: &dyn TargetIsa,
debug_info: bool,
) -> Self {
let unwind_context = UnwindContext::new(
tcx,
module.isa(),
matches!(backend_config.codegen_mode, CodegenMode::Aot),
);
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,
global_asm: String::new(),
constants_cx: ConstantCx::default(),
cached_context: Context::new(),
vtables: FxHashMap::default(),
debug_context,
unwind_context,
}
}
fn finalize(self) -> (String, Option<DebugContext<'tcx>>, UnwindContext<'tcx>) {
self.constants_cx.finalize(self.tcx, self.module);
(self.global_asm, self.debug_context, self.unwind_context)
}
}
#[derive(Copy, Clone, Debug)]
pub enum CodegenMode {
Aot,
Jit,
JitLazy,
}
impl Default for CodegenMode {
fn default() -> Self {
CodegenMode::Aot
}
}
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,
}
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 {
return Err(format!("Invalid option `{}`", opt));
}
}
Ok(config)
}
}
pub struct CraneliftCodegenBackend {
@@ -240,13 +181,23 @@ impl CodegenBackend for CraneliftCodegenBackend {
metadata: EncodedMetadata,
need_metadata_module: bool,
) -> Box<dyn Any> {
let config = if let Some(config) = self.config {
tcx.sess.abort_if_errors();
let config = if let Some(config) = self.config.clone() {
config
} else {
BackendConfig::from_opts(&tcx.sess.opts.cg.llvm_args)
.unwrap_or_else(|err| tcx.sess.fatal(&err))
};
driver::codegen_crate(tcx, metadata, need_metadata_module, config)
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(
@@ -284,7 +235,7 @@ fn target_triple(sess: &Session) -> target_lexicon::Triple {
sess.target.llvm_target.parse().unwrap()
}
fn build_isa(sess: &Session) -> 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);
@@ -292,9 +243,8 @@ fn build_isa(sess: &Session) -> Box<dyn isa::TargetIsa + 'static> {
let mut flags_builder = settings::builder();
flags_builder.enable("is_pic").unwrap();
flags_builder.set("enable_probestack", "false").unwrap(); // __cranelift_probestack is not provided
let enable_verifier =
cfg!(debug_assertions) || std::env::var("CG_CLIF_ENABLE_VERIFIER").is_ok();
flags_builder.set("enable_verifier", if enable_verifier { "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",
@@ -322,10 +272,28 @@ fn build_isa(sess: &Session) -> Box<dyn isa::TargetIsa + 'static> {
let flags = settings::Flags::new(flags_builder);
let variant = 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();
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, variant).unwrap();
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, variant).unwrap();
// 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)
}