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

Alex Bradbury via llvm-dev llvm-dev at lists.llvm.org
Sat Mar 18 08:37:27 PDT 2017


On 8 March 2017 at 09:02, Alex Bradbury <asb at asbradbury.org> wrote:
> 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.

There are also tradeoffs for passing large scalar values, which I
thought I'd share here in case it's useful for someone else (and
indeed, if anyone has extra input).

In the RISC-V calling convention, large scalars (larger than 2 GPRs)
are passed indirect, just like large aggregates. e.g. an i128 or a
long double on a 32-bit platform. It's tempting to let the frontend
emit i128 and fp128 arguments/return values, however making the
argument indirect is somewhat easier in the frontend. This is because
by the time you get to the LLVM CC code the type has already been
legalised and so converted to a series of word-sized values. You can
detect that the arguments were formed by splitting a larger value and
fix it up so it all works properly (see CC_SystemZ_I128Indirect in
SystemZCallingConv.h) but this is more hassle than just having the
frontend pass it indirect in the first place. When return values have
the same rules, meaning an implicit parameter has to be generated it's
even more complex (in fact it's not immediately obvious to me how to
do that in a tablegen-based calling convention implementation).

Best,

Alex


More information about the llvm-dev mailing list