test: migrate Fam4 static-init/DATA-emit value tests to @test (#30)

Continues the test-arch tower past Fam8-13. 11 module-level static-init
/ DATA-emit value drivers move from test/wcc/*_run.c into @test row-
tables under test/lang/; every classification empirically re-probed at
HEAD (refuting two stale worklist tags).

- value rows -> test/lang/*_test.ww (11 files)
- reject rows -> runww //ww:error carriers (3, dual-stage non-vacuous;
  947 const-divzero confirmed a both-stage compile-reject, not run-exit)
- 840_zeroinit, 944_array_zeroinit, 989_arrlit_tail_zero kept as byte-id
  .c pins (zero-over-dirtied-frame / DATAW-length is byte-id-blind to a
  runtime @test; #263), mutation-gated
- repoint two stale comment refs to deleted test names (719,
  989_structlocal_frame)

Migrated static-init @test ride the cs==ww T2 byte-id gate, preserving
DATA-emit byte-id. 2D global-struct array-field read (#137/#150)
confirmed cs==ww + correct at HEAD. Coverage parity verified row-by-row;
two-round reviewed. Floor ratchet follows.
This commit is contained in:
2026-06-25 01:32:32 +09:00
parent 4cb697af87
commit 74cc35d488
28 changed files with 647 additions and 2790 deletions

View File

@@ -0,0 +1,41 @@
// arr_u16_store_test — [N]u16/[N]i16 array-literal init stores MOVW per slot.
// Migrated from test/wcc/914_arr_u16_store_run.c. Pre-fix a [4]u16 init emitted
// overlapping MOVQ stores (accident-corrected for some values); the fix dispatches
// a proper MOVW per 2-byte slot (op chosen by esz, not signedness). cstage
// build+run was T1; cs==ww .s byte-id rides T2 (test-lang-byteid). The full_init
// row asserts each element to catch any value drift; the [4]u8 control pins the
// MOVB path is unchanged; i16_signed pins the dispatch is not signedness-gated.
package arr_u16_store_test;
@test fn u16_full_init() void = {
let a: [4]u16 = [0xABCDu16, 0xBEEFu16, 0xC0DEu16, 0xDEADu16];
assert(a[0] == 0xABCDu16);
assert(a[1] == 0xBEEFu16);
assert(a[2] == 0xC0DEu16);
assert(a[3] == 0xDEADu16);
};
@test fn u16_small_values() void = {
let a: [4]u16 = [10u16, 20u16, 30u16, 40u16];
let s: i32 = 0;
s += a[0]: i32; s += a[1]: i32;
s += a[2]: i32; s += a[3]: i32;
assert(s == 100);
};
@test fn u8_control() void = {
let a: [4]u8 = [10u8, 20u8, 30u8, 40u8];
let s: i32 = 0;
s += a[0]: i32; s += a[1]: i32;
s += a[2]: i32; s += a[3]: i32;
assert(s == 100);
};
@test fn i16_signed() void = {
let a: [4]i16 = [10i16, 20i16, 30i16, -5i16];
let s: i32 = 0;
s += a[0]: i32; s += a[1]: i32;
s += a[2]: i32; s += a[3]: i32;
assert(s == 55);
};

View File

@@ -0,0 +1,99 @@
// array_static_init_test — module-level 1D/2D/3D array static-init, element
// read. Migrated from test/wcc/919_array_static_init_run.c (#129 Phase A.3,
// #156). emit_array_lit_bytes recurses on a TY_ARRAY element (esz=etype->size,
// rule 13); cgindex leaves the sub-array ADDRESS for an array element so the
// outer index dereferences the right cell (#135 sister). cstage build+run was
// T1; cs==ww .s byte-id rides T2 (test-lang-byteid). The nested-array `...`
// repeat reject is the runww carrier test/wcc/data/arr_nested_ellipsis_reject.
//
// Float-element rows assert bit-exact incl negative elements (drew: exercise the
// sign-XOR byte-loop per element). The struct-with-array-field rows read the
// array-field elements directly (D1.buf[k], D2.m[i][j]): the old #137/#150 cs≠ww
// global-struct-field-base bug is CLOSED at HEAD, so the read is now cs==ww IDENT
// — the original deferred this to byte-id only because the bug was then open.
package array_static_init_test;
let A_U8: [4]u8 = [1u8, 2u8, 3u8, 4u8];
let A_U32: [4]u32 = [1u32, 2u32, 3u32, 4u32];
let A_U64: [2]u64 = [1u64, 2u64];
let A_INEG: [4]i32 = [-1, -2, -3, -4];
let A_F64: [4]f64 = [1.5, -2.5, 3.5, -4.5];
let A_F32: [4]f32 = [1.5f32, -2.5f32, 3.5f32, -4.5f32];
def DA_U32: [4]u32 = [11u32, 22u32, 33u32, 44u32];
def DA_F64: [4]f64 = [1.5, 2.5, 3.5, 4.5];
let A_UZ: [4]u8 = [0u8, 0u8, 0u8, 0u8];
let A_U1: [1]u8 = [7u8];
let A2D: [3][2]u64 = [[1u64,2u64],[3u64,4u64],[5u64,6u64]];
def DA2D: [3][2]u64 = [[1u64,2u64],[3u64,4u64],[5u64,6u64]];
let A2V: [3][2]u64 = [[10u64,11u64],[20u64,21u64],[30u64,31u64]];
let A28: [2][1]u32 = [[7u32],[9u32]];
let A2W: [2][2]u64 = [[1u64,2u64],[3u64,4u64]];
let A3D: [2][2][2]u8 = [[[1u8,2u8],[3u8,4u8]],[[5u8,6u8],[7u8,8u8]]];
type dt1 = struct { tag: i32, buf: [4]u8 };
let D1: dt1 = dt1{tag=42, buf=[1u8, 2u8, 3u8, 4u8]};
type dt2 = struct { tag: i32, m: [2][2]u64 };
let D2: dt2 = dt2{tag=42, m=[[1u64,2u64],[3u64,4u64]]};
fn bits64(v: f64) u64 = {
let x: f64 = v;
let p: *u64 = (&x): *u64;
return *p;
};
fn bits32(v: f32) u32 = {
let x: f32 = v;
let p: *u32 = (&x): *u32;
return *p;
};
fn at(i: i32, j: i32) u64 = { return A2V[i][j]; };
@test fn let_u8_arr() void = { assert(A_U8[0]: i32 == 1); };
@test fn let_u32_arr() void = { assert(A_U32[0]: i32 == 1); };
@test fn let_u64_arr() void = { assert(A_U64[0]: i32 == 1); };
@test fn let_i32_neg_arr() void = { assert(A_INEG[0] == -1); };
@test fn let_f64_arr() void = {
assert(bits64(A_F64[0]) == 0x3FF8000000000000u64);
assert(bits64(A_F64[1]) == 0xC004000000000000u64);
assert(bits64(A_F64[3]) == 0xC012000000000000u64);
};
@test fn let_f32_arr() void = {
assert(bits32(A_F32[0]) == 0x3FC00000u32);
assert(bits32(A_F32[1]) == 0xC0200000u32);
assert(bits32(A_F32[3]) == 0xC0900000u32);
};
@test fn def_u32_arr() void = { assert(DA_U32[0]: i32 == 11); };
@test fn def_f64_arr() void = {
assert(bits64(DA_F64[0]) == 0x3FF8000000000000u64);
assert(bits64(DA_F64[3]) == 0x4012000000000000u64);
};
@test fn let_struct_with_arr_field() void = {
assert(D1.tag == 42);
assert(D1.buf[0]: i32 == 1);
assert(D1.buf[3]: i32 == 4);
};
@test fn let_u8_zero_arr() void = { assert(A_UZ[0]: i32 == 0); };
@test fn let_u8_single() void = { assert(A_U1[0]: i32 == 7); };
@test fn let_2d_u64() void = { assert(A2D[1][0]: i32 == 3); };
@test fn def_2d_u64() void = { assert(DA2D[2][1]: i32 == 6); };
@test fn let_2d_varidx() void = { assert((at(1, 1) + at(2, 0)): i32 == 51); };
@test fn let_2d_u32_8byte() void = { assert(A28[1][0]: i32 == 9); };
@test fn let_2d_write() void = {
A2W[1][0] = 99u64;
assert((A2W[0][0] + A2W[0][1] + A2W[1][0] + A2W[1][1]): i32 == 106);
};
@test fn let_struct_2d_field() void = {
assert(D2.tag == 42);
assert(D2.m[1][0]: i32 == 3);
assert(D2.m[1][1]: i32 == 4);
};
@test fn let_3d_u8() void = { assert(A3D[1][1][0]: i32 == 7); };

View File

@@ -0,0 +1,62 @@
// const_slice_aggregate_test — module-level const slice of (str,*fn) tuple rows
// + scalar &fn globals, DATA emit with element relocations. Migrated from
// test/wcc/946_const_slice_aggregate_run.c (#117/#119). cstage build+run was T1;
// cs==ww .s byte-id rides T2 (test-lang-byteid). The loud non-tuple-aggregate
// reject is the runww carrier test/wcc/data/slice_of_str_reject.
//
// drew: CALL THROUGH the *fn reloc — a scalar-only / len-only assert is
// reloc-blind. Each row calls each distinct fn back so a wrong/swapped reloc is
// caught; the str-element relocs + per-row backing stride ride the T2 byte-id.
// Whole-element word0 is the only correctly-loaded backing word (#121 read
// constraint), so the fn-first / scalar-first orderings put the read target at
// word0.
package const_slice_aggregate_test;
fn fa(c: rune) bool = { return c == 'a'; };
fn fz(c: rune) bool = { return c == 'z'; };
const TBL_FN: [](*fn(c: rune) bool, str) = [(&fa, "aa"), (&fz, "zzz")];
const TBL_SF: [](str, *fn(c: rune) bool) = [("aa", &fa), ("zzz", &fz)];
const TBL_3: [](str, *fn(c: rune) bool) =
[("a", &fa), ("bb", &fa), ("ccc", &fa)];
const TSCAL: [](i64, str) = [(10i64, "a"), (20i64, "bb")];
let PF: *fn(c: rune) bool = &fa;
let PG: *fn(c: rune) bool = &fz;
@test fn fnfirst_reloc() void = {
let e0 = TBL_FN[0];
let e1 = TBL_FN[1];
let f0 = e0.0;
let f1 = e1.0;
assert((*f0)('a'));
assert(!(*f0)('z'));
assert((*f1)('z'));
assert(!(*f1)('a'));
assert(len(TBL_FN) == 2);
};
@test fn consumer_str_fn() void = {
assert(len(TBL_SF) == 2);
};
@test fn consumer_3row() void = {
assert(len(TBL_3) == 3);
};
@test fn scalar_tuple_slice() void = {
let e0 = TSCAL[0];
let e1 = TSCAL[1];
let v0 = e0.0;
let v1 = e1.0;
assert(v0 == 10);
assert(v1 == 20);
assert(len(TSCAL) == 2);
};
@test fn scalar_fnptr() void = {
assert((*PF)('a'));
assert(!(*PF)('z'));
assert((*PG)('z'));
assert(!(*PG)('a'));
};

View File

@@ -0,0 +1,62 @@
// def_float_lit_test — module-level `def`/`let` f64/f32 literal (incl negation)
// emits DATA, read back from a fn. Migrated from test/wcc/917_def_float_lit_run.c
// (#129 Phase A.1). Pre-fix `def K: f64 = lit;` fell through emit_defs's int-only
// fold gate so no DATAW landed (link: `undefined reference to main.K`); emit_lets's
// float arm never peeled N_UN(MINUS/PLUS, N_FLOATLIT) so `let g: f64 = -1.5;`
// silently zero-emitted. Fix = shared emit_floatlit_data helper (negation via
// IEEE-754 sign-bit XOR). cstage build+run was T1; cs==ww .s byte-id rides T2
// (test-lang-byteid).
//
// drew: assert BIT-EXACT incl sign — the bits()-reinterpret reads the full IEEE
// pattern, so a sign-bit or mantissa drift fails (a truncating `: i32` read would
// alias 1.5 and 1.9). The negative rows pin the sign-XOR byte path.
package def_float_lit_test;
def KDPOS: f64 = 1.5;
def KDNEG: f64 = -1.5;
def KFPOS: f32 = 1.5f32;
def KFNEG: f32 = -1.5f32;
let GDNEG: f64 = -1.5;
let GDPOS: f64 = 1.5;
let GFPOS: f32 = 1.5f32;
fn bits64(v: f64) u64 = {
let x: f64 = v;
let p: *u64 = (&x): *u64;
return *p;
};
fn bits32(v: f32) u32 = {
let x: f32 = v;
let p: *u32 = (&x): *u32;
return *p;
};
@test fn def_f64_pos() void = {
assert(bits64(KDPOS) == 0x3FF8000000000000u64);
};
@test fn def_f64_neg() void = {
assert(bits64(KDNEG) == 0xBFF8000000000000u64);
};
@test fn def_f32_pos() void = {
assert(bits32(KFPOS) == 0x3FC00000u32);
};
@test fn def_f32_neg() void = {
assert(bits32(KFNEG) == 0xBFC00000u32);
};
@test fn let_f64_neg() void = {
assert(bits64(GDNEG) == 0xBFF8000000000000u64);
};
@test fn let_f64_pos() void = {
assert(bits64(GDPOS) == 0x3FF8000000000000u64);
};
@test fn let_f32_pos() void = {
assert(bits32(GFPOS) == 0x3FC00000u32);
};

View File

@@ -0,0 +1,33 @@
// inferred_scalar_global_test — module-level inferred/const-expr scalar global
// emit + read. Migrated from test/wcc/947_inferred_scalar_global_run.c
// (#66 b-i, #134 neg, #133 const-expr). An inferred / unary / const-expr int
// global once emitted no DATAW on wwstage (MOVSXD on stale AX) and link-failed
// on cstage; the let pass-2 arm now const-folds the rhs and stamps an N_INTLIT
// so cgen's literal DATA emitter fires in BOTH stages. cstage build+run was T1;
// cs==ww .s byte-id rides T2 (test-lang-byteid). The div-by-zero const-expr
// reject is the runww carrier test/wcc/data/const_divzero_reject.
//
// The typed controls (typed_ctrl/neg_typed_ctrl/const_typed) lock the
// construction proof: the inferred decl's emitted .s equals the typed decl's
// after defaulting.
package inferred_scalar_global_test;
let SI = 42;
let STC: i64 = 42;
let SNI = -42;
let SNT: int = -42;
let SCI = 7 * 6;
let SCT: i64 = 7 * 6;
def KD: int = 6;
let SDR = KD * 7;
let SUB = -(2 * 3);
@test fn inferred() void = { assert(SI: i64 == 42); };
@test fn typed_ctrl() void = { assert(STC == 42); };
@test fn neg_inferred() void = { assert(SNI: i64 == -42); };
@test fn neg_typed_ctrl() void = { assert(SNT == -42); };
@test fn const_inferred() void = { assert(SCI: i64 == 42); };
@test fn const_typed() void = { assert(SCT == 42); };
@test fn const_defref() void = { assert(SDR: i64 == 42); };
@test fn const_unary_binop() void = { assert(SUB: i64 == -6); };

View File

@@ -0,0 +1,38 @@
// nestfield_test — nested sub-8 composite struct field at natural offsets.
// Migrated from test/wcc/989_nestfield_run.c (#44/#55). For outer{a:u8, p:inner}
// the natural offset of p is 1, but a pre-fix slot-padded layout put it at 8, so
// construction (write) and field-access (read) disagreed and o.p.x / o.p.y read
// wrong. cstage build+run was T1; the original cat-A invariant (cs==ww exit)
// now rides the stronger T2 .s byte-id (test-lang-byteid).
//
// nested3's z proves post-composite accumulation stays natural (z follows the
// 1-byte-padded inner, not the 8-byte-padded one). flat_ctl is the no-sub-8-field
// control where natural and slot-padded layouts coincide.
package nestfield_test;
type inr = struct { x: u8, y: u8 };
type ot2 = struct { a: u8, p: inr };
type ot3 = struct { a: u8, p: inr, z: i64 };
type flt = struct { a: u8, b: i64 };
@test fn nested2() void = {
let o: ot2 = ot2 { a = 5, p = inr { x = 6, y = 7 } };
assert(o.a: int == 5);
assert(o.p.x: int == 6);
assert(o.p.y: int == 7);
};
@test fn nested3() void = {
let o: ot3 = ot3 { a = 1, p = inr { x = 2, y = 3 }, z = 0x44444444i64 };
assert(o.a: int == 1);
assert(o.p.x: int == 2);
assert(o.p.y: int == 3);
assert(o.z == 0x44444444i64);
};
@test fn flat_ctl() void = {
let o: flt = flt { a = 9, b = 0x33333333i64 };
assert(o.a: int == 9);
assert(o.b == 0x33333333i64);
};

View File

@@ -0,0 +1,66 @@
// signed_data_emit_test — module-level signed i8..i64 scalar + 1D-array DATA
// emit, self-asserting the sign survives exactly. Migrated from
// test/wcc/923_signed_data_emit_run.c. Pre-fix wwstage silently zeroed negative
// array entries; cstage emitted nothing (link failed). cstage build+run was T1;
// cs==ww .s byte-id rides T2 (test-lang-byteid).
//
// drew: assert SIGN survives exactly — every row compares against the signed
// typed literal, so a sign-extension or zero-fill drift fails. i64_tilde pins
// the N_UN(TK_TILDE) fold (~0u64 == -1i64). The arrays mirror the utf8 DFA shape.
package signed_data_emit_test;
let X_I8N: i8 = -1i8;
let X_I8P: i8 = 42i8;
let X_I16N: i16 = -2i16;
let X_I16P: i16 = 1000i16;
let X_I32N: i32 = -100i32;
let X_I32P: i32 = 100000i32;
let X_I64N: i64 = -1000i64;
let X_I64P: i64 = 1000000i64;
let X_TILDE: i64 = (~0u64): i64;
let DFA: [8]i8 = [0i8, -1i8, 1i8, 2i8, 0i8, 0i8, -1i8, -1i8];
let A16: [4]i16 = [1i16, -2i16, 3i16, -4i16];
let A32: [4]i32 = [10i32, -20i32, 30i32, -40i32];
let A64: [4]i64 = [100i64, -200i64, 300i64, -400i64];
@test fn i8_neg_scalar() void = { assert(X_I8N == -1i8); };
@test fn i8_pos_scalar() void = { assert(X_I8P == 42i8); };
@test fn i16_neg_scalar() void = { assert(X_I16N == -2i16); };
@test fn i16_pos_scalar() void = { assert(X_I16P == 1000i16); };
@test fn i32_neg_scalar() void = { assert(X_I32N == -100i32); };
@test fn i32_pos_scalar() void = { assert(X_I32P == 100000i32); };
@test fn i64_neg_scalar() void = { assert(X_I64N == -1000i64); };
@test fn i64_pos_scalar() void = { assert(X_I64P == 1000000i64); };
@test fn i64_tilde_scalar() void = { assert(X_TILDE == -1i64); };
@test fn i8_arr_dfa() void = {
assert(DFA[0] == 0i8);
assert(DFA[1] == -1i8);
assert(DFA[2] == 1i8);
assert(DFA[3] == 2i8);
assert(DFA[6] == -1i8);
assert(DFA[7] == -1i8);
};
@test fn i16_arr_mixed() void = {
assert(A16[0] == 1i16);
assert(A16[1] == -2i16);
assert(A16[2] == 3i16);
assert(A16[3] == -4i16);
};
@test fn i32_arr_mixed() void = {
assert(A32[0] == 10i32);
assert(A32[1] == -20i32);
assert(A32[2] == 30i32);
assert(A32[3] == -40i32);
};
@test fn i64_arr_mixed() void = {
assert(A64[0] == 100i64);
assert(A64[1] == -200i64);
assert(A64[2] == 300i64);
assert(A64[3] == -400i64);
};

View File

@@ -0,0 +1,44 @@
// strarray_static_test — module-level [N]str static-init: per-element .len
// header sums + per-element .ptr RELOC dereferenced to chars. Migrated from
// test/wcc/919_strarray_static_run.c. cstage build+run was T1; cs==ww .s byte-id
// rides T2 (test-lang-byteid).
//
// drew: assert THROUGH the per-element .ptr deref (not just .len) — a reloc-blind
// .len-only check would miss a wrong/swapped element relocation. The empty-slot
// and `...` repeat-suffix rows pin that an empty element doesn't shift the
// following element's reloc and that the repeat-fill row's DATAR resolves to the
// last explicit element.
package strarray_static_test;
let TLEN: [3]str = ["ab", "cde", "f"];
let TPTR: [3]str = ["A", "B", "C"];
let TVAR: [3]str = ["xx", "yyy", "z"];
let TEMP: [2]str = ["", "Z"];
let TREP: [3]str = ["X", "Y"...];
@test fn strtab_len() void = {
assert((TLEN[0].len + TLEN[1].len + TLEN[2].len): i32 == 6);
};
@test fn strtab_ptr_elem2() void = {
let p: *u8 = TPTR[2].ptr;
assert((*p): i32 == 67);
};
@test fn strtab_ptr_varindex() void = {
let i: i32 = 1;
let p: *u8 = TVAR[i].ptr;
assert((*p): i32 == 121);
};
@test fn strtab_empty_then_ptr() void = {
assert(TEMP[0].len == 0);
let p: *u8 = TEMP[1].ptr;
assert((*p): i32 == 90);
};
@test fn strtab_repeat_suffix() void = {
let p: *u8 = TREP[2].ptr;
assert((*p): i32 == 89);
};

View File

@@ -0,0 +1,66 @@
// struct_composite_init_test — module-level `let`/`def` composite-struct
// static-init, field read. Migrated from test/wcc/918_struct_composite_init_run.c
// (#129 Phase A.2). Pre-fix emit_lets/emit_defs skipped struct-typed decls
// (link: `undefined reference to main.NAME`) and a struct def read MOVSXD'd
// stack byte 0. Fix = emit_struct_data/emit_struct_lit_bytes walking the field
// list with per-field-offset zero-fill (rule 13). cstage build+run was T1;
// cs==ww .s byte-id rides T2 (test-lang-byteid).
//
// The float-field rows assert bit-exact (drew) via bits64. let_empty/norhs read
// 0 from the statically zero-filled DATA (a global, not a dirtied stack — no
// benign-zero trap; an under-emit would shorten the symbol, not pad zero). The
// 8B-struct row pins the !is_struct gate over the sz==8 scalar short-circuit.
package struct_composite_init_test;
type cfg_t = struct { a: i32, b: u64 };
type ft = struct { a: f64, b: u32 };
type s8 = struct { a: i32, b: i32 };
let CFG_L: cfg_t = cfg_t{a=1, b=2u64};
def CFG_D: cfg_t = cfg_t{a=1, b=2u64};
let F_L: ft = ft{a=1.5, b=99u32};
def F_D: ft = ft{a=1.5, b=99u32};
let Z: cfg_t = cfg_t{};
let X8: s8 = s8{a=7, b=42};
let CFG_NR: cfg_t;
fn bits64(v: f64) u64 = {
let x: f64 = v;
let p: *u64 = (&x): *u64;
return *p;
};
@test fn let_int_struct() void = {
assert(CFG_L.a == 1);
assert(CFG_L.b == 2u64);
};
@test fn def_int_struct() void = {
assert(CFG_D.a == 1);
assert(CFG_D.b == 2u64);
};
@test fn let_float_field() void = {
assert(bits64(F_L.a) == 0x3FF8000000000000u64);
assert(F_L.b == 99u32);
};
@test fn def_float_field() void = {
assert(bits64(F_D.a) == 0x3FF8000000000000u64);
assert(F_D.b == 99u32);
};
@test fn let_empty_struct() void = {
assert(Z.a == 0);
assert(Z.b == 0u64);
};
@test fn let_int_struct_8b() void = {
assert(X8.a == 7);
assert(X8.b == 42);
};
@test fn let_norhs_struct() void = {
assert(CFG_NR.a == 0);
};

View File

@@ -0,0 +1,34 @@
// structlit_arrfield_test — struct array-field init + read (global let/def and
// local lit). Migrated from test/wcc/949_structlit_arrfield_run.c (#249). BUG B:
// reading a [4]u8 field of a module-global struct SEGFAULTed on wwstage; BUG A:
// a local struct-lit array field fell to the scalar tail and dropped every
// element but the first. Fix = cg_structlit_fill array arm + def_isstructdef
// LOAD widening (ADDQ $field_off). cstage build+run was T1; cs==ww .s byte-id
// rides T2 (test-lang-byteid). The def row has a [3]u8 pad ahead of encmap, so
// the read exercises a non-zero field offset (the base64 std_encoding shape).
package structlit_arrfield_test;
type e1 = struct { encmap: [4]u8 };
let GE: e1 = e1 { encmap = [65u8, 66u8, 67u8, 68u8] };
type e2 = struct { pad: [3]u8, encmap: [4]u8 };
def GD: e2 = e2 { pad = [9u8, 9u8, 9u8], encmap = [65u8, 66u8, 67u8, 68u8] };
@test fn global_let_read() void = {
assert(GE.encmap[0]: i32 == 65);
};
@test fn global_def_read_off() void = {
assert(GD.encmap[2]: i32 == 67);
};
@test fn local_lit_read0() void = {
let g: e1 = e1 { encmap = [65u8, 66u8, 67u8, 68u8] };
assert(g.encmap[0]: i32 == 65);
};
@test fn local_lit_read3() void = {
let g: e1 = e1 { encmap = [65u8, 66u8, 67u8, 68u8] };
assert(g.encmap[3]: i32 == 68);
};

View File

@@ -0,0 +1,70 @@
// valstruct_subsize_test — sub-8 nested value-struct zero-init extent, local +
// global, distinct byte asserts. Migrated from
// test/wcc/949_valstruct_subsize_run.c. A nested {[N]u8} value-struct of ABI
// size 1/2/4 once emitted a stray MOVQ $0 (local) / 8 zero DATA bytes (global)
// on wwstage that cstage didn't. cstage build+run was T1; cs==ww .s byte-id
// rides T2 (test-lang-byteid).
//
// The D1/D2 rows WRITE then READ a byte so the value is deterministic (the
// robust falsifiable dimension). The ctl_*_16 rows are the negative control: a
// >8 multi-word value-struct still zero-inits — a wrongly-suppressed >8 zero arm
// would read stack garbage (and diverge from the still-zeroing cstage on the T2
// byte-id, which is the real guarantee for the unwritten read).
package valstruct_subsize_test;
type in4 = struct { m: [4]u8 };
type ov4 = struct { i: in4 };
type in2 = struct { m: [2]u8 };
type ov2 = struct { i: in2 };
type in1 = struct { m: [1]u8 };
type ov1 = struct { i: in1 };
type in16 = struct { m: [16]u8 };
type ov16 = struct { i: in16 };
let G4: ov4;
let G2: ov2;
let G1: ov1;
let G16: ov16;
@test fn d1_local_4() void = {
let o: ov4;
o.i.m[0] = 66u8;
assert(o.i.m[0]: i32 == 66);
};
@test fn d1_local_2() void = {
let o: ov2;
o.i.m[1] = 55u8;
assert(o.i.m[1]: i32 == 55);
};
@test fn d1_local_1() void = {
let o: ov1;
o.i.m[0] = 44u8;
assert(o.i.m[0]: i32 == 44);
};
@test fn d2_global_4() void = {
G4.i.m[0] = 66u8;
assert(G4.i.m[0]: i32 == 66);
};
@test fn d2_global_2() void = {
G2.i.m[1] = 55u8;
assert(G2.i.m[1]: i32 == 55);
};
@test fn d2_global_1() void = {
G1.i.m[0] = 44u8;
assert(G1.i.m[0]: i32 == 44);
};
@test fn ctl_local_16() void = {
let o: ov16;
assert(o.i.m[7]: i32 == 0);
};
@test fn ctl_global_16() void = {
assert(G16.i.m[7]: i32 == 0);
};