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

Alex Bradbury via llvm-dev llvm-dev at lists.llvm.org
Sat Mar 18 09:10:16 PDT 2017


On 18 March 2017 at 15:37, Alex Bradbury <asb at asbradbury.org> wrote:
> 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).

Sorry to respond to myself again so soon, but as usual I've spotted
another issue. libcalls (e.g. fp128 equality) will be emitted in
TargetLowering, which won't do the necessary pass-indirect conversion
for you. Therefore the following C would generate something sensible:
`long double f_fp_scalar_3(long double x) { return x; }`. But if your
code tries to do anything with fp128 values (e.g. `fcmp une fp128 %1,
%2` gets generated), you're stuck. I think I'm now understanding why
the SystemZ backend make the choices it did.

Best,

Alex


More information about the llvm-dev mailing list