issue-0036: 16-byte integer-only struct by value trips LLVM verifier
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.
This commit is contained in:
38
examples/issue-0036.sx
Normal file
38
examples/issue-0036.sx
Normal file
@@ -0,0 +1,38 @@
|
||||
// 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;
|
||||
}
|
||||
Reference in New Issue
Block a user