Every section banner dies (103 -> 0) across test/lang, the observer suites, the C carriers, and the five comment-heavy corpus fixtures; banner provenance (#N cites, carrier numbers, repair-cluster labels) folded into headers or adjacent WHY comments. Narration deleted; row provenance, ref cites, divergence pins, and layout contracts kept (fwd-ref decl-order guards and bootstrap-gate corpus rationale restored where the sweep over-cut). Comment-only proven: all 3742 wwbuild workdir .s byte-identical before/after; test-commit and test-byteid (161 lang + 1399 data, 0 pinned-divergent) green.
85 lines
3.5 KiB
Plaintext
85 lines
3.5 KiB
Plaintext
// Runtime contract for #163, the tuple-PARAM ABI (the param
|
|
// twin of #164's tuple RETURN). Migrated from test/wcc/905_tupparam_run.c.
|
|
// A tuple passed AS AN ARGUMENT was unhandled in both stages: a tuple-typed
|
|
// call result left its elements in the return-ABI cursor and the SEND fell to
|
|
// the 1-GP-word else, so all but the first element was dropped. The fix
|
|
// restages the tuple into a frame slot by SysV class then pushes the slot
|
|
// words; both stages byte-identical (rule 10). GATE-BLIND TO BYTE-ID ALONE:
|
|
// pre-fix both stages were symmetric-WRONG, so cs==ww held — the rows diverge
|
|
// only at RUNTIME; these @test fns pin that runtime contract (T1), the byte-id
|
|
// gate (T2) keeps cs==ww. The loud-stop arg-reg-overflow row is a reject
|
|
// carrier (test/wcc/data/tupparam_gp_overflow_loudstop/).
|
|
|
|
package tupparam_test;
|
|
|
|
fn pair_f64f64_arg(a: f64, b: f64) (f64, f64) = { return (a, b); };
|
|
fn add_f64f64_arg(t: (f64, f64)) f64 = { return t.0 + t.1; };
|
|
|
|
fn pair_i64i64_arg(a: i64, b: i64) (i64, i64) = { return (a, b); };
|
|
fn add_i64i64_arg(t: (i64, i64)) i64 = { return t.0 + t.1; };
|
|
|
|
fn mk_f64i64_arg(a: f64, b: i64) (f64, i64) = { return (a, b); };
|
|
fn add_f64i64_arg(t: (f64, i64)) i64 = { return (t.0: i64) + t.1; };
|
|
|
|
fn mk_i64f64_arg(a: i64, b: f64) (i64, f64) = { return (a, b); };
|
|
fn add_i64f64_arg(t: (i64, f64)) i64 = { return t.0 + (t.1: i64); };
|
|
|
|
fn mk_f64str_arg(a: f64) (f64, str) = { return (a, "hello"); };
|
|
fn add_f64str_arg(t: (f64, str)) i64 = {
|
|
return (t.0: i64) + (t.1.len: i64);
|
|
};
|
|
|
|
fn pair_two_tuple_args(a: i64, b: i64) (i64, i64) = { return (a, b); };
|
|
fn add4_two_tuple_args(s: (i64, i64), t: (i64, i64)) i64 = {
|
|
return s.0 + s.1 + t.0 + t.1;
|
|
};
|
|
|
|
fn pair_f64f64_chain(a: f64, b: f64) (f64, f64) = { return (a, b); };
|
|
fn id_f64f64_chain(t: (f64, f64)) f64 = { return t.0 * 10.0 + t.1; };
|
|
|
|
// HEADLINE — (f64, f64) arg. Pre-fix the SEND pushes only AX (the two floats
|
|
// stay stranded in X0/X1) and the callee reads one GP word. Post-fix each
|
|
// float rides the SSE arg cursor (X0, X1).
|
|
@test fn f64f64_arg() void = {
|
|
assert(!(add_f64f64_arg(pair_f64f64_arg(3.0, 5.0)) != 8.0));
|
|
};
|
|
|
|
// (i64, i64) arg — proves the broader INTEGER-tuple-param drop is fixed
|
|
// (master dropped the second i64 too). e0->DI, e1->SI.
|
|
@test fn i64i64_arg() void = {
|
|
assert(!(add_i64i64_arg(pair_i64i64_arg(3, 5)) != 8));
|
|
};
|
|
|
|
// (f64, i64) — class independent of position: f64@X0 (SSE cursor), i64@DI
|
|
// (INTEGER cursor), independent counters.
|
|
@test fn f64i64_arg() void = {
|
|
assert(!(add_f64i64_arg(mk_f64i64_arg(3.0, 5)) != 8));
|
|
};
|
|
|
|
// (i64, f64) — order-swap: i64@DI, f64@X0. Confirms the float lands in the
|
|
// next XMM regardless of its positional slot.
|
|
@test fn i64f64_arg() void = {
|
|
assert(!(add_i64f64_arg(mk_i64f64_arg(3, 5.0)) != 8));
|
|
};
|
|
|
|
// (f64, str) — SSE + wide (24B {ptr,len,cap}) coexist. The f64 rides X0 (SSE,
|
|
// consuming no GP slot); the str rides DI/SI/DX (INTEGER cursor). f=4.0,
|
|
// s.len=5 -> 4+5 = 9.
|
|
@test fn f64str_arg() void = {
|
|
assert(!(add_f64str_arg(mk_f64str_arg(4.0)) != 9));
|
|
};
|
|
|
|
// MULTI-TUPLE-ARG, ONE CALL — f(g(), h()) where both args are tuple-producing
|
|
// calls. Proves @tupargscr (single-slot-per-fn) is REUSED per arg, not
|
|
// COLLIDED. 1+2+3+4 = 10.
|
|
@test fn two_tuple_args() void = {
|
|
assert(!(add4_two_tuple_args(pair_two_tuple_args(1, 2),
|
|
pair_two_tuple_args(3, 4)) != 10));
|
|
};
|
|
|
|
// CONTROL — a tuple arg threaded through a chain of two calls, proving the
|
|
// SEND/RECV round-trips through the slot intact.
|
|
@test fn f64f64_chain() void = {
|
|
assert(!(id_f64f64_chain(pair_f64f64_chain(3.0, 5.0)) != 35.0));
|
|
};
|