toolchain: banner purge + WHY-only comment sweep (rule 8)

selfhost/, cmd/, internal/ join the tree-wide sweep: every section
banner dies (91 selfhost + the cmd C-style dividers -> 0); narration
and stale contracts deleted (pre-#22 bundler notes, retired
single-PT_LOAD and no-archive claims, superseded ABI tables); every
ref/harec/qbe cite, task cite, encoding/ELF contract, and rule-10
twin pointer kept; lost lifetime/rationale lines restored where the
sweep over-cut (elf_globals ownership, kwtab linear-scan). Comment-
only proven: all five wwstage tool binaries byte-identical across
the sweep; test-commit, test-byteid (161+1399, 0 pinned-divergent),
and test-bootstrap (fixed point + 991-995 byte-id) all exit 0.
The read-through banked 66 latent-bug leads (checkpoint).
This commit is contained in:
2026-08-08 23:14:03 +09:00
parent 83f5956df2
commit 62b9d20383
60 changed files with 232 additions and 1045 deletions

View File

@@ -1,4 +1,4 @@
// selfhost/cmd/w6a/parse.ww — port of cmd/w6a/parse.c.
// Port of cmd/w6a/parse.c.
//
// Line-oriented parser for the asm subset emitted by w6c.
// Grammar:
@@ -28,8 +28,7 @@ fn streqlit(p: *u8, n: u64, lit: str) bool = {
return true;
};
// opcodelookup — name (length-bounded *u8) → A_*. Returns 0 (A_NOP)
// if not found.
// Returns 0 (A_NOP) if not found.
fn opcodelookup(p: *u8, n: u64) i32 = {
if (streqlit(p, n, "MOVQ")) { return A_MOVQ; };
if (streqlit(p, n, "MOVL")) { return A_MOVL; };
@@ -100,7 +99,7 @@ fn opcodelookup(p: *u8, n: u64) i32 = {
return A_NOP;
};
// reglookup — name → D_*. Returns D_NONE if not found.
// Returns D_NONE if not found.
fn reglookup(p: *u8, n: u64) i32 = {
if (streqlit(p, n, "AX")) { return D_AX; };
if (streqlit(p, n, "BX")) { return D_BX; };
@@ -180,7 +179,6 @@ fn perr(a: *asm_, msg: str) void = {
a.errs += 1;
};
// dupstr — copy n bytes from p into a fresh heap str.
fn dupstr(p: *u8, n: u64) str = {
let view: str;
view.ptr = p;
@@ -188,8 +186,6 @@ fn dupstr(p: *u8, n: u64) str = {
return strings.dup(view);
};
// ---- line iteration & whitespace --------------------------------------
// Read next line into a fresh heap buffer; returns (ptr, len) or (nil,0)
// at EOF. Advances a.pos past the newline.
fn nextline(a: *asm_) (*u8, u64) = {
@@ -204,7 +200,7 @@ fn nextline(a: *asm_) (*u8, u64) = {
let i: u64 = 0u64;
for (i < n) { buf[i] = a.src[start + i]; i += 1u64; };
buf[n] = 0u8;
a.pos += 1u64; // skip newline
a.pos += 1u64;
return buf.ptr, n;
};
// EOF without trailing newline
@@ -226,7 +222,6 @@ fn skipws(p: *u8, off: u64, n: u64) u64 = {
return i;
};
// parseoperand — parse one operand from p[off..n), populate out.
// Returns new offset (clamped to n on error).
fn parseoperand(a: *asm_, p: *u8, offin: u64, n: u64, out: *aoperand) u64 = {
let off: u64 = skipws(p, offin, n);
@@ -239,7 +234,6 @@ fn parseoperand(a: *asm_, p: *u8, offin: u64, n: u64, out: *aoperand) u64 = {
if (off >= n) { return off; };
let c0: u8 = p[off];
// $NUM
if (c0 == '$') {
off += 1u64;
let v: i64;
@@ -250,7 +244,6 @@ fn parseoperand(a: *asm_, p: *u8, offin: u64, n: u64, out: *aoperand) u64 = {
return off + used;
};
// (REG)
if (c0 == '(') {
off += 1u64;
let rstart: u64 = off;
@@ -377,7 +370,6 @@ fn parseoperand(a: *asm_, p: *u8, offin: u64, n: u64, out: *aoperand) u64 = {
return n;
};
// Append a fresh aprog to the list with given opcode and label.
fn addprog(a: *asm_, opc: i32, lbl: str) *aprog = {
let pr: *aprog = alloc(aprog { as_ = opc, line = a.line, label = lbl })!;
pr.from = alloc(aoperand { })!;
@@ -398,9 +390,7 @@ export fn parse(a: *asm_) i32 = {
line, n = nextline(a);
if (line == nil) { return a.errs; };
// skip leading ws
let i: u64 = skipws(line, 0u64, n);
// blank or //-comment
if (i >= n) { a.line += 1; continue; };
if (i + 1u64 < n) {
if (line[i] == '/') { if (line[i + 1u64] == '/') {
@@ -435,7 +425,6 @@ export fn parse(a: *asm_) i32 = {
};
};
// MNEMONIC at the start of the rest. Scan to first ws/EOL.
let mstart: u64 = i;
let m: u64 = mstart;
let scan: bool = true;
@@ -458,11 +447,9 @@ export fn parse(a: *asm_) i32 = {
let pr: *aprog = addprog(a, opc, pending);
pending.ptr = nil; pending.len = 0;
// Skip ws after mnemonic
let r0: u64 = skipws(line, m, n);
if (opc == A_TEXT) {
// TEXT name,$framesize — find first ',' as the end of name.
let q: u64 = r0;
let commapos: u64 = n;
let scant: bool = true;
@@ -502,7 +489,6 @@ export fn parse(a: *asm_) i32 = {
let toop: *aoperand = pr.to;
toop.atype = D_EXTERN;
toop.asym = dupstr(line + r0, lparen - r0);
// Skip past `(SB)` to land just after ')'.
let p2: u64 = lparen;
let scand2: bool = true;
for (scand2) {
@@ -510,7 +496,6 @@ export fn parse(a: *asm_) i32 = {
else { if (line[p2] == ')') { p2 += 1u64; scand2 = false; }
else { p2 += 1u64; }; };
};
// Skip ws / ',' / tab between `)` and the `"`.
let scand3: bool = true;
for (scand3) {
if (p2 >= n) { scand3 = false; }
@@ -521,8 +506,7 @@ export fn parse(a: *asm_) i32 = {
};
if (p2 >= n) { perr(a, "DATA missing payload"); a.line += 1; continue; };
if (line[p2] != '"') { perr(a, "DATA expects \"...\""); a.line += 1; continue; };
p2 += 1u64; // past opening "
// Parse escape sequence into a fresh growable buffer.
p2 += 1u64;
let cap: u64 = 32u64;
let blen: u64 = 0u64;
let dbuf: []u8 = alloc([], cap)!;
@@ -575,8 +559,6 @@ export fn parse(a: *asm_) i32 = {
a.line += 1; continue;
};
// Generic instruction: 0/1/2 operands separated by ','.
// Find top-level comma.
let comma: i64 = -1i64;
let q: u64 = r0;
for (q < n) {