Skip to content

Commit 9e76c3e

Browse files
authored
Merge pull request #1068 from bjorn3/support_proc_macros
Pass ByRef values at fixed stack offset for extern "C"
2 parents ccfd1b9 + 942039b commit 9e76c3e

File tree

7 files changed

+60
-54
lines changed

7 files changed

+60
-54
lines changed

Cargo.lock

Lines changed: 22 additions & 22 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cargo.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,4 @@ fi
2020
cmd=$1
2121
shift
2222

23-
cargo +${TOOLCHAIN} $cmd --target $TARGET_TRIPLE $@
23+
cargo +${TOOLCHAIN} $cmd $@

src/abi/mod.rs

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ mod returning;
66
use rustc_target::spec::abi::Abi;
77
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
88

9-
use cranelift_codegen::ir::AbiParam;
9+
use cranelift_codegen::ir::{AbiParam, ArgumentPurpose};
1010

1111
use self::pass_mode::*;
1212
use crate::prelude::*;
@@ -123,7 +123,11 @@ fn clif_sig_from_fn_sig<'tcx>(
123123
if abi != Abi::Rust && abi != Abi::RustCall && abi != Abi::RustIntrinsic {
124124
match pass_mode {
125125
PassMode::NoPass | PassMode::ByVal(_) => {}
126-
PassMode::ByValPair(_, _) | PassMode::ByRef { sized: _ } => {
126+
PassMode::ByRef { size: Some(size) } => {
127+
let purpose = ArgumentPurpose::StructArgument(u32::try_from(size.bytes()).expect("struct too big to pass on stack"));
128+
return EmptySinglePair::Single(AbiParam::special(pointer_ty(tcx), purpose)).into_iter();
129+
}
130+
PassMode::ByValPair(_, _) | PassMode::ByRef { size: None } => {
127131
tcx.sess.span_warn(
128132
span,
129133
&format!(
@@ -137,34 +141,34 @@ fn clif_sig_from_fn_sig<'tcx>(
137141
}
138142
}
139143
}
140-
pass_mode.get_param_ty(tcx).into_iter()
144+
pass_mode.get_param_ty(tcx).map(AbiParam::new).into_iter()
141145
})
142146
.flatten();
143147

144148
let (mut params, returns): (Vec<_>, Vec<_>) = match get_pass_mode(
145149
tcx,
146150
tcx.layout_of(ParamEnv::reveal_all().and(output)).unwrap(),
147151
) {
148-
PassMode::NoPass => (inputs.map(AbiParam::new).collect(), vec![]),
152+
PassMode::NoPass => (inputs.collect(), vec![]),
149153
PassMode::ByVal(ret_ty) => (
150-
inputs.map(AbiParam::new).collect(),
154+
inputs.collect(),
151155
vec![AbiParam::new(ret_ty)],
152156
),
153157
PassMode::ByValPair(ret_ty_a, ret_ty_b) => (
154-
inputs.map(AbiParam::new).collect(),
158+
inputs.collect(),
155159
vec![AbiParam::new(ret_ty_a), AbiParam::new(ret_ty_b)],
156160
),
157-
PassMode::ByRef { sized: true } => {
161+
PassMode::ByRef { size: Some(_) } => {
158162
(
159163
Some(pointer_ty(tcx)) // First param is place to put return val
160164
.into_iter()
165+
.map(|ty| AbiParam::special(ty, ArgumentPurpose::StructReturn))
161166
.chain(inputs)
162-
.map(AbiParam::new)
163167
.collect(),
164168
vec![],
165169
)
166170
}
167-
PassMode::ByRef { sized: false } => todo!(),
171+
PassMode::ByRef { size: None } => todo!(),
168172
};
169173

170174
if requires_caller_location {

src/abi/pass_mode.rs

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub(super) enum PassMode {
77
NoPass,
88
ByVal(Type),
99
ByValPair(Type, Type),
10-
ByRef { sized: bool },
10+
ByRef { size: Option<Size> },
1111
}
1212

1313
#[derive(Copy, Clone, Debug)]
@@ -70,8 +70,8 @@ impl PassMode {
7070
PassMode::NoPass => Empty,
7171
PassMode::ByVal(clif_type) => Single(clif_type),
7272
PassMode::ByValPair(a, b) => Pair(a, b),
73-
PassMode::ByRef { sized: true } => Single(pointer_ty(tcx)),
74-
PassMode::ByRef { sized: false } => Pair(pointer_ty(tcx), pointer_ty(tcx)),
73+
PassMode::ByRef { size: Some(_) } => Single(pointer_ty(tcx)),
74+
PassMode::ByRef { size: None } => Pair(pointer_ty(tcx), pointer_ty(tcx)),
7575
}
7676
}
7777
}
@@ -93,16 +93,17 @@ pub(super) fn get_pass_mode<'tcx>(tcx: TyCtxt<'tcx>, layout: TyAndLayout<'tcx>)
9393
// Returning (i128, i128) by-val-pair would take 4 regs, while only 3 are
9494
// available on x86_64. Cranelift gets confused when too many return params
9595
// are used.
96-
PassMode::ByRef { sized: true }
96+
PassMode::ByRef { size: Some(layout.size) }
9797
} else {
9898
PassMode::ByValPair(a, b)
9999
}
100100
}
101101

