x64 and aarch64: allow StructArgument and StructReturn args.

The StructReturn ABI is fairly simple at the codegen/isel level: we only
need to take care to return the sret pointer as one of the return values
if that wasn't specified in the initial function signature.

Struct arguments are a little more complex. A struct argument is stored
as a chunk of memory in the stack-args space. However, the CLIF
semantics are slightly special: on the caller side, the parameter passed
in is a pointer to an arbitrary memory block, and we must memcpy this
data to the on-stack struct-argument; and on the callee side, we provide
a pointer to the passed-in struct-argument as the CLIF block param
value.

This is necessary to support various ABIs other than Wasm, such as that
of Rust (with the cg_clif codegen backend).
This commit is contained in:
Chris Fallin
2020-12-13 18:50:59 -08:00
parent 25088dee9d
commit 456561f431
14 changed files with 641 additions and 166 deletions

View File

@@ -81,12 +81,12 @@ impl ABIMachineSpec for Arm32MachineDeps {
if next_rreg < max_reg_val {
let reg = rreg(next_rreg);
ret.push(ABIArg::Reg(
ValueRegs::one(reg.to_real_reg()),
param.value_type,
param.extension,
param.purpose,
));
ret.push(ABIArg::Reg {
regs: ValueRegs::one(reg.to_real_reg()),
ty: param.value_type,
extension: param.extension,
purpose: param.purpose,
});
next_rreg += 1;
} else {
// Arguments are stored on stack in reversed order.
@@ -101,12 +101,12 @@ impl ABIMachineSpec for Arm32MachineDeps {
let extra_arg = if add_ret_area_ptr {
debug_assert!(args_or_rets == ArgsOrRets::Args);
if next_rreg < max_reg_val {
ret.push(ABIArg::Reg(
ValueRegs::one(rreg(next_rreg).to_real_reg()),
I32,
ir::ArgumentExtension::None,
ir::ArgumentPurpose::Normal,
));
ret.push(ABIArg::Reg {
regs: ValueRegs::one(rreg(next_rreg).to_real_reg()),
ty: I32,
extension: ir::ArgumentExtension::None,
purpose: ir::ArgumentPurpose::Normal,
});
} else {
stack_args.push((
I32,
@@ -124,12 +124,12 @@ impl ABIMachineSpec for Arm32MachineDeps {
let max_stack = next_stack;
for (ty, ext, purpose) in stack_args.into_iter().rev() {
next_stack -= 4;
ret.push(ABIArg::Stack(
(max_stack - next_stack) as i64,
ret.push(ABIArg::Stack {
offset: (max_stack - next_stack) as i64,
ty,
ext,
extension: ext,
purpose,
));
});
}
assert_eq!(next_stack, 0);
@@ -426,6 +426,15 @@ impl ABIMachineSpec for Arm32MachineDeps {
insts
}
fn gen_memcpy(
_call_conv: isa::CallConv,
_dst: Reg,
_src: Reg,
_size: usize,
) -> SmallVec<[Self::I; 8]> {
unimplemented!("StructArgs not implemented for ARM32 yet");
}
fn get_number_of_spillslots_for_value(rc: RegClass, _ty: Type) -> u32 {
match rc {
RegClass::I32 => 1,