[llvm-dev] Difference between "byval" and actually passing by value?

Tim Northover via llvm-dev llvm-dev at lists.llvm.org
Sun Apr 22 05:46:41 PDT 2018


Hi,

On 22 April 2018 at 06:34, edA-qa mort-ora-y via llvm-dev
<llvm-dev at lists.llvm.org> wrote:
> They are not compatible with each other yet logically do the same
> thing.  The second form is the one that appears to work with the ABI on
> linux, and the first one not.
>
> What is the reason for the difference?

If you pass a struct directly, the LLVM target will just see an
exploded list of the basic types (e.g. i8, i8, i32, ...) and have to
classsify them individually. This is usually too simplistic to model a
real C ABI, so it's not used much. But LLVM does have to give it some
meaning because it's still a legitimate IR function. The result is
that you tend to get the arguments out again if everything is
consistent, but where they actually get passed is a bit random.

A byval parameter is usually used to model a struct that gets passed
on the stack; the target sees the size & alignment constraints, but
not each individual sub-type. This is often actually used in C ABIs
for a couple of reasons. First, the extra alignment parameter lets you
pass structs with above-natural alignment correctly. Second, because
the type actually is in memory, you tend to get a cleaner mapping from
IR to machine instructions if the IR is represented that way. Of
course, peepholes could probably fix a lot of that if we really cared.

For structs that get passed in registers, the front-ends tend to
coerce them to some type with the same constraints (register type,
size, alignment, ...) in a pretty ad-hoc manner when emitting IR.
That's actually responsible for a lot of the difficulty in calling C
code from LLVM.

Cheers.

Tim.


More information about the llvm-dev mailing list