Continue fold-2: migrate the pointer-deref / narrow-load / pointer-array-stride family from bespoke build+run C twins to test/lang @test, retiring each twin in the same commit. Runtime coverage MOVES from $(TESTS) to test-lang (T1 runs + asserts via `ww test`) + test-lang-byteid (T2 keeps cs==ww .s byte-id); the $(TESTS) headline drops 5. Every assert is a primitive int/bool comparison with a width-preserving (`==`) sink so a stale high half or wrong stride FAILS; the narrow-signed rows route through an `: i32` cast against a 64B-widened literal to force sign-extension onto the load. Each .c row maps to one inline @test fn (50 cases total, strict superset of the C rows): 947_deref_narrow_run.c -> deref_narrow_test.ww (#116, 10 rows: *p reads pointee width not 8B MOVQ; i32/u32/u8/i8/i16/u16 + !i32-alias + enum-i8 + bool/i64 controls) 949_ptrarr_index_run.c -> ptrarr_index_test.ww (#61, 23 rows: p[i]/(&p[i])/(*p)[i] stride by size(T); {1,2,4,8}B, const+var idx, param/local/cast bases, neighbor guards, nested *[2][3], *[3]str header, siphash round()) 949_dotbase_arr_run.c -> dotbase_arr_test.ww (#135, 3 rows: (*struct).arrayfield[i] read/write/compound addresses the field) 944_def_amp_idx_run.c -> def_amp_idx_test.ww (#94, 6 rows: &D[i] over a def-array; +plain/read/2D controls) 944_alias_amp_idx_run.c -> alias_amp_idx_test.ww (#5, 8 rows: &a[i] over an alias-typed base classifies off the chased type; local/global, narrow, fwd-ref, plain+str controls) The two sibling .c (949_dotbase_addr_slice_run, 944_alias_def_addr_run) stay in $(TESTS): the first is run-only byteid=0 (#254 cs!=ww rows), the second carries a LOUD rule-7 reject row — both routed to fold-3 (task #7). Bump LANGBYTEID_EXPECTED_MIN 38->43.
47 lines
1.7 KiB
Plaintext
47 lines
1.7 KiB
Plaintext
// dotbase_arr_test — an N_INDEX with an N_DOT base on a `[N]T`-typed field
|
|
// (`(*struct).array_field[i]`) must compute the field's ADDRESS, not load its
|
|
// value, migrated from test/wcc/949_dotbase_arr_run.c (#135). Pre-#135 the
|
|
// N_INDEX read + plain-assign + compound fallbacks all invoked cgexpr on the
|
|
// N_DOT base, which auto-derefs and loads the field's first 8 bytes as if a
|
|
// pointer → every read/write/compound through a packed array field segfaulted,
|
|
// cs==ww BOTH stages broken identically (gate-blind). The fix
|
|
// (cg_dotbase_addr/dotbaseaddr) detects an N_DOT base whose FIELD is TY_ARRAY,
|
|
// walks to the inner ident, and emits address-of-field inline; the TY_ARRAY
|
|
// gate keeps it inert on pointer/slice/str fields. The .s is byte-identical, so
|
|
// these behavioral @tests are the runtime net.
|
|
//
|
|
// read_u8 / write_u8 / compound_u8 are the 3 fix shapes on a `*struct` base
|
|
// with an [8]u8 field (the strconv decimal.ha:178 compound shape, #133+#135
|
|
// prereqs). Wider element widths and the TY_ARRAY-gate no-over-fire control are
|
|
// left to the bootstrap byte-id corpus (994/995) per the C twin's note: the i32
|
|
// return ABI's MOVL-vs-MOVSXD is a pre-existing cs/ww divergence below the
|
|
// helper, unrelated to #135.
|
|
|
|
package dotbase_arr_test;
|
|
|
|
type t = struct { digits: [8]u8, nd: size };
|
|
|
|
fn rd(d: *t) i32 = { return d.digits[3]: i32; };
|
|
fn setit(d: *t) void = { d.digits[3] = 99u8; };
|
|
fn bump(d: *t) void = { d.digits[3] += 1u8; };
|
|
|
|
@test fn read_u8() void = {
|
|
let x: t;
|
|
x.digits[0] = 50u8;
|
|
x.digits[3] = 77u8;
|
|
assert(rd(&x) == 77i32);
|
|
};
|
|
|
|
@test fn write_u8() void = {
|
|
let x: t;
|
|
setit(&x);
|
|
assert(x.digits[3]: i32 == 99i32);
|
|
};
|
|
|
|
@test fn compound_u8() void = {
|
|
let x: t;
|
|
x.digits[3] = 10u8;
|
|
bump(&x);
|
|
assert(x.digits[3]: i32 == 11i32);
|
|
};
|