- StructureKind enum (18 kinds), IRStructure entity, IRStructureId
- Structure capnp schema, entity providers, pack/unpack
- Structure generation (PushStructure/PopStructure) for all control flow
- FUNCTION_SCOPE, nested SCOPE for CompoundStmt, implicit SCOPE for for-init
- ENTER_SCOPE/EXIT_SCOPE opcodes on all paths (including break/continue/return/goto)
- Block parentStructureId, scope object association via AssociateObjectWithScope
- IRFunction::body_scope(), IRBlock::parent_structure() accessors
- SWITCH_CASE structures for each case/default
- IRSwitchCase → IRStructure(SWITCH_CASE) full migration (deferred)
- Full Python bindings (stub exists, requires bootstrap regen)
- GenerateGlobalInit creates synthetic FunctionIR for globals with initializers
- FunctionKind::GLOBAL_INITIALIZER, sourceDeclEntityId = VarDecl
- Entry block with ADDRESS_OF → EmitRValue(init) → STORE → RET
- VarDecl maps to its GLOBAL_INITIALIZER IRFunction
- MEMSET (opcode 68): dest, byte_value, size — lowered from memset/builtin calls
- MEMCPY (opcode 69): dest, src, size — lowered from memcpy/memmove/builtin calls
- MemsetInst, MemcpyInst instruction class wrappers
- VAR_INIT block kind + structure kind (for variable initialization regions)
- IRSwitchCase still separate entity type (coexists with SWITCH_CASE structures)
- string_bytes() missing on IRObject for string literals
- Python bindings are stub only for IRStructure
- Global initializer quality depends on EmitRValue handling of all init expressions
- Goto/Duff's device scope compensation:
gotothat jumps into the middle of a scope bypasses the normal ENTER_SCOPE path. An interpreter following the goto would not see the scope entry for variables in that scope. Similarly, Duff's device-style switch cases can interleave with loop bodies, creating scope entry paths that don't go through ENTER_SCOPE. We need "compensation blocks" — synthetic blocks inserted on goto/case edges that emit the ENTER_SCOPE instructions for any scopes being entered. This is tricky because the label/case might also be reachable from normal control flow (which already has the ENTER_SCOPE), so we can't just add ENTER_SCOPE at the label — we need it on the specific edge. Always using compensation blocks (even for the normal case) would be the simplest correct solution.
- Phase 3 merged into Phase 2
- SWITCH_CASE structures coexist with IRSwitchCase for backward compat
- ENTER_SCOPE/EXIT_SCOPE carry IRStructureId extra in entity pool
- StructureKind embedded in IRStructureId (18 sub_kind offsets)
- Global initializer uses same EmitRValue path as function body codegen
- MEMSET/MEMCPY lowered from memset/memcpy/memmove and all _builtin variants
- Goto conservatively exits all scopes to FUNCTION_SCOPE