# Short-circuit AND/OR Tag `v3-short-circuit`. Main suite **111/111**. ## Why V3 evaluated both sides of `AND`/`OR`; gm2 (and the compiler's own sources) rely on short-circuit — e.g. `SymTab.Resolve`'s `… AND (tform[t] = FAlias)` dereferences `tform[-1]` when `t` is invalid. Roughly 25 such guard sites exist in the compiler sources, so matching gm2 is the right fix rather than rewriting them. ## How The RHS operand is already parsed (and its code emitted) by the time the binary-op action runs, so short-circuit needs **deferred code**: - `QbeGen.DelayBegin` redirects output into a small buffer; `DelayEnd` restores the previous sink; `DelayFlush` replays the buffer at the branch. `WEmit` routes to the delay buffer while active. - `SimExpr` (OR) and `Term` (AND) wrap the RHS `Term`/`Fact` in `DelayBegin`/`DelayEnd` and emit: - `OR`: `if a then r = 1 else { ; r = b }` - `AND`: `if a then { ; r = b } else r = 0` - The merge uses a **4-byte memory slot** (`Slot4`/`StoreW`/`LoadW`) rather than a QBE `phi`: a phi must name the right predecessor block, but the RHS can span several blocks (e.g. a set-membership trap check), which broke the phi's predecessor list. The slot is robust to any RHS shape. ## Result Suite 111/111 (the earlier WIP failed 14 tests: `DelayFlush` popped the wrong buffer index, then the `CopyOp`-only merge collapsed the two branches to one compile-time operand). ## Still open (task 2: full self-image) The self-compiled V3 compiles a single file to byte-identical `.ssa`, but the **whole compiler source set** still aborts, now in the scanner's `GetName` (`LexName ← GetIdent ← ProcTypeSection`) — a bounds trap; next to diagnose. ## Files `compiler/src/{M2.atg,QbeGen.def,QbeGen.mod,M2.lst}`.