Struct parameters being converted to other types

(I previously asked this question on the llvm-dev mailing list. Someone suggested that I ask on cfe-dev instead.)

In a project I'm working on, functions are being read in from LLVM bitcode, and then LLVM is being used to generate code that calls those functions.

When a function with a struct parameter or return type is compiled with `clang -O0 -emit-llvm`, the resulting bitcode varies greatly depending on the type of struct.

For example, Clang may lower a struct parameter into...

  - a "byval" pointer (for a struct with several different members)
  - a vector (for a struct with a few float members)
  - two doubles (for a struct with two double members)
  - an i64 (for a struct with two i32 members)

... and possibly more variations.

When calling a function that takes a struct argument, I'm having to convert the argument value (the original struct type) to match the parameter type (which could be any of the above variations).

Is there a way to avoid generating all these variations? For example, is there a Clang argument that would cause all structs to be passed as "byval" pointers?

Hi Jaymie,

Is there a way to avoid generating all these variations? For example, is there a Clang argument that would cause all structs to be passed as "byval" pointers?

I believe not. These machinations are necessary to conform to the ABI
in question; picking any single one of those would almost certainly
give code that doesn't interoperate with other compilers or libraries.

If you really don't care about that, your best option would probably
be to implement an intentionally simpler ABI in Clang. This is all
decided for the various targets in lib/CodeGen/TargetInfo.cpp. Beware
that the LLVM backend may not be expecting this "simpler" system, so
you could encounter more errors there. And you'd almost certainly
break variadic functions, if they matter to you.

Cheers.

Tim.

Thanks for the suggestion, Tim. I got a little better sense of what is going on by looking at lib/CodeGen/TargetInfo.cpp and lib/CodeGen/CodeGenTypes.cpp.

Is there any documentation on implementing an ABI? Would an ABI have to be implemented for each supported OS / architecture? I'm trying to estimate how long this would take.

Is there any documentation on implementing an ABI?

Not really. Mostly you have a document which lays down precisely which
registers and stack slots any type should be passed in (for example
the AArch64 one is at
Documentation – Arm Developer).
You then hammer out a compromise where Clang sends enough information
along with the arguments that the LLVM code can make the right choices
without itself being too complicated.

Your situation is a little different though. It sounds like your goal
is to make these ABI bits as simple as possible and cope with the
fallout elsewhere. In fact, it looks like you might be able to make
use of the existing definitions in the DefaultABIInfo class. It seems
to take care of the places I know dragons exist.

Would an ABI have to be implemented for each supported
OS / architecture? I'm trying to estimate how long this would take.

In principle just one could work, and then be reused. You'd have to
work through any backend bugs coming from emitting slightly odd code
in each case, of course.

I'll just point out again that taking route will divorce you from any
support the OS or its libraries could provide: there will be no
printf, no fopen, no nothing unless you carefully wrap them up in
functions that use your new ABI.

Tim.