feat(asm): Phase B.1 — operand-name validation (echo + duplicates)
Extends lowerAsmExpr with a pinnedRegister(constraint) helper and two §II.5
operand-naming checks, in the compile path before the codegen bail:
- reject the echo form `[eax] "={eax}"` — a label identical to the register its
own constraint pins is redundant (the operand is already auto-named after the
register); the useful form is a label that differs (`[quot] "={rax}"`);
- reject duplicate operand names (ambiguous %[name] / result field).
Locked with 1643-platform-asm-echo-name and 1644-platform-asm-duplicate-name.
zig build test green (652 corpus, 445 unit).
This commit is contained in:
@@ -6,7 +6,17 @@ commit, one step at a time per the cadence rule (no commit may both add a test
|
||||
and make it pass).
|
||||
|
||||
## Last completed step
|
||||
**B.0** — asm shape validation (compile-path diagnostics). Restructured the
|
||||
**B.1** — operand-name validation (design §II.5 auto-naming rule). Extended
|
||||
`lowerAsmExpr` with a `pinnedRegister(constraint)` helper (`"={eax}"`→`eax`,
|
||||
`"+{rax}"`→`rax`, `"=r"`→null) and two checks: (1) **reject the echo form**
|
||||
`[eax] "={eax}"` — a label identical to its own pinned register is redundant
|
||||
(the operand is already auto-named after the register); (2) **reject duplicate
|
||||
operand names** (ambiguous `%[name]` / result field). Locked with
|
||||
`examples/1643-platform-asm-echo-name.sx` + `1644-platform-asm-duplicate-name.sx`.
|
||||
`zig build test` green (652 corpus, 0 failed; 445 unit). Files:
|
||||
`src/ir/lower/expr.zig`.
|
||||
|
||||
Prior: **B.0** — asm shape validation (compile-path diagnostics). Restructured the
|
||||
`.asm_expr` lowering arm into `lowerAsmExpr` (`src/ir/lower/expr.zig`, mixed into
|
||||
`Lowering` in `src/ir/lower.zig`): it validates BEFORE the not-yet-implemented
|
||||
codegen bail, so the user sees the real problem first. Two checklist items now
|
||||
@@ -83,20 +93,19 @@ Phase B–E feasibility already confirmed against the live tree
|
||||
`extern`, 60 sites; `--target` a global CLI flag).
|
||||
|
||||
## Next step
|
||||
**B.1 / C.0** — two viable directions:
|
||||
- **B.1 (more validation, testable now):** remaining checklist items that fire
|
||||
pre-codegen — echo-name rejection (`[eax] "={eax}"`, §II.5 auto-naming),
|
||||
duplicate operand names, `%[name]` references that name no operand. Add to
|
||||
`lowerAsmExpr` (same compile-path pattern). Each is a pinnable error example.
|
||||
- **C.0 (IR op, unlocks the rest):** add `inline_asm: InlineAsm` to `Op`
|
||||
(`src/ir/inst.zig`) + interp `bailDetail`; then `lowerAsmExpr` stops bailing
|
||||
and builds the op, at which point **result-type derivation becomes observable**
|
||||
(so the auto-naming rule + tuple result typing in `expr_typer.zig` can be
|
||||
tested end-to-end). See `PLAN-ASM.md` Phase C + design §II.6.
|
||||
**C.0** (Phase C — IR op) — add `inline_asm: InlineAsm` to `Op` (`src/ir/inst.zig`,
|
||||
next to `objc_msg_send`) + the `AsmOperand` IR struct (role/name/constraint/operand
|
||||
as `StringId`/`Ref`), and an interp `bailDetail` arm (`src/ir/interp.zig`) — inline
|
||||
asm can never be comptime-evaluated. Unit-test the IR shape. This is a `lock`
|
||||
commit (no behavior change yet — `lowerAsmExpr` keeps bailing). Then C.1 wires
|
||||
`lowerAsmExpr` to actually intern strings + lower input `Ref`s + build the op and
|
||||
compute the result `TypeId`, at which point **result-type derivation becomes
|
||||
observable** and the auto-naming/tuple typing (`expr_typer.zig`, deferred from B)
|
||||
can be tested end-to-end. See `PLAN-ASM.md` Phase C + design §II.6.
|
||||
|
||||
Recommended: finish the cheap B.1 validation diagnostics, then move to C.0.
|
||||
(Result-type derivation in `expr_typer.zig` is intentionally deferred until C
|
||||
makes it observable — see Current state.)
|
||||
Remaining deferred validation (do alongside C, once template scanning is worth
|
||||
it): `%[name]` references in the template that name no operand. Needs effective-
|
||||
name resolution (explicit `[name]` ∪ auto-derived register names).
|
||||
|
||||
## Log
|
||||
- (init) Plan + design doc written; ASM stream opened.
|
||||
@@ -120,6 +129,9 @@ makes it observable — see Current state.)
|
||||
no-output⇒volatile, with named diagnostics before the codegen bail. Locked with
|
||||
1641 (volatile error) + 1642 (volatile accepted). `zig build test` green (650
|
||||
corpus, 445 unit).
|
||||
- (B.1) operand-name validation: `pinnedRegister` helper + reject echo form
|
||||
(`[eax] "={eax}"`) and duplicate names. Locked with 1643 + 1644. `zig build
|
||||
test` green (652 corpus, 445 unit).
|
||||
|
||||
## Known issues
|
||||
- **0137** — `sx run` on a program with no `main` segfaults (unguarded JIT entry
|
||||
|
||||
Reference in New Issue
Block a user