commit d08722348902363a034ec532e71f67b3151f6047
parent 790ab01a4a5ee273f357f12e3b872736371e3879
Author: Ryan Sepassi <rsepassi@gmail.com>
Date: Sun, 26 Apr 2026 23:46:25 -0700
docs: mark §F.1-4, §G.1-2, §J.1-3, §K.2-6 done in punchlist
All items completed with cg + parse fixtures and impl. §G.2 ships
with a documented limitation: only first 4 incoming args (named +
variadic) live in the saved-register area; >=4 needs LDARG path.
Diffstat:
| M | docs/CC-PUNCHLIST.md | | | 159 | ++++++++++++++++++++++++++++++++++++++++++------------------------------------- |
1 file changed, 85 insertions(+), 74 deletions(-)
diff --git a/docs/CC-PUNCHLIST.md b/docs/CC-PUNCHLIST.md
@@ -230,46 +230,55 @@ accepts an init bv but is never given one.
### F. Control flow extensions
-- [ ] **`do { } while (e);`**
- - cg: `cc-cg/NN-do-while.scm`
- - parse: `cc-parse/NN-do-while.c`
- - Needs: parser already wires `cg-loop` + `cg-if` + `cg-break`;
- this is largely a fixture exercise.
-
-- [ ] **`for (init; cond; step)` with declaration in `init`**
- - parse: `cc-parse/NN-for-decl.c`
- - Needs: existing `parse-for-stmt` exercised end-to-end.
-
-- [ ] **`switch / case / default` with fall-through**
- - cg: `cc-cg/NN-switch.scm` — three cases falling through to default.
- - parse: `cc-parse/NN-switch.c`
- - Needs: validates the existing `swctx` machinery in cg.
-
-- [ ] **`goto` / labelled statement (forward and backward)**
- - cg: `cc-cg/NN-goto.scm`
- - parse: `cc-parse/NN-goto.c`
- - Needs: replace the `cg-break` hack in `parse-goto-stmt`. Add
+- [x] **`do { } while (e);`**
+ - cg: `cc-cg/63-do-while.scm`
+ - parse: `cc-parse/63-do-while.c`
+ - Done: composes existing `cg-loop` + `cg-if` + `cg-break`;
+ fixture-only.
+
+- [x] **`for (init; cond; step)` with declaration in `init`**
+ - parse: `cc-parse/64-for-decl.c`
+ - Done: existing `parse-for-stmt` exercised end-to-end.
+
+- [x] **`switch / case / default` with fall-through**
+ - cg: `cc-cg/64-switch.scm` — three cases falling through to default.
+ - parse: `cc-parse/65-switch.c`
+ - Done: validated the existing `swctx` machinery in cg.
+
+- [x] **`goto` / labelled statement (forward and backward)**
+ - cg: `cc-cg/65-goto.scm`
+ - parse: `cc-parse/66-goto.c`
+ - Done: replaced the `cg-break` hack in `parse-goto-stmt`. Added
`cg-emit-label cg name-bv` (drops `::user_<name>`) and
`cg-goto cg name-bv` (emits `%b(&::user_<name>)`).
- `parse-labelled-stmt` calls `cg-emit-label` before the inner stmt.
+ `parse-labelled-stmt` now calls `cg-emit-label` before the inner stmt.
+ - Drive-by fix: `cg-binop` `'le`/`'ge` previously emitted `%xori`,
+ which is undefined in P1. Replaced with `%li(t1,1) %xor(t0,t0,t1)`.
### G. Variadics
-- [ ] **Variadic call: per-arg default-promote**
- - cg: `cc-cg/NN-vararg-call.scm`
- - parse: `cc-parse/NN-vararg-call.c`
- - Needs: parser inspects fn type at `parse-call-args`; for arg index
- ≥ named-arg count, emits `cg-promote` and `cg-cast` per CC.md
- §Implicit conversions.
-
-- [ ] **Variadic receive: `__builtin_va_start/arg/end`**
- - cg: `cc-cg/NN-vararg-recv.scm` — sums N int-typed variadic args.
- - parse: `cc-parse/NN-vararg-recv.c`
- - Needs: `cg-va-start cg ap-lval`, `cg-va-arg cg ap-lval ctype`,
- `cg-va-end cg ap-lval`. Layout: variadic args sit at a known
- offset relative to fixed-arg slots; cg already controls the frame.
- - Also needs: a bundled `stdarg.h` (CC.md §Standard library
- expectations — "supplied by us").
+- [x] **Variadic call: per-arg default-promote**
+ - cg: `cc-cg/66-vararg-call.scm`
+ - parse: `cc-parse/67-vararg-call.c`
+ - Done: parser inspects fn type at `parse-call-args`; for arg index
+ ≥ named-arg count, emits `cg-promote` per CC.md §Implicit
+ conversions. Fixed-arg index emits `cg-cast` to declared param
+ type (also covers §K.5).
+
+- [x] **Variadic receive: `__builtin_va_start/arg/end`**
+ - cg: `cc-cg/69-vararg-recv.scm` — sums N int-typed variadic args.
+ - parse: `cc-parse/76-vararg-recv.c`
+ - Done: added `cg-va-start cg`, `cg-va-arg cg ctype`,
+ `cg-va-end cg` (each pops ap-lval from vstack);
+ `cg-fn-begin/v` reserves a 4-slot saved-register area and saves
+ a0..a3 unconditionally so va_arg can read past the named-arg count.
+ Parser recognizes `__builtin_va_start/arg/end` at parse-primary;
+ `parse-fn-body` threads the fn ctype's variadic? flag.
+ - Bundled `cc/headers/stdarg.h` aliases `va_list`/`va_start`/
+ `va_arg`/`va_end` to the builtins.
+ - **Limitation**: only the first 4 incoming args (named + variadic)
+ live in the saved-register area. Variadic args at index >= 4 need
+ an `LDARG`-based path that is not yet implemented.
### H. Conditionals as values
@@ -306,20 +315,25 @@ both branches store into it, vstack ends with one frame opnd.
### J. Driver / envelope
-- [ ] **Entry stub forwards `argc` / `argv` to `main`**
- - e2e: gate is "cc-e2e/00-return-argc still green after stub change."
- - Needs: confirm against P1's program-entry contract whether `a0`/`a1`
- already hold argc/argv at `p1_main`. If yes, the current
- fall-through stub is correct and we just document it; if no,
- `cg-finish` reads them from P1's argv block.
-
-- [ ] **`int main()` falling off the end returns 0**
- - parse: `cc-parse/NN-main-noret.c` — `int main(){}` → exit 0.
- - Needs: ret-slot zero-init guarantee (verify it lands in the
- prologue, not just in the conceptual frame layout).
-
-- [ ] **Multi-function translation unit with forward references**
- - parse: `cc-parse/NN-multi-fn.c`
+- [x] **Entry stub forwards `argc` / `argv` to `main`**
+ - e2e: `cc-e2e/00-return-argc` (already green; locked in).
+ - Done: P1's program-entry contract delivers `a0=argc`, `a1=argv`
+ at `p1_main` (P1.md §Program Entry). `%call` doesn't clobber
+ a0/a1, so the existing fall-through stub `%fn(p1_main, 16,
+ { %call(&cc__main) })` correctly forwards them. Documented in
+ `cg-finish`.
+
+- [x] **`int main()` falling off the end returns 0**
+ - parse: `cc-parse/68-main-noret.c` — `int main(){}` → exit 0.
+ - Done: `cg-fn-begin` now zero-inits the ret slot in the prologue
+ when the return type isn't void, so falling through to `::ret`
+ reads back a defined 0 instead of relying on kernel zero-fill.
+
+- [x] **Multi-function translation unit with forward references**
+ - parse: `cc-parse/69-multi-fn.c`
+ - Done: forward declaration `int helper(int x);` binds an extern
+ fn sym up-front so `parse-primary` finds it before the
+ definition appears.
### K. Expressions and conversions
@@ -330,41 +344,38 @@ both branches store into it, vstack ends with one frame opnd.
Handler discards lhs (`cg-pop`) before evaluating rhs. tcc.c uses
this in `for` headers.
-- [ ] **Function-pointer call**
- - cg: `cc-cg/NN-fnptr-call.scm` — push a fn-typed sym, spill to a
+- [x] **Function-pointer call**
+ - cg: `cc-cg/67-fnptr-call.scm` — push a fn-typed sym, spill to a
frame slot, reload, call.
- - parse: `cc-parse/NN-fnptr-call.c` — `int (*fp)(int) = f; return fp(41);`
- → exit 42.
- - Needs: exercises `cg-call`'s `%callr(t0)` branch; verify
+ - parse: `cc-parse/71-fnptr-call.c` — `int (*fp)(int) = f; return fp(7);`
+ → exit 21.
+ - Done: exercises `cg-call`'s `%callr(t0)` branch; verified
return-type extraction walks `ptr → fn → ret` correctly.
-- [ ] **Enum constant in expressions**
- - parse: `cc-parse/NN-enum-const.c` — `enum E { A=1, B=10 }; return A+B;`
- → exit 11.
- - Needs: existing `cg-push-sym` `'enum-const` branch; just a fixture.
+- [x] **Enum constant in expressions**
+ - parse: `cc-parse/72-enum-const.c` — `enum E { A=1, B=10, C };
+ return A+B+C;` → exit 22.
+ - Done: locked in the existing `parse-primary` `'enum-const` branch.
-- [ ] **`void *` ↔ `T *` implicit conversion (no cast required)**
- - parse: `cc-parse/NN-voidptr-impl.c` — `void *p; int x=42; p=&x;
+- [x] **`void *` ↔ `T *` implicit conversion (no cast required)**
+ - parse: `cc-parse/73-voidptr-impl.c` — `void *p; int x=42; p=&x;
int *q=p; return *q;` → exit 42.
- - Needs: parser accepts both directions at assignment, return, and
- call sites without an explicit cast. cg's relabel-only path
- between pointer types already supports it.
+ - Done: cg-cast's `to-kind = 'ptr` clause is relabel-only between
+ any pointer types; `cg-assign` drives the cast each direction.
-- [ ] **Implicit narrowing of fixed-arg call arguments to declared
+- [x] **Implicit narrowing of fixed-arg call arguments to declared
param type**
- - parse: `cc-parse/NN-call-narrow.c` — `int f(unsigned char x){return x;}
+ - parse: `cc-parse/74-call-narrow.c` — `int f(unsigned char x){return x;}
int main(){ return f(258); }` → exit 2.
- - Needs: `parse-call-args` emits `cg-cast` per fixed arg to the
- declared param type (variadic args are §G.1).
+ - Done: `parse-call-args` now emits `cg-cast` per fixed arg to the
+ declared param type (variadic args promoted via §G.1).
-- [ ] **Pointer comparison is unsigned**
- - cg: `cc-cg/NN-ptr-cmp.scm` — verify two frame-slot pointers compare
- via `ltu`.
- - parse: `cc-parse/NN-ptr-cmp.c` — `int a[2]; return &a[1] > &a[0];`
+- [x] **Pointer comparison is unsigned**
+ - cg: `cc-cg/68-ptr-cmp.scm` — verifies `%ifelse_ltu` dispatch.
+ - parse: `cc-parse/75-ptr-cmp.c` — `int a[2]; return &a[1] > &a[0];`
→ exit 1.
- - Needs: confirms `cg-binop`'s `lt/le/gt/ge` dispatch picks the
- unsigned variant when either operand is `ptr` or `arr`. Likely
- already correct; locks it in.
+ - Done: `cg-binop`'s `lt/le/gt/ge` dispatch already picks the
+ unsigned variant for ptr/arr operands. Fixtures lock it in.
### L. Aggregates round 2