Files
sx/examples/1331-ffi-objc-call-05-struct-returns.sx
agra 4e942b5373 test: migrate examples to XXXX-category-name layout + split expected streams
Rename all example tests/companions to the XXXX-category-test-name scheme
(per-category 100-blocks: basic 0010, types 0100, ... errors 1000,
diagnostics 1100, ffi 1200, ffi-objc 1300, ffi-jni 1400, vectors 1500,
platform 1600). Companions and dir/C fixtures move in lockstep with their
parent test; #import/#source/#include paths rewritten to match.

Expected output now lives in examples/expected/ (a sibling dir of the
tests) split into three streams per the new convention:
  <name>.exit / <name>.stdout / <name>.stderr  (+ optional <name>.ir)

run_examples.sh rewritten: scans examples/ and issues/ for an
expected/<name>.exit marker, captures stdout and stderr separately (no
more 2>&1), compares each stream + exit + optional IR snapshot.

Behavior validated unchanged: every renamed test reproduces its prior
merged output + exit (diffs limited to file paths/basenames embedded in
diagnostics + traces, which correctly reflect the new names). Suite:
292 passed, 0 failed. 50-smoke.sx split + issue relocation + docs follow
in subsequent commits.
2026-06-01 19:05:15 +03:00

52 lines
1.9 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.
// Phase 1 step 1.7 (PLAN-FFI.md): struct returns through
// `#objc_call`. emit_llvm's `objc_msg_send` arm hands the IR
// struct type straight to LLVMBuildCall2; the AArch64 / SysV
// AMD64 backend handles the register-pair / HFA / byval+sret
// lowering as long as the function type at the call site is
// the precise IR struct type.
//
// Obj-C runtime contract: `[nil structMethod]` returns a
// zero-initialized struct of the return type. Lets us pin the
// ABI without constructing a real object graph.
#import "modules/std.sx";
#import "modules/compiler.sx";
// 16 B HFA (Apple ARM64 — 2×f64 stays in v0/v1, SysV AMD64 — in xmm0/xmm1).
NSPoint :: struct { x: f64; y: f64; }
// 16 B integer aggregate (Apple ARM64 — x0/x1 register pair, coerced
// via `[2 x i64]` in our foreign-decl path; same trip-up that
// issue-0036 surfaced).
NSRange :: struct { location: u64; length: u64; }
// 32 B HFA (Apple ARM64 — 4×f64 stays in v0..v3). NSRect / CGRect
// shape. The plan singles this out because >16 B is the sret cliff
// for *integer* aggregates, but HFAs of any size up to v0..v3 stay
// register-resident; that distinction is what we want to lock in.
NSRect :: struct {
x: f64; y: f64; width: f64; height: f64;
}
main :: () -> s32 {
inline if OS == .macos {
// 16 B HFA — both fields zero.
p := #objc_call(NSPoint)(null, "pointValue");
print("point = ({}, {})\n", p.x, p.y);
// 16 B integer — both fields zero.
r := #objc_call(NSRange)(null, "rangeValue");
print("range = ({}, {})\n", r.location, r.length);
// 32 B HFA — all four fields zero.
rect := #objc_call(NSRect)(null, "rectValue");
print("rect = ({}, {}, {}, {})\n", rect.x, rect.y, rect.width, rect.height);
// >16 B non-HFA struct returns (sret path) land in Phase 1.8.
}
inline if OS != .macos {
print("skipped (not macos)\n");
}
0;
}