fix(lir): resolve all LIR backend regressions — 26/26 examples + selfhost passing

- hir_lower: add isScope=true to lowerBlock; fix resolveExprType for ekIndex,
  ekField on monomorphized structs, and ekTry/ekUnwrap tmpVar typing
- lir_lower: add loop label stack for break/continue; pass null arg to
  bux_task_spawn when spawn has no arguments
- lir_c_backend: multi-pass type inference for temps; include params in
  varTypes; handle lvkTemp in lirLoad; use inferred type in lirAlloca
This commit is contained in:
2026-06-06 19:49:24 +03:00
parent 4f7653a410
commit 797ca7c80c
3 changed files with 191 additions and 60 deletions
+26 -3
View File
@@ -16,12 +16,17 @@ type
funcRetType*: string
## Current source location for debug
currentFile*: string
## Loop end labels for break/continue
loopEndLabels*: seq[string]
loopStartLabels*: seq[string]
proc initLowerToLirCtx*(): LowerToLirCtx =
result = LowerToLirCtx(
builder: initLirBuilder(),
varTypes: initTable[string, string](),
varLirValues: initTable[string, LirValue](),
loopEndLabels: @[],
loopStartLabels: @[],
)
# ── Helpers ──
@@ -360,6 +365,8 @@ proc lowerExpr(ctx: var LowerToLirCtx, node: HirNode): LirValue =
var args: seq[LirValue] = @[]
if node.spawnArgs.len > 0:
args.add(lowerExpr(ctx, node.spawnArgs[0]))
else:
args.add(lirInt(0))
let t = b.freshTemp()
b.emitAlloca(t.strVal, "void*")
b.emitCall(t, "bux_task_spawn", @[lirGlobal(node.spawnCallee)] & args)
@@ -492,28 +499,44 @@ proc lowerStmt(ctx: var LowerToLirCtx, node: HirNode) =
let bodyLbl = b.freshLabel("wbody")
let endLbl = b.freshLabel("wend")
ctx.loopStartLabels.add(startLbl.strVal)
ctx.loopEndLabels.add(endLbl.strVal)
b.emitLabel(startLbl)
let cond = lowerExpr(ctx, node.whileCond)
b.emitJz(endLbl, cond)
lowerStmt(ctx, node.whileBody)
b.emitJmp(startLbl)
b.emitLabel(endLbl)
discard ctx.loopStartLabels.pop()
discard ctx.loopEndLabels.pop()
# ── Loop (infinite) ──
of hLoop:
let startLbl = b.freshLabel("loop")
let endLbl = b.freshLabel("lend")
ctx.loopStartLabels.add(startLbl.strVal)
ctx.loopEndLabels.add(endLbl.strVal)
b.emitLabel(startLbl)
lowerStmt(ctx, node.loopBody)
b.emitJmp(startLbl)
b.emitLabel(endLbl)
discard ctx.loopStartLabels.pop()
discard ctx.loopEndLabels.pop()
# ── Break ──
of hBreak:
# We emit a break label reference; the emitter tracks the nearest loop end
b.emitRawC("break;")
if ctx.loopEndLabels.len > 0:
b.emitJmp(lirLabel(ctx.loopEndLabels[^1]))
else:
b.emitRawC("break;")
# ── Continue ──
of hContinue:
b.emitRawC("continue;")
if ctx.loopStartLabels.len > 0:
b.emitJmp(lirLabel(ctx.loopStartLabels[^1]))
else:
b.emitRawC("continue;")
# ── Alloca ──
of hAlloca: