Quartz v5.25

Handoff — SYS.1 Kickoff: Items 1, 2, 3, 5 Shipped

Head: a24b7d96 on trunk. Fixpoint stable at 2115 functions. Context: First session after Binary DSL Phase 2 wrapped. Kernel Epic planning artifacts landed, then four SYS.1 items shipped on top.

What shipped (in order)

CommitSliceScope
3f396d6ePlanning artifacts (Kernel Epic + effects plan)Docs only: ROADMAP Tier 6, KERNEL_EPIC.md, research/EFFECTS_IMPLEMENTATION_PLAN.md, research/NOTATION_PRIMER.md.
98da3295SYS.1 item 1 — atomic RMW completenessMerged from worktree-agent-ad2ef9f1 (rebased onto post-Track-B trunk). atomic_and / or / xor / min / max with all 5 orderings; 19/19 spec tests green.
7c6a3a84KERNEL_EPIC discovery: UFCS alias collisionDocs: .and/.or collide with lexer keywords, .min/.max shadow Array builtins. Free-function form works for all five.
c1ad8f23SYS.1 item 2 — Quake linker-script passthroughNew link_baremetal(objs, out, script, flags) in std/quake.qz; baremetal:verify task; hand-written aarch64 asm smoke.
5f51a2a4SYS.1 item 3 — target knobs passthroughNew assemble(src, out, target, flags) + compile_llc_to_obj(ll, out, flags) in std/quake.qz; baremetal:verify_x86_64_knobs task verifies -mattr=-sse,-mmx,-avx -relocation-model=static -code-model=kernel flow through. Hand-written x86_64 IR with deliberate memcpy forces meaningful negative test.
a24b7d96SYS.1 item 5 — @weak function attributeFull compiler change: parser + ast + mir + mir_lower + codegen. Emits LLVM define weak. 6 spec tests. Rejects @weak on non-function decls.

SYS.1 punch list

ItemStatusNotes
1 — atomic RMW completeness✓ DONEcommit 98da3295
2 — Quake linker-script passthrough✓ DONEcommit c1ad8f23
3 — target knobs passthrough✓ DONEcommit 5f51a2a4
4 — field-level @[align(N)]OPENDeferred — requires struct layout redesign. Quartz uses a flat i64 slot model today; real field alignment changes offset math and touches mir_lower struct layout + codegen GEP offsets + alloca alignment. Medium-large.
5 — @weak function attribute✓ DONEcommit a24b7d96
6 — @[panic_handler] hookOPENHighest strategic value for next session. Unblocks full freestanding .qz compilation. Requires parser attr + typecheck validation + prelude rewiring (prelude panic fns currently call libc write/strlen/longjmp/exit unconditionally) + optional mark-prelude-internal-linkage so globaldce prunes unused panic helpers.
7 — custom TLS (FS/GS, TPIDR intrinsics)OPENRuntime + codegen. Medium.
8 — custom calling conventions (extern "x86-interrupt", extern "sysv64")OPENLargest remaining. Parser + codegen function attribute emission.
9 — @[weak] on globals, @[alias("sym")]OPENSmall extensions of item 5. Not blocking anything.

Recommended next slice: @[panic_handler] (item 6). Two reasons:

  1. It’s the one remaining blocker on full .qz freestanding compilation (see discovery in docs/KERNEL_EPIC.md). Until this lands, tools/baremetal/hello.qz cannot reach an ELF, and the baremetal:verify* tasks have to use hand-written asm/IR instead of Quartz source.
  2. It validates @weak in a real use case: the default panic handler can be @weak def __qz_panic(msg: String): Void and the kernel overrides with a strong definition.

Alternate smaller slices if context is tight: @weak on globals, @[alias("sym")], or extern "sysv64" calling convention.

State of the tree

  • Trunk HEAD: a24b7d96
  • Fixpoint: 2115 functions, gen1 == gen2 byte-identical
  • Smokes: brainfuck PASS, style_demo PASS
  • baremetal:verify (aarch64): PASS
  • baremetal:verify_x86_64_knobs: PASS (zero xmm instructions emitted with knobs; 2 xmm instructions emitted WITHOUT knobs — regression-catching)
  • Relevant specs: atomic_rmw 19/19, memory_ordering 25/25, weak_attribute 6/6

Discoveries filed during the session

All in docs/KERNEL_EPIC.md under “Discoveries During Implementation”:

  1. UFCS method alias collision on atomic RMW intrinsics. .and / .or collide with lexer keywords, .min / .max shadow Array builtins. Free-function form works. Cosmetic, non-blocking.
  2. Freestanding prelude undefined globals / libc references. cg_emit_runtime_decls early-returns for freestanding targets, suppressing @.panic.prefix / @.newline globals — but the auto-emitted prelude unwrap / unwrap_ok / unwrap_err reference them AND call @write / @strlen / @longjmp / @exit. Real fix is item 6 (@[panic_handler] + internal linkage on prelude fns).

Pre-existing issue also surfaced (not filed):

  1. ps_error non-advancing on unknown attributes causes infinite loop. Both current binary and the backup exhibit the same hang on @bogus input. Pre-existing pattern — ps_error prints but doesn’t advance, so parser recovery loops. Already noted in session memory as a standing quirk; not my regression.

Guard / fixpoint hash recipe mismatch (meta-finding, worked around)

Guard’s stamp and the pre-commit hook’s check both use

find self-hosted -name '*.qz' -not -path '*/bin/*' | sort | xargs cat | shasum -a 256

but if guard runs from a git worktree, gitignored files like self-hosted/bootstrap.qz are absent, so the stamp hashes a subset. Pre-commit hook runs from the main working tree and the hash mismatches. Worked around by re-running guard from main tree. Durable fix: either exclude bootstrap.qz from both recipes, or formally register bootstrap.qz as compiler source. Low priority — only matters when guard runs from a worktree and the resulting stamp later faces the main-tree hook.

Safety rails (unchanged)

  • quake guard mandatory for any commit touching self-hosted/*.qz. The pre-commit hook enforces it. Do not --no-verify.
  • Smokes (brainfuck + style_demo) after every guard. Both green at head.
  • Fix-specific backup from this session: self-hosted/bin/backups/quartz-pre-weak-attr-golden.
  • Full QSpec NOT safe in Claude Code PTY — use quake qspec_file FILE=... or QUARTZ_COMPILER=./self-hosted/bin/quartz /tmp/<spec_bin> for targeted runs.