cstage+selfhost+test: fold N_UN over signed int literal in let DATA emit (#19)
emit_lets / emitletdataw's scalar-8B and array arms only matched bare N_INTLIT / N_RUNELIT / N_TRUE / N_FALSE / N_NIL on the let rhs. `let x: i8 = -1i8;` arrives as N_UN(TK_MINUS, N_INTLIT(1)) — none of those — so cstage's scalar arm hit `else continue;` and dropped the DATAW row entirely; the array arm bailed at the first non-foldable element and the skip-array-with-non-NIL-rhs fall-through dropped the whole row. Wwstage's mirror arms silently emitted zero bytes for negative literals in both shapes. Severity split — cstage symptom is no DATA emit, the linker fails loudly at build time. Wwstage symptom is silent-zero element substitution for negative array values: compiles, runs, returns wrong answers. Corpus-coverage-blind on the wwstage side, only surfaces when a consumer reads the wrong value. Single N_UN-fold helper application retires both symptoms across both stages. Fourth corpus-coverage-blind unmask this session (catalog: i64 div/mod CQO #16, IDENT-local /= no-op, #21 call-arg DX drop, now #19 wwstage silent-zero). Route all four sites through fold_int_literal / foldintliteral, the same helper #24 used on the def-emit side (which already covered N_UN over the leaf set). The wwstage array arm also picks up an N_CAST peel and drops a dead non-`...` N_FIELD branch (the parser never emits non-`...` N_FIELD inside an N_ARRLIT — only as the `...` repeat marker). Same-path sibling cleanup; rule-11 justified. Tests: - 719_signed_data_emit asserts DATAW <sym>(SB),"<bytes>" lines are present in both stages' .s for the {i8, i16, i32, i64} × {scalar, 1D array} matrix, plus cmp -s byte-id between stages per row. Corpus-coverage-blind sentinel per rob's STATUS-3 note. - 923_signed_data_emit_run runtime-pins the same matrix plus a TK_TILDE row through cstage and wwstage drivers. 995_self_rebuild stays green (ww2==ww3==ww4 byte-id).
This commit is contained in:
@@ -1108,14 +1108,12 @@ fn emitletdataw(c: *cgen, file: *node) void = {
|
||||
if (r.kind != nkind.N_CAST) { break; };
|
||||
r = r.lhs;
|
||||
};
|
||||
ok = false;
|
||||
if (r != nil) {
|
||||
if (r.kind == nkind.N_INTLIT) { v = r.uval; ok = true; };
|
||||
if (r.kind == nkind.N_RUNELIT) { v = r.uval; ok = true; };
|
||||
if (r.kind == nkind.N_TRUE) { v = 1u64; ok = true; };
|
||||
if (r.kind == nkind.N_FALSE) { v = 0u64; ok = true; };
|
||||
if (r.kind == nkind.N_NIL) { v = 0u64; ok = true; };
|
||||
};
|
||||
// Same helper as emitdefconstants (#24)
|
||||
// — widens the gate so N_UN over an
|
||||
// int leaf folds. `let x: i8 = -1i8;`
|
||||
// arrives as N_UN(TK_MINUS, N_INTLIT)
|
||||
// after the typed-AST cast peel.
|
||||
ok = foldintliteral(r, &v);
|
||||
};
|
||||
if (ok) {
|
||||
emitline("DATAW ");
|
||||
@@ -1245,11 +1243,14 @@ fn emitletdataw(c: *cgen, file: *node) void = {
|
||||
// Top-level `[N]T = [a, b, ...]` array global.
|
||||
// Emits N*esz bytes with each element's bytes
|
||||
// little-endian for the declared primitive width.
|
||||
// Without this, `let arr: [N]T = ...` references
|
||||
// from function bodies link-fail with `undefined
|
||||
// reference to arr`, and bare-name addressing
|
||||
// (LEAQ arr(SB)) inside cgindex / cgassign has no
|
||||
// symbol to bind to.
|
||||
// Element fold goes through foldintliteral (same
|
||||
// helper as emitdefconstants / scalar arm above)
|
||||
// so `-1i8` and friends emit their two's-complement
|
||||
// bytes after the leading N_CAST peel — pre-#19
|
||||
// this arm only matched bare N_INTLIT/N_RUNELIT and
|
||||
// silently emitted zero for unfoldable elements.
|
||||
// `...` (N_FIELD with str="...") repeats the last
|
||||
// folded value across the remaining slots.
|
||||
if (d.lhs != nil) {
|
||||
if (d.lhs.kind == nkind.N_TARRAY) {
|
||||
let elemn: *node = d.lhs.lhs;
|
||||
@@ -1273,27 +1274,25 @@ fn emitletdataw(c: *cgen, file: *node) void = {
|
||||
emitline("(SB),\"");
|
||||
let i: i32 = 0;
|
||||
let e: *node = elems;
|
||||
let fillv: u64 = 0u64;
|
||||
let last: u64 = 0u64;
|
||||
let inrepeat: bool = false;
|
||||
for (i < alen) {
|
||||
let v: u64 = fillv;
|
||||
let v: u64 = last;
|
||||
if (!inrepeat && e != nil) {
|
||||
if (e.kind == nkind.N_FIELD) {
|
||||
if (streq(e.str, "...")) {
|
||||
// `..., ...` repeat marker: prior v stays.
|
||||
inrepeat = true;
|
||||
} else {
|
||||
if (e.lhs != nil) {
|
||||
if (e.lhs.kind == nkind.N_INTLIT) { v = e.lhs.uval; };
|
||||
if (e.lhs.kind == nkind.N_RUNELIT) { v = e.lhs.uval; };
|
||||
};
|
||||
fillv = v;
|
||||
e = e.next;
|
||||
};
|
||||
} else {
|
||||
if (e.kind == nkind.N_INTLIT) { v = e.uval; };
|
||||
if (e.kind == nkind.N_RUNELIT) { v = e.uval; };
|
||||
fillv = v;
|
||||
let ev: *node = e;
|
||||
for (ev != nil) {
|
||||
if (ev.kind != nkind.N_CAST) { break; };
|
||||
ev = ev.lhs;
|
||||
};
|
||||
if (!foldintliteral(ev, &v)) { v = 0u64; };
|
||||
last = v;
|
||||
e = e.next;
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user