102102
// FIXME implement Vector Abi in a cg_llvm compatible way
103-
Abi::Vector { .. } => PassMode::ByRef { sized: true },
103+
Abi::Vector { .. } => PassMode::ByRef { size: Some(layout.size) },
104104

105-
&Abi::Aggregate { sized } => PassMode::ByRef { sized },
105+
Abi::Aggregate { sized: true } => PassMode::ByRef { size: Some(layout.size) },
106+
Abi::Aggregate { sized: false } => PassMode::ByRef { size: None },
106107
}
107108
}
108109
}
@@ -118,7 +119,7 @@ pub(super) fn adjust_arg_for_abi<'tcx>(
118119
let (a, b) = arg.load_scalar_pair(fx);
119120
Pair(a, b)
120121
}
121-
PassMode::ByRef { sized: _ } => {
122+
PassMode::ByRef { size: _ } => {
122123
match arg.force_stack(fx) {
123124
(ptr, None) => Single(ptr.get_addr(fx)),
124125
(ptr, Some(meta)) => Pair(ptr.get_addr(fx), meta),
@@ -164,8 +165,8 @@ pub(super) fn cvalue_for_param<'tcx>(
164165
let (a, b) = block_params.assert_pair();
165166
Some(CValue::by_val_pair(a, b, layout))
166167
}
167-
PassMode::ByRef { sized: true } => Some(CValue::by_ref(Pointer::new(block_params.assert_single()), layout)),
168-
PassMode::ByRef { sized: false } => {
168+
PassMode::ByRef { size: Some(_) } => Some(CValue::by_ref(Pointer::new(block_params.assert_single()), layout)),
169+
PassMode::ByRef { size: None } => {
169170
let (ptr, meta) = block_params.assert_pair();
170171
Some(CValue::by_ref_unsized(Pointer::new(ptr), meta, layout))
171172
}

src/abi/returning.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ pub(crate) fn can_return_to_ssa_var<'tcx>(tcx: TyCtxt<'tcx>, dest_layout: TyAndL
99
match get_pass_mode(tcx, dest_layout) {
1010
PassMode::NoPass | PassMode::ByVal(_) => true,
1111
// FIXME Make it possible to return ByValPair and ByRef to an ssa var.
12-
PassMode::ByValPair(_, _) | PassMode::ByRef { sized: _ } => false
12+
PassMode::ByValPair(_, _) | PassMode::ByRef { size: _ } => false
1313
}
1414
}
1515

@@ -33,14 +33,14 @@ pub(super) fn codegen_return_param(
3333

3434
Empty
3535
}
36-
PassMode::ByRef { sized: true } => {
36+
PassMode::ByRef { size: Some(_) } => {
3737
let ret_param = fx.bcx.append_block_param(start_block, fx.pointer_type);
3838
fx.local_map
3939
.insert(RETURN_PLACE, CPlace::for_ptr(Pointer::new(ret_param), ret_layout));
4040

4141
Single(ret_param)
4242
}
43-
PassMode::ByRef { sized: false } => todo!(),
43+
PassMode::ByRef { size: None } => todo!(),
4444
};
4545

4646
#[cfg(not(debug_assertions))]
@@ -69,11 +69,11 @@ pub(super) fn codegen_with_call_return_arg<'tcx, B: Backend, T>(
6969
let output_pass_mode = get_pass_mode(fx.tcx, ret_layout);
7070
let return_ptr = match output_pass_mode {
7171
PassMode::NoPass => None,
72-
PassMode::ByRef { sized: true } => match ret_place {
72+
PassMode::ByRef { size: Some(_)} => match ret_place {
7373
Some(ret_place) => Some(ret_place.to_ptr().get_addr(fx)),
74-
None => Some(fx.bcx.ins().iconst(fx.pointer_type, 43)),
74+
None => Some(fx.bcx.ins().iconst(fx.pointer_type, 43)), // FIXME allocate temp stack slot
7575
},
76-
PassMode::ByRef { sized: false } => todo!(),
76+
PassMode::ByRef { size: None } => todo!(),
7777
PassMode::ByVal(_) | PassMode::ByValPair(_, _) => None,
7878
};
7979

@@ -94,19 +94,19 @@ pub(super) fn codegen_with_call_return_arg<'tcx, B: Backend, T>(
9494
ret_place.write_cvalue(fx, CValue::by_val_pair(ret_val_a, ret_val_b, ret_layout));
9595
}
9696
}
97-
PassMode::ByRef { sized: true } => {}
98-
PassMode::ByRef { sized: false } => todo!(),
97+
PassMode::ByRef { size: Some(_) } => {}
98+
PassMode::ByRef { size: None } => todo!(),
9999
}
100100

