Files
sx/examples/issue-0036.sx
agra 36e929101b 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.
2026-05-19 11:22:56 +03:00

39 lines
1.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 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;
}