// A 3-reg composite (`[]u8` slice) CALL result passed // inline as a composite arg to another call, migrated from // test/wcc/927_composite_call_arg_run.c (#24, Class A wwstage cgen miscompile). // Pre-fix wwstage emitted a single `PUSHQ AX` for a slice-returning CALL arg // (losing .len/.cap) and under-popped the receiver's arg-regs by two words: the // arg-shift collision corrupts every subsequent arg (the receiver reads the // caller's spilled p.ptr as its own s.len). The fix gave `nodeisslice` an N_CALL // arm (mirroring nodeisstr): both the push side (3-PUSH CX,BX,AX) and the pop // side (extra=2) fire for slice-returning CALLs as args. Each @test KEEPS the // `check(view(s))` call-arg-composite shape under test and asserts the receiver // saw the right .len (a check fn returns 0 only when its internal .len checks // pass, so the asserted 0 IS the value contract). package composite_call_arg_test; fn view(s: str) []u8 = { let r: []u8; r.ptr = s.ptr; r.len = s.len; r.cap = s.len; return r; }; fn passthrough(a: []u8) []u8 = { return a; }; fn check_a(a: []u8) i32 = { if (a.len == 13) { return 0; }; return 11; }; fn check2_b(a: []u8, b: []u8) i32 = { if (a.len != 13) { return 11; }; if (b.len != 5) { return 12; }; return 0; }; fn check2_c(a: []u8, b: []u8) i32 = { if (a.len != 3) { return 11; }; if (b.len != 5) { return 12; }; return 0; }; fn check3_d(k0: i32, a: []u8, k1: i32) i32 = { if (k0 != 7) { return 11; }; if (a.len != 4) { return 12; }; if (k1 != 9) { return 13; }; return 0; }; fn check_e(a: []u8) i32 = { if (a.len == 6) { return 0; }; return 11; }; fn use2_f(a: []u8, k: i32) i32 = { if (a.len != 13) { return 11; }; if (k != 99) { return 12; }; return 0; }; type oserror = !i32; fn yield_ptr() (*u8 | oserror) = { let p: *u8 = nil; return p; }; fn dispatch(v: (*u8 | oserror)) i32 = { match (v) { case let p: *u8 => return 7; case let e: oserror => return e: i32; }; return -99; }; @test fn canonical_slice_call() void = { // (a) canonical f(g()) with g returning []u8. let s: str = "hello, world!"; assert(check_a(view(s)) == 0); }; @test fn slice_call_then_letslice() void = { // (b) f(g(), p) — strings.hasprefix shape: slice-CALL then a let-slice. let s: str = "hello, world!"; let p: []u8; p.ptr = s.ptr; p.len = 5; p.cap = 5; assert(check2_b(view(s), p) == 0); }; @test fn two_composite_calls_args() void = { // (c) f(g(in1), g(in2)) — two composite CALLs; the stack must hold both // 3-word headers before the 6-POP drain. let s1: str = "foo"; let s2: str = "hello"; assert(check2_c(view(s1), view(s2)) == 0); }; @test fn slice_call_middle_arg() void = { // (d) f(k0, g(), k1) — slice-CALL in the middle of three args. let s: str = "abcd"; assert(check3_d(7, view(s), 9) == 0); }; @test fn nested_composite_calls() void = { // (e) f(g(h(s))) — composite-in-composite nesting. let s: str = "abcdef"; assert(check_e(passthrough(view(s))) == 0); }; @test fn slice_call_then_scalar() void = { // (f) f(g(), 99) — slice-CALL then a scalar (pop-count mix). let s: str = "hello, world!"; assert(use2_f(view(s), 99) == 0); }; @test fn tagged_call_regression() void = { // (g) tagged-CALL alongside the slice path — confirms #21's natural-push // arm composes with #24's. assert(dispatch(yield_ptr()) == 7); };