8 Commits
Author SHA1 Message Date
adrien d53f92482d feat: switch from C to LLVM IR code generation
- Replace all C code generation with LLVM IR (flat DFA model with
  bb_ prefix labels to avoid SSA value name collisions)
- Remove c.min.js, add llvm.min.js highlight.js language definition
- Update shell.nix: gcc -> clang, remove sdl3/mesa deps
- Download LLVM Language Reference to docs/llvm/LangRef.html
- Rename #c-code to #ir-code in HTML, JS, and CSS
- Replace _generateIncludes with _generateLLVMDecls for extern
  function declarations using LLVM_DECL_MAP
- Add string pool (CodeGen.allocString, stringGlobal, llvmStringArg)
  for LLVM IR global string constants with getelementptr references
2026-06-23 03:39:22 +02:00
adrien 35959784de refactor: flat DFA code generation — every block is a label, every edge is a goto
Replace the nested if-else branch-analysis architecture with a flat DFA
model using CodeGen.emitFlat — a single DFS walk emitting each block as
a C label followed by its code and gotos to all successors.

Removed:
- _branchDescendants / emitBranch / generateCallWithError
- _generateCallWithError, _noWalkNext, _genVisited
- generateNextCode, findBackEdges
- WCDecision._branchDescendants / _emitBranch / overridden generateCode

Added:
- CodeGen.emitFlat(entry) — flat DFS emit with labels + gotos
- WCBlock.generateFlowCode() — base emits gotos from wcNextFlow
- WCDecision.generateFlowCode() — if-goto / goto for decisions
- WCProcCall.generateFlowCode() — if (call != 0) goto err / goto ok

Output is flat — zero nested if-else for branch/error handling.
Tests use local out/ directory.
2026-06-23 03:21:22 +02:00
adrien 9b2c8da5dc fix: wrap okCode in else to prevent execution after error path
Success-exclusive code was emitted outside the if-else, so it ran even
when the call failed. Now it's wrapped in else { ... } — shared code
(blocks reachable from both error and success paths) stays outside.
2026-06-23 03:12:58 +02:00
adrien 400870d888 fix: seed _generateCallWithError's local visited set from main traversal
- _emitBranch now sets _genVisited on blocks before calling generateOwnCode
  so that proc calls inside loop bodies can seed their error-handling
  visited set from the main traversal, preventing loop-decision re-walk
- Add _noWalkNext flag on proc calls when error handling is active, so
  _emitBranch skips redundant nextFlow walking (the success path was
  already covered by the error-handling branch emission)
- Known issue: shared blocks that are direct roots of emitBranch (from
  the shared set) may still be re-walked when they were already emitted
  by a downstream proc call's error-handling success path
2026-06-23 03:08:20 +02:00
adrien cefee37cd8 fix: decisions not skipped when encountered in _emitBranch walk
- _emitBranch walk no longer adds decisions to visited before calling
  generateCode — let the decision's own generateCode manage its visited
  tracking. Otherwise the decision's generateCode sees itself as already
  visited and returns empty, dropping its entire subtree.
- Same fix in both codegen/index.js and blocks-algo.js
2026-06-23 02:56:41 +02:00
adrien 82627a3852 refactor: only emit labels for blocks that are actual back-edge targets
- Add CodeGen.findBackEdges(root) pre-pass — DFS-based back-edge
  detection that finds all blocks targeted by at least one back-edge
- Only those blocks get C labels; only those back-edges emit goto
- emitBranch reverts to generateOwnCode + manual successor walking
  (respects stop set properly for shared blocks)
- generateCode/generateNextCode accept loopTargets parameter;
  visited-but-not-back-edge blocks are silently skipped
- No more -Wunused-label warnings in compiled output
2026-06-23 02:51:17 +02:00
adrien 439cc6e7ba feat: loop support via goto labels on each block
- Every block now emits a C label (its id) before its code
- generateNextCode emits goto label; for back-edges (visited targets)
- _emitBranch delegates to generateCode (not generateOwnCode), so labels
  are emitted consistently in both main and branch traversals
- generateCallWithError threads a shared visited set across all three
  emitBranch calls, preventing duplicate label emission for shared blocks
- emitBranch skips roots already visited by previous roots in the same
  branch (prevents spurious gotos from shared-block traversal)
2026-06-23 01:16:14 +02:00
adrien f1eed2d4e0 refactor: extract pure codegen into shared module, remove duplication
- Create codegen/index.js with pure branchDescendants, emitBranch,
  generateCallWithError, and generateCFile — zero DOM dependencies
- blocks-proc.js adapters delegate to CodeGen with browser instanceof check
- run.js uses the same CodeGen module instead of duplicating block classes
  with their own branchDescendants/emitBranch logic
- Load codegen/index.js in browser before blocks-proc.js
2026-06-23 01:07:08 +02:00