Merge pull request #1068 from bjorn3/support_proc_macros

Pass ByRef values at fixed stack offset for extern "C"
This commit is contained in:
bjorn3 2020-07-17 13:07:11 +02:00 committed by GitHub
commit 9e76c3e886
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 60 additions and 54 deletions

44
Cargo.lock generated
View File

@ -43,16 +43,16 @@ checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]] [[package]]
name = "cranelift-bforest" name = "cranelift-bforest"
version = "0.65.0" version = "0.66.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#4ba3ee33682c293747a672bfb87d5235bb1e62b3" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#5c5a30f76c35e15697fc150fb00c4b86be621d66"
dependencies = [ dependencies = [
"cranelift-entity", "cranelift-entity",
] ]
[[package]] [[package]]
name = "cranelift-codegen" name = "cranelift-codegen"
version = "0.65.0" version = "0.66.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#4ba3ee33682c293747a672bfb87d5235bb1e62b3" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#5c5a30f76c35e15697fc150fb00c4b86be621d66"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"cranelift-bforest", "cranelift-bforest",
@ -69,8 +69,8 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-codegen-meta" name = "cranelift-codegen-meta"
version = "0.65.0" version = "0.66.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#4ba3ee33682c293747a672bfb87d5235bb1e62b3" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#5c5a30f76c35e15697fc150fb00c4b86be621d66"
dependencies = [ dependencies = [
"cranelift-codegen-shared", "cranelift-codegen-shared",
"cranelift-entity", "cranelift-entity",
@ -78,18 +78,18 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-codegen-shared" name = "cranelift-codegen-shared"
version = "0.65.0" version = "0.66.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#4ba3ee33682c293747a672bfb87d5235bb1e62b3" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#5c5a30f76c35e15697fc150fb00c4b86be621d66"
[[package]] [[package]]
name = "cranelift-entity" name = "cranelift-entity"
version = "0.65.0" version = "0.66.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#4ba3ee33682c293747a672bfb87d5235bb1e62b3" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#5c5a30f76c35e15697fc150fb00c4b86be621d66"
[[package]] [[package]]
name = "cranelift-frontend" name = "cranelift-frontend"
version = "0.65.0" version = "0.66.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#4ba3ee33682c293747a672bfb87d5235bb1e62b3" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#5c5a30f76c35e15697fc150fb00c4b86be621d66"
dependencies = [ dependencies = [
"cranelift-codegen", "cranelift-codegen",
"log", "log",
@ -99,8 +99,8 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-module" name = "cranelift-module"
version = "0.65.0" version = "0.66.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#4ba3ee33682c293747a672bfb87d5235bb1e62b3" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#5c5a30f76c35e15697fc150fb00c4b86be621d66"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cranelift-codegen", "cranelift-codegen",
@ -111,8 +111,8 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-native" name = "cranelift-native"
version = "0.65.0" version = "0.66.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#4ba3ee33682c293747a672bfb87d5235bb1e62b3" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#5c5a30f76c35e15697fc150fb00c4b86be621d66"
dependencies = [ dependencies = [
"cranelift-codegen", "cranelift-codegen",
"raw-cpuid", "raw-cpuid",
@ -121,8 +121,8 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-object" name = "cranelift-object"
version = "0.65.0" version = "0.66.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#4ba3ee33682c293747a672bfb87d5235bb1e62b3" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#5c5a30f76c35e15697fc150fb00c4b86be621d66"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"cranelift-codegen", "cranelift-codegen",
@ -133,8 +133,8 @@ dependencies = [
[[package]] [[package]]
name = "cranelift-simplejit" name = "cranelift-simplejit"
version = "0.65.0" version = "0.66.0"
source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#4ba3ee33682c293747a672bfb87d5235bb1e62b3" source = "git+https://github.com/bytecodealliance/wasmtime/?branch=main#5c5a30f76c35e15697fc150fb00c4b86be621d66"
dependencies = [ dependencies = [
"cranelift-codegen", "cranelift-codegen",
"cranelift-module", "cranelift-module",
@ -275,9 +275,9 @@ dependencies = [
[[package]] [[package]]
name = "regalloc" name = "regalloc"
version = "0.0.27" version = "0.0.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9ba8aaf5fe7cf307c6dbdaeed85478961d29e25e3bee5169e11b92fa9f027a8" checksum = "3598bed0895fe0f72a9e0b00ef9e3a3c8af978a8401b2f2046dec5927de6364a"
dependencies = [ dependencies = [
"log", "log",
"rustc-hash", "rustc-hash",

View File

@ -20,4 +20,4 @@ fi
cmd=$1 cmd=$1
shift shift
cargo +${TOOLCHAIN} $cmd --target $TARGET_TRIPLE $@ cargo +${TOOLCHAIN} $cmd $@

View File

@ -6,7 +6,7 @@ mod returning;
use rustc_target::spec::abi::Abi; use rustc_target::spec::abi::Abi;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use cranelift_codegen::ir::AbiParam; use cranelift_codegen::ir::{AbiParam, ArgumentPurpose};
use self::pass_mode::*; use self::pass_mode::*;
use crate::prelude::*; use crate::prelude::*;
@ -123,7 +123,11 @@ fn clif_sig_from_fn_sig<'tcx>(
if abi != Abi::Rust && abi != Abi::RustCall && abi != Abi::RustIntrinsic { if abi != Abi::Rust && abi != Abi::RustCall && abi != Abi::RustIntrinsic {
match pass_mode { match pass_mode {
PassMode::NoPass | PassMode::ByVal(_) => {} PassMode::NoPass | PassMode::ByVal(_) => {}
PassMode::ByValPair(_, _) | PassMode::ByRef { sized: _ } => { PassMode::ByRef { size: Some(size) } => {
let purpose = ArgumentPurpose::StructArgument(u32::try_from(size.bytes()).expect("struct too big to pass on stack"));
return EmptySinglePair::Single(AbiParam::special(pointer_ty(tcx), purpose)).into_iter();
}
PassMode::ByValPair(_, _) | PassMode::ByRef { size: None } => {
tcx.sess.span_warn( tcx.sess.span_warn(
span, span,
&format!( &format!(
@ -137,7 +141,7 @@ fn clif_sig_from_fn_sig<'tcx>(
} }
} }
} }
pass_mode.get_param_ty(tcx).into_iter() pass_mode.get_param_ty(tcx).map(AbiParam::new).into_iter()
}) })
.flatten(); .flatten();
@ -145,26 +149,26 @@ fn clif_sig_from_fn_sig<'tcx>(
tcx, tcx,
tcx.layout_of(ParamEnv::reveal_all().and(output)).unwrap(), tcx.layout_of(ParamEnv::reveal_all().and(output)).unwrap(),
) { ) {
PassMode::NoPass => (inputs.map(AbiParam::new).collect(), vec![]), PassMode::NoPass => (inputs.collect(), vec![]),
PassMode::ByVal(ret_ty) => ( PassMode::ByVal(ret_ty) => (
inputs.map(AbiParam::new).collect(), inputs.collect(),
vec![AbiParam::new(ret_ty)], vec![AbiParam::new(ret_ty)],
), ),
PassMode::ByValPair(ret_ty_a, ret_ty_b) => ( PassMode::ByValPair(ret_ty_a, ret_ty_b) => (
inputs.map(AbiParam::new).collect(), inputs.collect(),
vec![AbiParam::new(ret_ty_a), AbiParam::new(ret_ty_b)], vec![AbiParam::new(ret_ty_a), AbiParam::new(ret_ty_b)],
), ),
PassMode::ByRef { sized: true } => { PassMode::ByRef { size: Some(_) } => {
( (
Some(pointer_ty(tcx)) // First param is place to put return val Some(pointer_ty(tcx)) // First param is place to put return val
.into_iter() .into_iter()
.map(|ty| AbiParam::special(ty, ArgumentPurpose::StructReturn))
.chain(inputs) .chain(inputs)
.map(AbiParam::new)
.collect(), .collect(),
vec![], vec![],
) )
} }
PassMode::ByRef { sized: false } => todo!(), PassMode::ByRef { size: None } => todo!(),
}; };
if requires_caller_location { if requires_caller_location {

View File

@ -7,7 +7,7 @@ pub(super) enum PassMode {
NoPass, NoPass,
ByVal(Type), ByVal(Type),
ByValPair(Type, Type), ByValPair(Type, Type),
ByRef { sized: bool }, ByRef { size: Option<Size> },
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
@ -70,8 +70,8 @@ impl PassMode {
PassMode::NoPass => Empty, PassMode::NoPass => Empty,
PassMode::ByVal(clif_type) => Single(clif_type), PassMode::ByVal(clif_type) => Single(clif_type),
PassMode::ByValPair(a, b) => Pair(a, b), PassMode::ByValPair(a, b) => Pair(a, b),
PassMode::ByRef { sized: true } => Single(pointer_ty(tcx)), PassMode::ByRef { size: Some(_) } => Single(pointer_ty(tcx)),
PassMode::ByRef { sized: false } => Pair(pointer_ty(tcx), pointer_ty(tcx)), PassMode::ByRef { size: None } => Pair(pointer_ty(tcx), pointer_ty(tcx)),
} }
} }
} }
@ -93,16 +93,17 @@ pub(super) fn get_pass_mode<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>)
// Returning (i128, i128) by-val-pair would take 4 regs, while only 3 are // Returning (i128, i128) by-val-pair would take 4 regs, while only 3 are
// available on x86_64. Cranelift gets confused when too many return params // available on x86_64. Cranelift gets confused when too many return params
// are used. // are used.
PassMode::ByRef { sized: true } PassMode::ByRef { size: Some(layout.size) }
} else { } else {
PassMode::ByValPair(a, b) PassMode::ByValPair(a, b)
} }
} }
// FIXME implement Vector Abi in a cg_llvm compatible way // FIXME implement Vector Abi in a cg_llvm compatible way
Abi::Vector { .. } => PassMode::ByRef { sized: true }, Abi::Vector { .. } => PassMode::ByRef { size: Some(layout.size) },
&Abi::Aggregate { sized } => PassMode::ByRef { sized }, Abi::Aggregate { sized: true } => PassMode::ByRef { size: Some(layout.size) },
Abi::Aggregate { sized: false } => PassMode::ByRef { size: None },
} }
} }
} }
@ -118,7 +119,7 @@ pub(super) fn adjust_arg_for_abi<'tcx>(
let (a, b) = arg.load_scalar_pair(fx); let (a, b) = arg.load_scalar_pair(fx);
Pair(a, b) Pair(a, b)
} }
PassMode::ByRef { sized: _ } => { PassMode::ByRef { size: _ } => {
match arg.force_stack(fx) { match arg.force_stack(fx) {
(ptr, None) => Single(ptr.get_addr(fx)), (ptr, None) => Single(ptr.get_addr(fx)),
(ptr, Some(meta)) => Pair(ptr.get_addr(fx), meta), (ptr, Some(meta)) => Pair(ptr.get_addr(fx), meta),
@ -164,8 +165,8 @@ pub(super) fn cvalue_for_param<'tcx>(
let (a, b) = block_params.assert_pair(); let (a, b) = block_params.assert_pair();
Some(CValue::by_val_pair(a, b, layout)) Some(CValue::by_val_pair(a, b, layout))
} }
PassMode::ByRef { sized: true } => Some(CValue::by_ref(Pointer::new(block_params.assert_single()), layout)), PassMode::ByRef { size: Some(_) } => Some(CValue::by_ref(Pointer::new(block_params.assert_single()), layout)),
PassMode::ByRef { sized: false } => { PassMode::ByRef { size: None } => {
let (ptr, meta) = block_params.assert_pair(); let (ptr, meta) = block_params.assert_pair();
Some(CValue::by_ref_unsized(Pointer::new(ptr), meta, layout)) Some(CValue::by_ref_unsized(Pointer::new(ptr), meta, layout))
} }

View File

@ -9,7 +9,7 @@ pub(crate) fn can_return_to_ssa_var<'tcx>(tcx: TyCtxt<'tcx>, dest_layout: TyAndL
match get_pass_mode(tcx, dest_layout) { match get_pass_mode(tcx, dest_layout) {
PassMode::NoPass | PassMode::ByVal(_) => true, PassMode::NoPass | PassMode::ByVal(_) => true,
// FIXME Make it possible to return ByValPair and ByRef to an ssa var. // FIXME Make it possible to return ByValPair and ByRef to an ssa var.
PassMode::ByValPair(_, _) | PassMode::ByRef { sized: _ } => false PassMode::ByValPair(_, _) | PassMode::ByRef { size: _ } => false
} }
} }
@ -33,14 +33,14 @@ pub(super) fn codegen_return_param(
Empty Empty
} }
PassMode::ByRef { sized: true } => { PassMode::ByRef { size: Some(_) } => {
let ret_param = fx.bcx.append_block_param(start_block, fx.pointer_type); let ret_param = fx.bcx.append_block_param(start_block, fx.pointer_type);
fx.local_map fx.local_map
.insert(RETURN_PLACE, CPlace::for_ptr(Pointer::new(ret_param), ret_layout)); .insert(RETURN_PLACE, CPlace::for_ptr(Pointer::new(ret_param), ret_layout));
Single(ret_param) Single(ret_param)
} }
PassMode::ByRef { sized: false } => todo!(), PassMode::ByRef { size: None } => todo!(),
}; };
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
@ -69,11 +69,11 @@ pub(super) fn codegen_with_call_return_arg<'tcx, B: Backend, T>(
let output_pass_mode = get_pass_mode(fx.tcx, ret_layout); let output_pass_mode = get_pass_mode(fx.tcx, ret_layout);
let return_ptr = match output_pass_mode { let return_ptr = match output_pass_mode {
PassMode::NoPass => None, PassMode::NoPass => None,
PassMode::ByRef { sized: true } => match ret_place { PassMode::ByRef { size: Some(_)} => match ret_place {
Some(ret_place) => Some(ret_place.to_ptr().get_addr(fx)), Some(ret_place) => Some(ret_place.to_ptr().get_addr(fx)),
None => Some(fx.bcx.ins().iconst(fx.pointer_type, 43)), None => Some(fx.bcx.ins().iconst(fx.pointer_type, 43)), // FIXME allocate temp stack slot
}, },
PassMode::ByRef { sized: false } => todo!(), PassMode::ByRef { size: None } => todo!(),
PassMode::ByVal(_) | PassMode::ByValPair(_, _) => None, PassMode::ByVal(_) | PassMode::ByValPair(_, _) => None,
}; };
@ -94,8 +94,8 @@ pub(super) fn codegen_with_call_return_arg<'tcx, B: Backend, T>(
ret_place.write_cvalue(fx, CValue::by_val_pair(ret_val_a, ret_val_b, ret_layout)); ret_place.write_cvalue(fx, CValue::by_val_pair(ret_val_a, ret_val_b, ret_layout));
} }
} }
PassMode::ByRef { sized: true } => {} PassMode::ByRef { size: Some(_) } => {}
PassMode::ByRef { sized: false } => todo!(), PassMode::ByRef { size: None } => todo!(),
} }
(call_inst, meta) (call_inst, meta)
@ -103,10 +103,10 @@ pub(super) fn codegen_with_call_return_arg<'tcx, B: Backend, T>(
pub(crate) fn codegen_return(fx: &mut FunctionCx<'_, '_, impl Backend>) { pub(crate) fn codegen_return(fx: &mut FunctionCx<'_, '_, impl Backend>) {
match get_pass_mode(fx.tcx, return_layout(fx)) { match get_pass_mode(fx.tcx, return_layout(fx)) {
PassMode::NoPass | PassMode::ByRef { sized: true } => { PassMode::NoPass | PassMode::ByRef { size: Some(_) } => {
fx.bcx.ins().return_(&[]); fx.bcx.ins().return_(&[]);
} }
PassMode::ByRef { sized: false } => todo!(), PassMode::ByRef { size: None } => todo!(),
PassMode::ByVal(_) => { PassMode::ByVal(_) => {
let place = fx.get_local_place(RETURN_PLACE); let place = fx.get_local_place(RETURN_PLACE);
let ret_val = place.to_cvalue(fx).load_scalar(fx); let ret_val = place.to_cvalue(fx).load_scalar(fx);

View File

@ -313,6 +313,7 @@ impl<'tcx> DebugContext<'tcx> {
use cranelift_codegen::ir::ArgumentPurpose; use cranelift_codegen::ir::ArgumentPurpose;
let base_name = match param.purpose { let base_name = match param.purpose {
ArgumentPurpose::Normal => "arg", ArgumentPurpose::Normal => "arg",
ArgumentPurpose::StructArgument(_) => "struct_arg",
ArgumentPurpose::StructReturn => "sret", ArgumentPurpose::StructReturn => "sret",
ArgumentPurpose::Link | ArgumentPurpose::FramePointer | ArgumentPurpose::CalleeSaved => continue, ArgumentPurpose::Link | ArgumentPurpose::FramePointer | ArgumentPurpose::CalleeSaved => continue,
ArgumentPurpose::VMContext | ArgumentPurpose::SignatureId | ArgumentPurpose::StackLimit => unreachable!(), ArgumentPurpose::VMContext | ArgumentPurpose::SignatureId | ArgumentPurpose::StackLimit => unreachable!(),

View File

@ -74,12 +74,12 @@ $RUSTC example/mod_bench.rs --crate-type bin --target $TARGET_TRIPLE
pushd simple-raytracer pushd simple-raytracer
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
echo "[BENCH COMPILE] ebobby/simple-raytracer" echo "[BENCH COMPILE] ebobby/simple-raytracer"
hyperfine --runs ${RUN_RUNS:-10} --warmup 1 --prepare "rm -r target/*/debug || true" \ hyperfine --runs ${RUN_RUNS:-10} --warmup 1 --prepare "cargo clean" \
"RUSTFLAGS='' cargo build --target $TARGET_TRIPLE" \ "RUSTFLAGS='' cargo build" \
"../cargo.sh build" "../cargo.sh build"
echo "[BENCH RUN] ebobby/simple-raytracer" echo "[BENCH RUN] ebobby/simple-raytracer"
cp ./target/*/debug/main ./raytracer_cg_clif cp ./target/debug/main ./raytracer_cg_clif
hyperfine --runs ${RUN_RUNS:-10} ./raytracer_cg_llvm ./raytracer_cg_clif hyperfine --runs ${RUN_RUNS:-10} ./raytracer_cg_llvm ./raytracer_cg_clif
else else
echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)" echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)"