Merge commit '370c397ec9' into sync_cg_clif-2022-03-20

This commit is contained in:
bjorn3 2022-03-20 16:55:21 +01:00
commit ef4ce72919
32 changed files with 462 additions and 515 deletions

View file

@ -94,6 +94,9 @@ impl<'tcx> FunctionCx<'_, '_, 'tcx> {
let sig = Signature { params, returns, call_conv: self.target_config.default_call_conv };
let func_id = self.module.declare_function(name, Linkage::Import, &sig).unwrap();
let func_ref = self.module.declare_func_in_func(func_id, &mut self.bcx.func);
if self.clif_comments.enabled() {
self.add_comment(func_ref, format!("{:?}", name));
}
let call_inst = self.bcx.ins().call(func_ref, args);
if self.clif_comments.enabled() {
self.add_comment(call_inst, format!("easy_call {}", name));
@ -367,7 +370,10 @@ pub(crate) fn codegen_terminator_call<'tcx>(
.map(|inst| fx.tcx.codegen_fn_attrs(inst.def_id()).flags.contains(CodegenFnAttrFlags::COLD))
.unwrap_or(false);
if is_cold {
// FIXME Mark current_block block as cold once Cranelift supports it
fx.bcx.set_cold_block(fx.bcx.current_block().unwrap());
if let Some((_place, destination_block)) = destination {
fx.bcx.set_cold_block(fx.get_block(destination_block));
}
}
// Unpack arguments tuple for closures
@ -501,7 +507,7 @@ pub(crate) fn codegen_terminator_call<'tcx>(
let ret_block = fx.get_block(dest);
fx.bcx.ins().jump(ret_block, &[]);
} else {
trap_unreachable(fx, "[corruption] Diverging function returned");
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
}
}

View file

