[llvm-dev] Current preferred approach for handling 'byval' struct arguments

Alex Bradbury via llvm-dev llvm-dev at lists.llvm.org
Wed Mar 8 01:02:52 PST 2017


On 7 March 2017 at 17:58, Reid Kleckner <rnk at google.com> wrote:
> Today, the vast majority of target in Clang coerce aggregates passed this
> way into appropriate word-sized types. They all use their own custom
> heuristics to compute the LLVM types used for the coercions. It's terrible,
> but this is the current consensus.
>
> I would like to improve the situation so that passing LLVM aggregates
> directly does the right thing when the LLVM struct type and C struct type
> are effectively the same, so that custom frontend lowering is required for
> hard cases involving things like _Complex and unions.

Thanks for the response Reid. Looking more closely, it appears that
the relationship between the target's ABI and whether aggregates are
represented as byval structs, and whether these are coerced to
something else in Clang's ABI handling)is more complex than I first
described.

For instance, looking at X86 code in clang/lib/CodeGen/TargetInfo.cpp
I see that small aggregates are coerced as long as all argument
registers are known to be used (i.e. we know the backend will place it
on the stack, as demanded by the calling convention). ARM will also
coerce structures below a certain size, however the call lowering code
in ARMISelLowering still has logic to split a byval aggregate between
the stack and registers (why not  I have to say looking at
AArch64ISelLowering and the clang code it's not immediately obvious to
me where aggregates get split between the stack and registers (which
is quite clear in MipsTargetLowering::passByValArg). What am I missing
here?

It seems to me there are a few possibilities for targets where the ABI
indicates aggregates may be passed in registers:
* Clang always passes aggregates as byval, LLVM call lowering may
assign some or all of the aggregate to registers. Seemingly nobody
does this
* Clang's ABI lowering code is aware of how many argument registers
have been used. If they have been exhausted, then leave the aggregate
as byval. If aggregate will be partially in registers and partially on
the stack, then coerce to two arguments - one byval and one direct.
Seemingly nobody does this.
* Split responsibilities between the Clang ABI lowering and the LLVM
backend lowering. If an aggregate is below a certain size, then coerce
and pass it direct. Depending on the ABI, the LLVM backend still has
the possibility that a byval aggregate may be passed partially in
registers and the stack and should handle that appropriately. This
seems to be more common

Best,

Alex


More information about the llvm-dev mailing list