101101
(call_inst, meta)
102102
}
103103

104104
pub(crate) fn codegen_return(fx: &mut FunctionCx<'_, '_, impl Backend>) {
105105
match get_pass_mode(fx.tcx, return_layout(fx)) {
106-
PassMode::NoPass | PassMode::ByRef { sized: true } => {
106+
PassMode::NoPass | PassMode::ByRef { size: Some(_) } => {
107107
fx.bcx.ins().return_(&[]);
108108
}
109-
PassMode::ByRef { sized: false } => todo!(),
109+
PassMode::ByRef { size: None } => todo!(),
110110
PassMode::ByVal(_) => {
111111
let place = fx.get_local_place(RETURN_PLACE);
112112
let ret_val = place.to_cvalue(fx).load_scalar(fx);

src/debuginfo/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ impl<'tcx> DebugContext<'tcx> {
313313
use cranelift_codegen::ir::ArgumentPurpose;
314314
let base_name = match param.purpose {
315315
ArgumentPurpose::Normal => "arg",
316+
ArgumentPurpose::StructArgument(_) => "struct_arg",
316317
ArgumentPurpose::StructReturn => "sret",
317318
ArgumentPurpose::Link | ArgumentPurpose::FramePointer | ArgumentPurpose::CalleeSaved => continue,
318319
ArgumentPurpose::VMContext | ArgumentPurpose::SignatureId | ArgumentPurpose::StackLimit => unreachable!(),

test.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,12 @@ $RUSTC example/mod_bench.rs --crate-type bin --target $TARGET_TRIPLE
7474
pushd simple-raytracer
7575
if [[ "$HOST_TRIPLE" = "$TARGET_TRIPLE" ]]; then
7676
echo "[BENCH COMPILE] ebobby/simple-raytracer"
77-
hyperfine --runs ${RUN_RUNS:-10} --warmup 1 --prepare "rm -r target/*/debug || true" \
78-
"RUSTFLAGS='' cargo build --target $TARGET_TRIPLE" \
77+
hyperfine --runs ${RUN_RUNS:-10} --warmup 1 --prepare "cargo clean" \
78+
"RUSTFLAGS='' cargo build" \
7979
"../cargo.sh build"
8080

8181
echo "[BENCH RUN] ebobby/simple-raytracer"
82-
cp ./target/*/debug/main ./raytracer_cg_clif
82+
cp ./target/debug/main ./raytracer_cg_clif
8383
hyperfine --runs ${RUN_RUNS:-10} ./raytracer_cg_llvm ./raytracer_cg_clif
8484
else
8585
echo "[BENCH COMPILE] ebobby/simple-raytracer (skipped)"

0 commit comments

Comments
 (0)