[s390x, abi_impl] Support struct args using explicit pointers (#4585)

This adds support for StructArgument on s390x.  The ABI for this
platform requires that the address of the buffer holding the copy
of the struct argument is passed from caller to callee as hidden
pointer, using a register or overflow stack slot.

To implement this, I've added an optional "pointer" filed to
ABIArg::StructArg, and code to handle the pointer both in common
abi_impl code and the s390x back-end.

One notable change necessary to make this work involved the
"copy_to_arg_order" mechanism.  Currently, for struct args
we only need to copy the data (and that need to happen before
setting up any other args), while for non-struct args we only
need to set up the appropriate registers or stack slots.
This order is ensured by sorting the arguments appropriately
into a "copy_to_arg_order" list.

However, for struct args with explicit pointers we need to *both*
copy the data (again, before everything else), *and* set up a
register or stack slot.  Since we now need to touch the argument
twice, we cannot solve the ordering problem by a simple sort.
Instead, the abi_impl common code now provided *two* callbacks,
emit_copy_regs_to_buffer and emit_copy_regs_to_arg, and expects
the back end to first call copy..to_buffer for all args, and
then call copy.._to_arg for all args.  This required updates
to all back ends.

In the s390x back end, in addition to the new ABI code, I'm now
adding code to actually copy the struct data, using the MVC
instruction (for small buffers) or a memcpy libcall (for larger
buffers).  This also requires a bit of new infrastructure:
- MVC is the first memory-to-memory instruction we use, which
  needed a bit of memory argument tweaking
- We also need to set up the infrastructure to emit libcalls.

(This implements the first half of issue #4565.)
This commit is contained in:
Ulrich Weigand
2022-08-03 21:00:07 +02:00
committed by GitHub
parent a897742593
commit b9dd48e34b
18 changed files with 687 additions and 152 deletions

View File

@@ -195,6 +195,8 @@ pub trait ABICaller {
fn signature(&self) -> &Signature;
/// Emit a copy of an argument value from a source register, prior to the call.
/// For large arguments with associated stack buffer, this may load the address
/// of the buffer into the argument register, if required by the ABI.
fn emit_copy_regs_to_arg<C: LowerCtx<I = Self::I>>(
&self,
ctx: &mut C,
@@ -202,10 +204,17 @@ pub trait ABICaller {
from_reg: ValueRegs<Reg>,
);
/// Specific order for copying into arguments at callsites. We must be
/// careful to copy into StructArgs first, because we need to be able
/// to invoke memcpy() before we've loaded other arg regs (see above).
fn get_copy_to_arg_order(&self) -> SmallVec<[usize; 8]>;
/// Emit a copy of a large argument into its associated stack buffer, if any.
/// We must be careful to perform all these copies (as necessary) before setting
/// up the argument registers, since we may have to invoke memcpy(), which could
/// clobber any registers already set up. The back-end should call this routine
/// for all arguments before calling emit_copy_regs_to_arg for all arguments.
fn emit_copy_regs_to_buffer<C: LowerCtx<I = Self::I>>(
&self,
ctx: &mut C,
idx: usize,
from_reg: ValueRegs<Reg>,
);
/// Emit a copy a return value into a destination register, after the call returns.
fn emit_copy_retval_to_regs<C: LowerCtx<I = Self::I>>(