AdeptLanguage / Adept

The Adept Programming Language
GNU General Public License v3.0
122 stars 9 forks source link

Passing struct by value to a foreign function does not work properly #342

Open Apis035 opened 6 months ago

Apis035 commented 6 months ago

...And may crash the program. But passing by reference does work properly.

While passing struct by value:

Example C library:

typedef struct {int a, b, c} i3;

void checkByRef(i3 *s) { printf("%d, %d, %d\n", s->a, s->b, s->c); }
void checkByVal(i3 s)  { printf("%d, %d, %d\n", s.a, s.b, s.c); }

Adept:

record i3(a, b, c int)

foreign checkByRef(s *i3) void
foreign checkByVal(s i3) void

func main {
    v i3 = i3(1, 2, 3)
    checkByRef(&v) // Ok
    checkByVal(v)  // Crash
}

Test case

Related issue to discussion #337. Luckily, that problem can be resolved because the 4 ubyte struct is packed into a single int.

IsaacShelton commented 6 months ago

Yes, apparently clang has around 12,000+ lines of gymnastics to get around this problem.

https://github.com/llvm/llvm-project/blob/5e691a1c9b0ad22689d4a434ddf4fed940e58dec/clang/lib/CodeGen/TargetInfo.cpp#L5816-L5823

The structs are passed differently for each architecture and os. Sometimes, values are passed in vector registers, sometimes in integer registers (even if the value is a float), sometimes combining multiple floats into a single integer register, sometimes breaking structs into multiple "args" which are passed as registers, sometimes returning structures by out pointers, sometimes passing some fields in one way and others in another, and lots more. And all of this is architecture and os dependent.

I've been looking at different ways to handle this, but it might be awhile as you can probably understand, given that it will require thousands of lines of nonsensical magic.