@ -4,6 +4,7 @@ use rustc_ast::InlineAsmOptions;
use rustc_index::vec::IndexVec;
use rustc_middle::ty::adjustment::PointerCast;
use rustc_middle::ty::layout::FnAbiOf;
use rustc_middle::ty::print::with_no_trimmed_paths;
use indexmap::IndexSet;
@ -25,7 +26,10 @@ pub(crate) fn codegen_fn<'tcx>(
let mir = tcx.instance_mir(instance.def);
let _mir_guard = crate::PrintOnPanic(|| {
let mut buf = Vec::new();
rustc_middle::mir::write_mir_pretty(tcx, Some(instance.def_id()), &mut buf).unwrap();
with_no_trimmed_paths!({
rustc_middle::mir::pretty::write_mir_fn(tcx, mir, &mut |_, _| Ok(()), &mut buf)
.unwrap();
});
String::from_utf8_lossy(&buf).into_owned()
});
@ -90,7 +94,7 @@ pub(crate) fn codegen_fn<'tcx>(
} else if arg_uninhabited {
fx.bcx.append_block_params_for_function_params(fx.block_map[START_BLOCK]);
fx.bcx.switch_to_block(fx.block_map[START_BLOCK]);
crate::trap::trap_unreachable(&mut fx, "function has uninhabited argument");
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
} else {
tcx.sess.time("codegen clif ir", || {
tcx.sess
@ -258,7 +262,9 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
if fx.clif_comments.enabled() {
let mut terminator_head = "\n".to_string();
bb_data.terminator().kind.fmt_head(&mut terminator_head).unwrap();
with_no_trimmed_paths!({
bb_data.terminator().kind.fmt_head(&mut terminator_head).unwrap();
});
let inst = fx.bcx.func.layout.last_inst(block).unwrap();
fx.add_comment(inst, terminator_head);
}
@ -303,7 +309,7 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
let target = fx.get_block(*target);
let failure = fx.bcx.create_block();
// FIXME Mark failure block as cold once Cranelift supports it
fx.bcx.set_cold_block(failure);
if *expected {
fx.bcx.ins().brz(cond, failure, &[]);
@ -424,18 +430,16 @@ fn codegen_fn_content(fx: &mut FunctionCx<'_, '_, '_>) {
fx.bcx.ins().jump(destination_block, &[]);
}
None => {
crate::trap::trap_unreachable(
fx,
"[corruption] Returned from noreturn inline asm",
);
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
}
}
}
TerminatorKind::Resume | TerminatorKind::Abort => {
trap_unreachable(fx, "[corruption] Unwinding bb reached.");
// FIXME implement unwinding
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
}
TerminatorKind::Unreachable => {
trap_unreachable(fx, "[corruption] Hit unreachable code.");
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
}
TerminatorKind::Yield { .. }
| TerminatorKind::FalseEdge { .. }
@ -813,7 +817,14 @@ pub(crate) fn codegen_place<'tcx>(
for elem in place.projection {
match elem {
PlaceElem::Deref => {
cplace = cplace.place_deref(fx);
if cplace.layout().ty.is_box() {
cplace = cplace
.place_field(fx, Field::new(0)) // Box<T> -> Unique<T>
.place_field(fx, Field::new(0)) // Unique<T> -> *const T
.place_deref(fx);
} else {
cplace = cplace.place_deref(fx);
}
}
PlaceElem::Field(field, _ty) => {
cplace = cplace.place_field(fx, field);
@ -918,5 +929,5 @@ pub(crate) fn codegen_panic_inner<'tcx>(
args,
);
crate::trap::trap_unreachable(fx, "panic lang item returned");
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
}

View file

@ -1,4 +1,4 @@
#![feature(rustc_private, once_cell)]
#![feature(rustc_private)]
#![warn(rust_2018_idioms)]
#![warn(unused_lifetimes)]
#![warn(unreachable_pub)]
@ -9,19 +9,21 @@ extern crate rustc_interface;
extern crate rustc_session;
extern crate rustc_target;
use std::lazy::SyncLazy;
use std::panic;
use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry};
use rustc_interface::interface;
use rustc_session::config::ErrorOutputType;
use rustc_session::config::{ErrorOutputType, TrimmedDefPaths};
use rustc_session::early_error;
use rustc_target::spec::PanicStrategy;
// FIXME use std::lazy::SyncLazy once it stabilizes
use once_cell::sync::Lazy;
const BUG_REPORT_URL: &str = "https://github.com/bjorn3/rustc_codegen_cranelift/issues/new";
static DEFAULT_HOOK: SyncLazy<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
SyncLazy::new(|| {
static DEFAULT_HOOK: Lazy<Box<dyn Fn(&panic::PanicInfo<'_>) + Sync + Send + 'static>> =
Lazy::new(|| {
let hook = panic::take_hook();
panic::set_hook(Box::new(|info| {
// Invoke the default handler, which prints the actual panic message and optionally a backtrace
@ -53,6 +55,8 @@ impl rustc_driver::Callbacks for CraneliftPassesCallbacks {
config.opts.maybe_sysroot = Some(config.opts.maybe_sysroot.clone().unwrap_or_else(|| {
std::env::current_exe().unwrap().parent().unwrap().parent().unwrap().to_owned()
}));
config.opts.trimmed_def_paths = TrimmedDefPaths::GoodPath;
}
}
@ -61,7 +65,7 @@ fn main() {
let start_rss = get_resident_set_size();
rustc_driver::init_rustc_env_logger();
let mut callbacks = CraneliftPassesCallbacks::default();
SyncLazy::force(&DEFAULT_HOOK); // Install ice hook
Lazy::force(&DEFAULT_HOOK); // Install ice hook
let exit_code = rustc_driver::catch_with_exit_code(|| {
let args = std::env::args_os()
.enumerate()

View file

@ -1,16 +1,18 @@
macro builtin_functions($register:ident; $(fn $name:ident($($arg_name:ident: $arg_ty:ty),*) -> $ret_ty:ty;)*) {
#[cfg(feature = "jit")]
#[allow(improper_ctypes)]
extern "C" {
$(fn $name($($arg_name: $arg_ty),*) -> $ret_ty;)*
}
#[cfg(feature = "jit")]
pub(crate) fn $register(builder: &mut cranelift_jit::JITBuilder) {
for (name, val) in [$((stringify!($name), $name as *const u8)),*] {
builder.symbol(name, val);
macro_rules! builtin_functions {
($register:ident; $(fn $name:ident($($arg_name:ident: $arg_ty:ty),*) -> $ret_ty:ty;)*) => {
#[cfg(feature = "jit")]
#[allow(improper_ctypes)]
extern "C" {
$(fn $name($($arg_name: $arg_ty),*) -> $ret_ty;)*
}
}
#[cfg(feature = "jit")]
pub(crate) fn $register(builder: &mut cranelift_jit::JITBuilder) {
for (name, val) in [$((stringify!($name), $name as *const u8)),*] {
builder.symbol(name, val);
}
}
};
}
builtin_functions! {

View file

@ -110,7 +110,6 @@ impl<'tcx> DebugContext<'tcx> {
entry.set(gimli::DW_AT_decl_file, AttributeValue::FileIndex(Some(file_id)));
entry.set(gimli::DW_AT_decl_line, AttributeValue::Udata(loc.line as u64));
// FIXME: probably omit this
entry.set(gimli::DW_AT_decl_column, AttributeValue::Udata(loc.col.to_usize() as u64));
}

View file

@ -81,6 +81,8 @@ impl UnwindContext {
#[cfg(all(feature = "jit", not(windows)))]
pub(crate) unsafe fn register_jit(self, jit_module: &cranelift_jit::JITModule) {
use std::mem::ManuallyDrop;
let mut eh_frame = EhFrame::from(super::emit::WriterRelocate::new(self.endian));
self.frame_table.write_eh_frame(&mut eh_frame).unwrap();
@ -95,17 +97,16 @@ impl UnwindContext {
// FIXME support unregistering unwind tables once cranelift-jit supports deallocating
// individual functions
#[allow(unused_variables)]
let (eh_frame, eh_frame_len, _) = Vec::into_raw_parts(eh_frame);
let eh_frame = ManuallyDrop::new(eh_frame);
// =======================================================================
// Everything after this line up to the end of the file is loosly based on
// Everything after this line up to the end of the file is loosely based on
// https://github.com/bytecodealliance/wasmtime/blob/4471a82b0c540ff48960eca6757ccce5b1b5c3e4/crates/jit/src/unwind/systemv.rs
#[cfg(target_os = "macos")]
{
// On macOS, `__register_frame` takes a pointer to a single FDE
let start = eh_frame;
let end = start.add(eh_frame_len);
let start = eh_frame.as_ptr();
let end = start.add(eh_frame.len());
let mut current = start;
// Walk all of the entries in the frame table and register them
@ -124,7 +125,7 @@ impl UnwindContext {
#[cfg(not(target_os = "macos"))]
{
// On other platforms, `__register_frame` will walk the FDEs until an entry of length 0
__register_frame(eh_frame);
__register_frame(eh_frame.as_ptr());
}
}
}

View file

@ -68,11 +68,10 @@ pub(crate) fn codegen_get_discriminant<'tcx>(
let layout = value.layout();
if layout.abi == Abi::Uninhabited {
return trap_unreachable_ret_value(
fx,
dest_layout,
"[panic] Tried to get discriminant for uninhabited type.",
);
let true_ = fx.bcx.ins().iconst(types::I32, 1);
fx.bcx.ins().trapnz(true_, TrapCode::UnreachableCodeReached);
// Return a dummy value
return CValue::by_ref(Pointer::const_addr(fx, 0), dest_layout);
}
let (tag_scalar, tag_field, tag_encoding) = match &layout.variants {

View file

@ -3,7 +3,6 @@
use std::cell::RefCell;
use std::ffi::CString;
use std::lazy::SyncOnceCell;
use std::os::raw::{c_char, c_int};
use std::sync::{mpsc, Mutex};
@ -14,6 +13,9 @@ use rustc_span::Symbol;
use cranelift_jit::{JITBuilder, JITModule};
// FIXME use std::lazy::SyncOnceCell once it stabilizes
use once_cell::sync::OnceCell;
use crate::{prelude::*, BackendConfig};
use crate::{CodegenCx, CodegenMode};
@ -27,8 +29,7 @@ thread_local! {
}
/// The Sender owned by the rustc thread
static GLOBAL_MESSAGE_SENDER: SyncOnceCell<Mutex<mpsc::Sender<UnsafeMessage>>> =
SyncOnceCell::new();
static GLOBAL_MESSAGE_SENDER: OnceCell<Mutex<mpsc::Sender<UnsafeMessage>>> = OnceCell::new();
/// A message that is sent from the jitted runtime to the rustc thread.
/// Senders are responsible for upholding `Send` semantics.

View file

@ -126,12 +126,9 @@ pub(crate) fn codegen_llvm_intrinsic_call<'tcx>(
};
}
if let Some((_, dest)) = destination {
let ret_block = fx.get_block(dest);
fx.bcx.ins().jump(ret_block, &[]);
} else {
trap_unreachable(fx, "[corruption] Diverging intrinsic returned.");
}
let dest = destination.expect("all llvm intrinsics used by stdlib should return").1;
let ret_block = fx.get_block(dest);
fx.bcx.ins().jump(ret_block, &[]);
}
// llvm.x86.avx2.vperm2i128

View file

@ -1,46 +1,32 @@
//! Codegen of intrinsics. This includes `extern "rust-intrinsic"`, `extern "platform-intrinsic"`
//! and LLVM intrinsics that have symbol names starting with `llvm.`.
mod cpuid;
mod llvm;
mod simd;
pub(crate) use cpuid::codegen_cpuid_call;
pub(crate) use llvm::codegen_llvm_intrinsic_call;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::SubstsRef;
use rustc_span::symbol::{kw, sym, Symbol};
use crate::prelude::*;
use cranelift_codegen::ir::AtomicRmwOp;
macro intrinsic_pat {
macro_rules! intrinsic_pat {
(_) => {
_
},
};
($name:ident) => {
sym::$name
},
};
(kw.$name:ident) => {
kw::$name
},
};
($name:literal) => {
$name
},
};
}
macro intrinsic_arg {
(o $fx:expr, $arg:ident) => {},
macro_rules! intrinsic_arg {
(o $fx:expr, $arg:ident) => {};
(c $fx:expr, $arg:ident) => {
let $arg = codegen_operand($fx, $arg);
},
};
(v $fx:expr, $arg:ident) => {
let $arg = codegen_operand($fx, $arg).load_scalar($fx);
}
};
}
macro intrinsic_match {
macro_rules! intrinsic_match {
($fx:expr, $intrinsic:expr, $args:expr,
_ => $unknown:block;
$(
@ -62,6 +48,20 @@ macro intrinsic_match {
}
}
mod cpuid;
mod llvm;
mod simd;
pub(crate) use cpuid::codegen_cpuid_call;
pub(crate) use llvm::codegen_llvm_intrinsic_call;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::subst::SubstsRef;
use rustc_span::symbol::{kw, sym, Symbol};
use crate::prelude::*;
use cranelift_codegen::ir::AtomicRmwOp;
fn report_atomic_type_validation_error<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
intrinsic: Symbol,
@ -229,7 +229,7 @@ pub(crate) fn codegen_intrinsic_call<'tcx>(
// Insert non returning intrinsics here
match intrinsic {
sym::abort => {
trap_abort(fx, "Called intrinsic::abort.");
fx.bcx.ins().trap(TrapCode::User(0));
}
sym::transmute => {
crate::base::codegen_panic(fx, "Transmuting to uninhabited type.", span);
@ -749,6 +749,18 @@ fn codegen_regular_intrinsic_call<'tcx>(
_ if intrinsic.as_str().starts_with("atomic_load"), (v ptr) {
let ty = substs.type_at(0);
match ty.kind() {
ty::Uint(UintTy::U128) | ty::Int(IntTy::I128) => {
// FIXME implement 128bit atomics
if fx.tcx.is_compiler_builtins(LOCAL_CRATE) {
// special case for compiler-builtins to avoid having to patch it
crate::trap::trap_unimplemented(fx, "128bit atomics not yet supported");
let ret_block = fx.get_block(destination.unwrap().1);
fx.bcx.ins().jump(ret_block, &[]);
return;
} else {
fx.tcx.sess.span_fatal(span, "128bit atomics not yet supported");
}
}
ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
_ => {
report_atomic_type_validation_error(fx, intrinsic, span, ty);
@ -765,6 +777,18 @@ fn codegen_regular_intrinsic_call<'tcx>(
_ if intrinsic.as_str().starts_with("atomic_store"), (v ptr, c val) {
let ty = substs.type_at(0);
match ty.kind() {
ty::Uint(UintTy::U128) | ty::Int(IntTy::I128) => {
// FIXME implement 128bit atomics
if fx.tcx.is_compiler_builtins(LOCAL_CRATE) {
// special case for compiler-builtins to avoid having to patch it
crate::trap::trap_unimplemented(fx, "128bit atomics not yet supported");
let ret_block = fx.get_block(destination.unwrap().1);
fx.bcx.ins().jump(ret_block, &[]);
return;
} else {
fx.tcx.sess.span_fatal(span, "128bit atomics not yet supported");
}
}
ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
_ => {
report_atomic_type_validation_error(fx, intrinsic, span, ty);
@ -1115,10 +1139,6 @@ fn codegen_regular_intrinsic_call<'tcx>(
};
}
if let Some((_, dest)) = destination {
let ret_block = fx.get_block(dest);
fx.bcx.ins().jump(ret_block, &[]);
} else {
trap_unreachable(fx, "[corruption] Diverging intrinsic returned.");
}
let ret_block = fx.get_block(destination.unwrap().1);
fx.bcx.ins().jump(ret_block, &[]);
}

View file

@ -409,6 +409,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
};
simd_reduce_add_ordered | simd_reduce_add_unordered, (c v, v acc) {
// FIXME there must be no acc param for integer vectors
if !v.layout().ty.is_simd() {
report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty);
return;
@ -424,6 +425,7 @@ pub(super) fn codegen_simd_intrinsic_call<'tcx>(
};
simd_reduce_mul_ordered | simd_reduce_mul_unordered, (c v, v acc) {
// FIXME there must be no acc param for integer vectors
if !v.layout().ty.is_simd() {
report_simd_type_validation_error(fx, intrinsic, span, v.layout().ty);
return;

View file

@ -1,5 +1,5 @@
#![feature(rustc_private, decl_macro)]
#![cfg_attr(feature = "jit", feature(never_type, vec_into_raw_parts, once_cell))]
#![feature(rustc_private)]
// Note: please avoid adding other feature gates where possible
#![warn(rust_2018_idioms)]
#![warn(unused_lifetimes)]
#![warn(unreachable_pub)]
@ -105,7 +105,6 @@ mod prelude {
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};
}
@ -196,7 +195,7 @@ impl CodegenBackend for CraneliftCodegenBackend {
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);
driver::jit::run_jit(tcx, config);
#[cfg(not(feature = "jit"))]
tcx.sess.fatal("jit support was disabled when compiling rustc_codegen_cranelift");
@ -301,7 +300,10 @@ fn build_isa(sess: &Session, backend_config: &BackendConfig) -> Box<dyn isa::Tar
}
};
isa_builder.finish(flags)
match isa_builder.finish(flags) {
Ok(target_isa) => target_isa,
Err(err) => sess.fatal(&format!("failed to build TargetIsa: {}", err)),
}
}
/// This is the entrypoint for a hot plugged rustc_codegen_cranelift

View file

@ -25,12 +25,6 @@ fn codegen_print(fx: &mut FunctionCx<'_, '_, '_>, msg: &str) {
fx.bcx.ins().call(puts, &[msg_ptr]);
}
/// Trap code: user1
pub(crate) fn trap_abort(fx: &mut FunctionCx<'_, '_, '_>, msg: impl AsRef<str>) {
codegen_print(fx, msg.as_ref());
fx.bcx.ins().trap(TrapCode::User(1));
}
/// Use this for example when a function call should never return. This will fill the current block,
/// so you can **not** add instructions to it afterwards.
///
@ -39,21 +33,6 @@ pub(crate) fn trap_unreachable(fx: &mut FunctionCx<'_, '_, '_>, msg: impl AsRef<
codegen_print(fx, msg.as_ref());
fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
}
/// Like `trap_unreachable` but returns a fake value of the specified type.
///
/// Trap code: user65535
pub(crate) fn trap_unreachable_ret_value<'tcx>(
fx: &mut FunctionCx<'_, '_, 'tcx>,
dest_layout: TyAndLayout<'tcx>,
msg: impl AsRef<str>,
) -> CValue<'tcx> {
codegen_print(fx, msg.as_ref());
let true_ = fx.bcx.ins().iconst(types::I32, 1);
fx.bcx.ins().trapnz(true_, TrapCode::UnreachableCodeReached);
CValue::by_ref(Pointer::const_addr(fx, 0), dest_layout)
}
/// Use this when something is unimplemented, but `libcore` or `libstd` requires it to codegen.
/// Unlike `trap_unreachable` this will not fill the current block, so you **must** add instructions
/// to it afterwards.