Surfaced while writing the ffi-02-small-struct.sx baseline. The sx
#foreign decl lowers `{ s64, s64 }` (and other 16-byte integer-only
shapes like `{ s32, s32, s32, s32 }`) to `[2 x i64]` for the small-
struct register-pair ABI on AAPCS64 / SysV AMD64, but the call site
loads the struct as `{ i64, i64 }`. The two types must agree for the
LLVM verifier to accept the call:
Call parameter type does not match function signature!
%load = load { i64, i64 }, ptr %alloca, align 8
[2 x i64] %call = call [2 x i64] @issue0036_swap({ i64, i64 } %load)
Float-only 16-byte aggregates (e.g. Vec4f) work because they route
through the HFA path which keeps the struct representation. See
examples/ffi-02-small-struct.sx for the working cases.
Phase 1's #foreign lowering rework is the natural place to unify
these representations; check there before fixing inline.
39 lines
1.3 KiB
Plaintext
39 lines
1.3 KiB
Plaintext
// 16-byte integer-only struct by value through `#foreign` trips
|
||
// the LLVM verifier:
|
||
//
|
||
// Call parameter type does not match function signature!
|
||
// %loadN = load { i64, i64 }, ptr %allocaM, align 8
|
||
// [2 x i64] %callN = call [2 x i64] @issue0036_swap({ i64, i64 } %load...)
|
||
//
|
||
// The foreign-decl side lowers `Pair64` to `[2 x i64]` (ABI-coercion
|
||
// for the small-struct register-pair return on AAPCS64 / SysV AMD64),
|
||
// while the call site loads the sx struct as `{ i64, i64 }`. The two
|
||
// representations need to agree.
|
||
//
|
||
// Float-only aggregates of the same total size (e.g. Vec4f, 4×f32 =
|
||
// 16 B) work today because they're routed through the HFA path which
|
||
// keeps the struct representation. See `examples/ffi-02-small-struct.sx`
|
||
// for the working cases.
|
||
//
|
||
// Expected once fixed: print "ok = true" with exit 0. Today this
|
||
// example fails at codegen with a non-zero exit; the snapshot captures
|
||
// that failure so the test suite stays honest.
|
||
|
||
#import "modules/std.sx";
|
||
|
||
#import c {
|
||
#source "vendors/issue_0036/issue_0036.c";
|
||
};
|
||
|
||
Pair64 :: struct { a: s64; b: s64; }
|
||
|
||
issue0036_swap :: (p: Pair64) -> Pair64 #foreign;
|
||
|
||
main :: () -> s32 {
|
||
p : Pair64 = .{ a = 1, b = 2 };
|
||
q := issue0036_swap(p);
|
||
print("swap = ({}, {})\n", q.a, q.b);
|
||
print("ok = {}\n", q.a == 2 and q.b == 1);
|
||
0;
|
||
}
|