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:
@@ -375,8 +375,9 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
|
||||
}
|
||||
}
|
||||
|
||||
let vm_context = f
|
||||
.signature
|
||||
let vm_context = vcode
|
||||
.abi()
|
||||
.signature()
|
||||
.special_param_index(ArgumentPurpose::VMContext)
|
||||
.map(|vm_context_index| {
|
||||
let entry_block = f.layout.entry_block().unwrap();
|
||||
@@ -386,7 +387,7 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
|
||||
|
||||
// Assign vreg(s) to each return value.
|
||||
let mut retval_regs = vec![];
|
||||
for ret in &f.signature.returns {
|
||||
for ret in &vcode.abi().signature().returns.clone() {
|
||||
let regs = alloc_vregs(ret.value_type, &mut next_vreg, &mut vcode)?;
|
||||
retval_regs.push(regs);
|
||||
debug!("retval gets regs {:?}", regs);
|
||||
@@ -465,6 +466,24 @@ impl<'func, I: VCodeInst> Lower<'func, I> {
|
||||
for insn in self.vcode.abi().gen_copy_arg_to_regs(i, regs).into_iter() {
|
||||
self.emit(insn);
|
||||
}
|
||||
if self.abi().signature().params[i].purpose == ArgumentPurpose::StructReturn {
|
||||
assert!(regs.len() == 1);
|
||||
let ty = self.abi().signature().params[i].value_type;
|
||||
// The ABI implementation must have ensured that a StructReturn
|
||||
// arg is present in the return values.
|
||||
let struct_ret_idx = self
|
||||
.abi()
|
||||
.signature()
|
||||
.returns
|
||||
.iter()
|
||||
.position(|ret| ret.purpose == ArgumentPurpose::StructReturn)
|
||||
.expect("StructReturn return value not present!");
|
||||
self.emit(I::gen_move(
|
||||
Writable::from_reg(self.retval_regs[struct_ret_idx].regs()[0]),
|
||||
regs.regs()[0].to_reg(),
|
||||
ty,
|
||||
));
|
||||
}
|
||||
}
|
||||
if let Some(insn) = self.vcode.abi().gen_retval_area_setup() {
|
||||
self.emit(insn);
|
||||
|
||||
Reference in New Issue
Block a user