Files
ww/test/lang/deref_narrow_test.ww
Hojun-Cho 83f5956df2 test: banner purge + WHY-only comment sweep (rule 8)
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.
2026-08-08 21:40:23 +09:00

97 lines
3.2 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.
// An integer pointer deref (`*p`) must read its pointee's
// ACTUAL width, not a fixed 8B MOVQ, migrated from test/wcc/947_deref_narrow_run.c
// (#116). Before #116 the TK_STAR integer arm emitted a raw `MOVQ (AX),AX`
// regardless of pointee size, so `*p` over a packed `*i32`/`*u32`/`*iN` slot
// pulled the next 47 bytes into the high half of RAX. Truncating sinks (an i32
// store) dropped the garbage; WIDTH-PRESERVING sinks (a `==` compare that
// widens the literal to 8B → CMPQ) saw it. The fix routes the load through
// localloadop(n->type), the MOVSXD/MOVSWQ/MOVSBQ + MOVL/MOVZWQ/MOVZBQ dispatch
// already shared by IDENT/DOT/index loads. The .s is byte-identical cs==ww, so
// these behavioral @tests are the runtime net the byte-id gate can't be.
//
// Each @test deliberately uses a `==` (CMPQ-width) sink so a stale high half
// would make the assert FAIL; the narrow-signed rows route through an `: i32`
// cast whose compare against a 64B-widened literal forces the sign-extension
// onto the load. alias/enum rows exercise the TY_NAMED/TBANG/TY_ENUM peel in
// localloadop's tinfo lookup; the struct-field base on the i16/u16/alias/enum
// rows dodges the sibling [N]alias array-init store-width concern (out of #116
// scope). i64_ctrl is the regression guard that a width-correct case keeps MOVQ.
package deref_narrow_test;
type err = !i32;
type abox = struct { v: err };
type ibox = struct { v: i16, m: u16 };
type ubox = struct { v: u16, m: u16 };
type flag = enum i8 { A = -2i8, B = 1i8 };
type fbox = struct { v: flag, m: u8 };
@test fn i32_cmpq() void = {
let buf: [4]i32 = [10, 20, 30, 40];
let p: *i32 = &buf[1];
assert(*p == 20);
};
@test fn u32_zeroext() void = {
let buf: [3]u32 = [10u32, 20u32, 0xFFFFFFFFu32];
let p: *u32 = &buf[2];
assert(*p == 0xFFFFFFFFu32);
};
@test fn u8_zeroext() void = {
let buf: [3]u8 = [10u8, 20u8, 0xFFu8];
let p: *u8 = &buf[2];
assert(*p == 0xFFu8);
};
@test fn i8_signext() void = {
let buf: [3]i8 = [-1i8, -2i8, -3i8];
let p: *i8 = &buf[1];
let v: i32 = (*p): i32;
assert(v == -2i32);
};
@test fn alias_signext() void = {
// `type err = !i32; *err` — the TY_NAMED/TBANG peel must reach the
// underlying i32 width for MOVSXD to fire.
let b: abox = abox { v = -7i32: err };
let p: *err = &b.v;
let r: i32 = (*p): i32;
assert(r == -7i32);
};
@test fn bool_ctrl() void = {
let buf: [3]bool = [true, false, true];
let p: *bool = &buf[1];
assert(*p == false);
};
@test fn i16_signext() void = {
let b: ibox = ibox { v = -200i16, m = 0xABCDu16 };
let p: *i16 = &b.v;
let r: i32 = (*p): i32;
assert(r == -200i32);
};
@test fn u16_zeroext() void = {
let b: ubox = ubox { v = 0xFFFFu16, m = 0xABCDu16 };
let p: *u16 = &b.v;
assert(*p == 0xFFFFu16);
};
@test fn enum_signext() void = {
// `type flag = enum i8 { ... }; *flag` — TY_NAMED/TY_ENUM peel in
// typeissigned + tinfo.size on the NAMED wrapper must land on MOVSBQ.
let b: fbox = fbox { v = flag.A, m = 0xABu8 };
let p: *flag = &b.v;
let r: i32 = ((*p): i8): i32;
assert(r == -2i32);
};
@test fn i64_ctrl() void = {
// width-correct case — MUST still emit MOVQ; regression guard.
let buf: [3]i64 = [100i64, 200i64, 300i64];
let p: *i64 = &buf[1];
assert(*p == 200i64);
};