[cfe-dev] [llvm-dev] RFC: Implementing the Swift calling convention in LLVM and Clang

John McCall via cfe-dev cfe-dev at lists.llvm.org
Thu Mar 3 13:08:36 PST 2016


> On Mar 3, 2016, at 10:06 AM, Renato Golin <renato.golin at linaro.org> wrote:
> On 3 March 2016 at 17:36, John McCall <rjmccall at apple.com> wrote:
>> I’m not sure of your point here.  We don’t use the Swift CC to call C functions.
>> It does not matter, at all, whether the frontend lowering of an aggregate under
>> the Swift CC resembles the frontend lowering of the same aggregate under AAPCS.
> 
> Right, ignore me, then.
> 
> 
>> I’m not sure why you say that.  We already do have parameter ABI override
>> attributes with target-specific behavior in LLVM IR: sret and inreg.
> 
> Their meaning is somewhat confused and hard-coded in the back-end. I
> once wanted to use inreg for lowering register-based divmod in
> SelectionDAG, but ended up implementing custom lowering in the ARM
> back-end because inreg wasn't used correctly. It's possible that now
> it's better, but you'll always be at the mercy of what the back-end
> does with the attributes, especially in custom lowering.
> 
> Also, for different back-ends, "inreg" means different things. If the
> PCS allows multiple argument/return registers, then sret inreg is
> possible for a structure with up to X/Y words, where X and Y are
> different for different targets and could very well be zero.
> 
> Example, in a machine with *two* PCS registers:
> 
> i64 @foo (i32)
> 
> returning in registers becomes: sret { i32, i32 } @foo (inreg i32)
> 
> then you add your error: sret { i32, i32, i8* } @foo (inreg i32, inreg i8*)
> 
> You can fit the two arguments in registers, but you can't fit the
> result + error in your sret.
> 
> Targets will have to deal with that in the DAG, if you don't do that
> in IR. The ARM target would put the error pointer in the stack, which
> is not where you want it to go.
> 
> You'd probably need a way to mark portions of your sret as *must be
> inreg* and others to be "nice to be inreg", so that you can spill the
> result and not the error, if that's what you want.

Right, this is one very good reason I would prefer to keep the error-result
modelled as a parameter rather than mixing it in with the return value.

Also, recall that the error-result is supposed to be assigned to a register
that isn’t normally used for return values (or arguments, for that matter).

>> Having that sort of ability might make some special cases easier for C lowering,
>> too, come to think of it.  Imagine an x86 ABI that — based on type information
>> otherwise erased by the conversion to LLVM IR — sometimes returns a float in
>> an SSE register and sometimes on the x86 stack.  It would be very awkward to
>> express that today, but some sort of abi(“x87”) attribute would make it easy.
> 
> If this is kept in Swift PCS only, and if the compiler always agree on
> which registers you're using, that's ok.
> 
> But if you call a C function, or a new version of LLVM decides to use
> a different register, you'll have run-time problems.

A new version of LLVM really can’t just decide to use a different register
once there’s an agreed interpretation.  It sounds like the problem you were
running into with “inreg” was that the ARM backend didn’t have a stable meaning
for it, probably because the ARM target doesn’t allow the frontend features
(regparm/sseregparm) that inreg is designed for.  But there are targets — i386,
chiefly — where inreg has a defined, stable meaning precisely because regparm
has a defined, stable meaning.  It seems to me that an abi(“context”) attribute
would be more like the latter than the former: any target that supports swiftcc
would also have to assign a stable meaning for abi(“context”).

John.


> 
> That's why ARM has different standards for hard and soft float, which
> cannot mix.
> 
> cheers,
> --renato



More information about the cfe-dev mailing list