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

edA-qa mort-ora-y via llvm-dev llvm-dev at lists.llvm.org
Sun Apr 22 07:29:16 PDT 2018


Super, that clarifies a lot what happens.  And yes, it's been a
challenge calling C APIs with by-value structures, but I think I've got
it working now, at least on x86_64 Linux.

If I understood correctly, when llvm sees a struct like `foo = { i8,
i64, float }` and then a function like `bar( %foo )` it is the same as
the function `bar( i8, i64, float )`?  Is the call guaranteed to be byte
compatible, or should I not rely on it (I don't of course).

What is the reason that `byval` requires a pointer type, as opposed to
being able to take a value type?  It's forcing me to copy values into an
alloca memory, which I presume will then just be copied again on to the
stack -- looking at the optimized output the redundancy is not disappearing.


On 22/04/18 14:46, Tim Northover wrote:
> 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.
>

-- 
edA-qa mort-ora-y  
	http://mortoray.com/

Creator of the Leaf language
	http://leaflang.org/

Streaming algorithms, AI, and design on Twitch
	https://www.twitch.tv/mortoray

Twitter
	edaqa
	



More information about the llvm-dev mailing list