Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

codegen: don't use PSym for labels #940

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/backend/ccgexprs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -2208,7 +2208,7 @@ proc expr(p: BProc, n: CgNode, d: var TLoc) =
of cnkRaiseStmt: genRaiseStmt(p, n)
of cnkPragmaStmt: discard
of cnkInvalid, cnkType, cnkAstLit, cnkMagic, cnkRange, cnkBinding, cnkExcept,
cnkFinally, cnkBranch:
cnkFinally, cnkBranch, cnkLabel:
internalError(p.config, n.info, "expr(" & $n.kind & "); unknown node kind")

proc getDefaultValue(p: BProc; typ: PType; info: TLineInfo): Rope =
Expand Down
29 changes: 16 additions & 13 deletions compiler/backend/ccgstmts.nim
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,23 @@ proc inExceptBlockLen(p: BProc): int =
for x in p.nestedTryStmts:
if x.inExcept: result.inc

proc startBlockInternal(p: BProc): int {.discardable.} =
proc startBlockInternal(p: BProc, blk: int) =
inc(p.labels)
result = p.blocks.len
let result = p.blocks.len
setLen(p.blocks, result + 1)
p.blocks[result].id = p.labels
p.blocks[result].blk = blk
p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16
p.blocks[result].nestedExceptStmts = p.inExceptBlockLen.int16

template startBlock(p: BProc, start: FormatStr = "{$n",
args: varargs[Rope]): int =
args: varargs[Rope]) =
lineCg(p, cpsStmts, start, args)
startBlockInternal(p)
startBlockInternal(p, 0)

template startBlock(p: BProc, id: BlockId) =
lineCg(p, cpsStmts, "{$n", [])
startBlockInternal(p, id.int + 1)

proc endBlock(p: BProc)

Expand Down Expand Up @@ -315,19 +320,17 @@ proc genRepeatStmt(p: BProc, t: CgNode) =
dec(p.withinLoop)

proc genBlock(p: BProc, n: CgNode) =
assert n[0].kind == cnkSym
let
breakIdx = startBlock(p)
sym = n[0].sym
sym.position = breakIdx + 1
startBlock(p, n[0].label)
genStmts(p, n[1])
endBlock(p)

proc genBreakStmt(p: BProc, t: CgNode) =
assert(t[0].kind == cnkSym)
let sym = t[0].sym
doAssert(sym.kind == skLabel)
let idx = sym.position-1
assert t[0].kind == cnkLabel
var idx = p.blocks.high
# search for the ``TBlock`` that corresponds to the label. `blk` stores the
# ID offset by 1, which has to be accounted for here
while idx >= 0 and p.blocks[idx].blk != (t[0].label.int + 1):
dec idx

let label = assignLabel(p.blocks[idx])
blockLeaveActions(p,
Expand Down
7 changes: 5 additions & 2 deletions compiler/backend/cgendata.nim
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,9 @@ type
BProc* = ref TCProc
TBlock* = object
id*: int ## the ID of the label; positive means that it
blk*: int ## the ``BlockId`` + 1 of the block.
## '0' if the ``TBlock`` doesn't correspond to a
## ``cnkBlockStmt``
label*: Rope ## generated text for the label
## nil if label is not used
sections*: TCProcSections ## the code belonging
Expand Down Expand Up @@ -370,7 +373,7 @@ proc hash(n: ConstrTree): Hash =
for it in n.items:
result = result !& hashTree(it)
of cnkInvalid, cnkAstLit, cnkPragmaStmt, cnkReturnStmt, cnkMagic,
cnkWithOperand, cnkLocal:
cnkWithOperand, cnkLocal, cnkLabel:
unreachable()
result = !$result

Expand Down Expand Up @@ -400,7 +403,7 @@ proc `==`(a, b: ConstrTree): bool =
if not treesEquivalent(a[i], b[i]): return
result = true
of cnkInvalid, cnkAstLit, cnkPragmaStmt, cnkReturnStmt, cnkMagic,
cnkWithOperand, cnkLocal:
cnkWithOperand, cnkLocal, cnkLabel:
# nodes that cannot appear in construction trees
unreachable()

Expand Down
7 changes: 7 additions & 0 deletions compiler/backend/cgir.nim
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type
cnkAstLit ## a ``NimNode`` literal

cnkSym
cnkLabel ## name of a block
cnkLocal ## reference to a local
# future direction: split up ``cnkSym`` in the way the MIR does it
cnkMagic ## name of a magic procedure. Only valid in the callee
Expand Down Expand Up @@ -164,6 +165,10 @@ type
name*: PIdent
## either the user-defined name or 'nil'

BlockId* = distinct uint32
## Identifies a block within another block -- the IDs are **not** unique
## within a ``Body``. An outermost block has ID 0, a block within the
## block ID 1, etc.
LocalId* = distinct uint32
## Identifies a local within a procedure.

Expand All @@ -182,6 +187,7 @@ type
of cnkAstLit: astLit*: PNode
of cnkSym: sym*: PSym
of cnkMagic: magic*: TMagic
of cnkLabel: label*: BlockId
of cnkLocal: local*: LocalId
of cnkPragmaStmt: pragma*: TSpecialWord
of cnkWithOperand: operand*: CgNode
Expand Down Expand Up @@ -258,6 +264,7 @@ func newLocalRef*(id: LocalId, info: TLineInfo, typ: PType): CgNode =
CgNode(kind: cnkLocal, info: info, typ: typ, local: id)

proc `==`*(x, y: LocalId): bool {.borrow.}
proc `==`*(x, y: BlockId): bool {.borrow.}

proc merge*(dest: var Body, source: Body): CgNode =
## Merges `source` into `dest` by appending the former to the latter.
Expand Down
28 changes: 16 additions & 12 deletions compiler/backend/cgirgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import
ast_types,
ast_idgen,
ast_query,
idents,
lineinfos,
types
],
Expand All @@ -57,6 +56,7 @@ import
]

from compiler/ast/ast import newSym, newType, rawAddSon
from compiler/ast/idents import whichKeyword
from compiler/sem/semdata import makeVarType

# TODO: move the procedure somewhere common
Expand Down Expand Up @@ -97,7 +97,6 @@ type

TranslateCl = object
graph: ModuleGraph
cache: IdentCache
idgen: IdGenerator

owner: PSym
Expand All @@ -107,8 +106,8 @@ type
localsMap: Table[int, LocalId]
## maps a sybmol ID to the corresponding local. Needed because normal
## local variables reach here as ``PSym``s
labelMap: SeqMap[LabelId, PSym]
## maps a block-label name to the ``PSym`` created for it
blocks: seq[LabelId]
## the stack of enclosing blocks for the currently processed node

locals: Store[LocalId, Local]
## the in-progress list of all locals in the translated body
Expand Down Expand Up @@ -247,6 +246,9 @@ func newTypeNode(info: TLineInfo, typ: PType): CgNode =
func newSymNode(s: PSym; info = unknownLineInfo): CgNode =
CgNode(kind: cnkSym, info: info, typ: s.typ, sym: s)

func newLabelNode(blk: BlockId; info = unknownLineInfo): CgNode =
CgNode(kind: cnkLabel, info: info, label: blk)

proc newExpr(kind: CgNodeKind, info: TLineInfo, typ: PType,
kids: sink seq[CgNode]): CgNode =
## Variant of ``newExpr`` optimized for passing a pre-existing child
Expand Down Expand Up @@ -907,13 +909,11 @@ proc tbSingleStmt(tree: TreeWithSource, cl: var TranslateCl, n: MirNode,
result = newStmt(cnkRepeatStmt, info, body())
leave(tree, cr)
of mnkBlock:
let sym = newSym(skLabel, cl.cache.getIdent("label"), cl.idgen.nextSymId(),
cl.owner, info)
cl.labelMap[n.label] = sym

cl.blocks.add n.label # push the label to the stack
result = newStmt(cnkBlockStmt, info,
newSymNode(sym), # the label
newLabelNode(cl.blocks.high.BlockId, info),
body())
cl.blocks.setLen(cl.blocks.len - 1) # pop block from the stack
leave(tree, cr)
of mnkTry:
result = newStmt(cnkTryStmt, info, [body()])
Expand Down Expand Up @@ -946,7 +946,12 @@ proc tbSingleStmt(tree: TreeWithSource, cl: var TranslateCl, n: MirNode,

leave(tree, cr)
of mnkBreak:
result = newStmt(cnkBreakStmt, info, [newSymNode(cl.labelMap[n.label])])
# find the stack index of the enclosing 'block' identified by the break's
# label; we use the index as the ID
var idx = cl.blocks.high
while idx >= 0 and cl.blocks[idx] != n.label:
dec idx
result = newStmt(cnkBreakStmt, info, [newLabelNode(BlockId idx, info)])
of mnkReturn:
result = newNode(cnkReturnStmt, info)
of mnkPNode:
Expand Down Expand Up @@ -1391,8 +1396,7 @@ proc generateIR*(graph: ModuleGraph, idgen: IdGenerator, owner: PSym,
## using `idgen` for provide new IDs when creating symbols. `sourceMap`
## must be the ``SourceMap`` corresponding to `tree` and is used as the
## provider for source position information
var cl = TranslateCl(graph: graph, idgen: idgen, cache: graph.cache,
owner: owner)
var cl = TranslateCl(graph: graph, idgen: idgen, owner: owner)
if owner.kind in routineKinds:
# setup the locals and associated mappings for the parameters
template add(v: PSym) =
Expand Down
6 changes: 6 additions & 0 deletions compiler/backend/cgirutils.nim
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ proc treeRepr*(n: CgNode): string =
result.add n.sym.name.s
result.add " id: "
result.add $n.sym.itemId
of cnkLabel:
result.add "label: "
result.addInt n.label.int
of cnkLocal:
result.add "local: "
result.add $n.local.int
Expand Down Expand Up @@ -161,6 +164,9 @@ proc render(c: var RenderCtx, body: Body, ind: int, n: CgNode,
else:
# magics are never cursors nor do they need disambiguation
res.add s.name.s
of cnkLabel:
res.add ":label_"
res.addInt n.label.int
of cnkLocal:
let name = body[n.local].name
if name.isNil:
Expand Down
31 changes: 7 additions & 24 deletions compiler/backend/jsgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,6 @@ type
# might be nil.
# (see `maybeMakeTemp`)

TBlock = object
id: int # the ID of the label; positive means that it
# has been used (i.e. the label should be emitted)

PGlobals* = ref object
typeInfo, constants*, code*: Rope
typeInfoGenerated: IntSet
Expand Down Expand Up @@ -147,7 +143,9 @@ type
g: PGlobals
beforeRetNeeded: bool
unique: int # for temp identifier generation
blocks: seq[TBlock]
blocks: seq[int]
## the stack of enclosing blocks, indexed by ``BlockId``. Each entry
## stores the number to use for the label name
extraIndent: int

locals: OrdinalSeq[LocalId, Loc]
Expand Down Expand Up @@ -890,31 +888,16 @@ proc genCaseJS(p: PProc, n: CgNode) =

proc genBlock(p: PProc, n: CgNode) =
inc(p.unique)
let idx = p.blocks.len
if n[0].kind != cnkEmpty:
# named block?
p.config.internalAssert(n[0].kind == cnkSym, n.info, "genBlock")
var sym = n[0].sym
sym.position = idx+1
let labl = p.unique
lineF(p, "Label$1: {$n", [labl.rope])
setLen(p.blocks, idx + 1)
p.blocks[idx].id = - p.unique # negative because it isn't used yet
p.blocks.add labl # push a new block
genStmt(p, n[1])
setLen(p.blocks, idx)
p.blocks.setLen(p.blocks.len - 1) # pop the block from the stack
lineF(p, "}$n", [labl.rope])

proc genBreakStmt(p: PProc, n: CgNode) =
var idx: int
genLineDir(p, n)
if true:
assert(n[0].kind == cnkSym)
let sym = n[0].sym
assert(sym.kind == skLabel)
idx = sym.position-1

p.blocks[idx].id = abs(p.blocks[idx].id) # label is used
lineF(p, "break Label$1;$n", [rope(p.blocks[idx].id)])
lineF(p, "break Label$1;$n", [$p.blocks[n[0].label.int]])

proc genAsmOrEmitStmt(p: PProc, n: CgNode) =
genLineDir(p, n)
Expand Down Expand Up @@ -2547,7 +2530,7 @@ proc gen(p: PProc, n: CgNode, r: var TCompRes) =
of cnkRaiseStmt: genRaiseStmt(p, n)
of cnkPragmaStmt: discard
of cnkInvalid, cnkMagic, cnkRange, cnkBinding, cnkExcept, cnkFinally,
cnkBranch, cnkAstLit:
cnkBranch, cnkAstLit, cnkLabel:
internalError(p.config, n.info, "gen: unknown node type: " & $n.kind)

proc newModule*(g: ModuleGraph; module: PSym): BModule =
Expand Down
41 changes: 13 additions & 28 deletions compiler/vm/vmgen.nim
Original file line number Diff line number Diff line change
Expand Up @@ -123,19 +123,16 @@ type
## register storing the backing location
kind: TSlotKind

TBlock = object
label: PSym
fixups: seq[TPosition]

LocalLoc = object
## The current state for a local.
reg: TRegister ## the register that holds either the handle or value
isIndirect: bool ## whether the local uses a handle while its value
## would fit it into a register

BProc = object
blocks: seq[TBlock]
## blocks; temp data structure
blocks: seq[seq[TPosition]]
## for each block, the jump instructions targeting the block's exit.
## These need to be patched once the code for the block is generated
sym: PSym
body: Body
## the full body of the current procedure/statement/expression
Expand Down Expand Up @@ -591,17 +588,6 @@ template withTemp(tmp, n, typ, body: untyped) {.dirty.} =
body
c.freeTemp(tmp)

proc popBlock(c: var TCtx; oldLen: int) =
for f in c.prc.blocks[oldLen].fixups:
c.patch(f)
c.prc.blocks.setLen(oldLen)

template withBlock(labl: PSym; body: untyped) {.dirty.} =
var oldLen {.gensym.} = c.prc.blocks.len
c.prc.blocks.add TBlock(label: labl, fixups: @[])
body
popBlock(c, oldLen)

proc gen(c: var TCtx; n: CgNode; dest: var TDest)
proc gen(c: var TCtx; n: CgNode; dest: TRegister) =
var d: TDest = dest
Expand Down Expand Up @@ -649,8 +635,14 @@ proc genRepeat(c: var TCtx; n: CgNode) =

proc genBlock(c: var TCtx; n: CgNode) =
let oldRegisterCount = c.prc.regInfo.len
withBlock(n[0].sym):
c.gen(n[1])

c.prc.blocks.add @[] # push a new block
c.gen(n[1])
# fixup the jumps:
for pos in c.prc.blocks[^1].items:
c.patch(pos)
# pop the block again:
c.prc.blocks.setLen(c.prc.blocks.len - 1)

for i in oldRegisterCount..<c.prc.regInfo.len:
when not defined(release):
Expand All @@ -665,14 +657,7 @@ proc genBlock(c: var TCtx; n: CgNode) =

proc genBreak(c: var TCtx; n: CgNode) =
let lab1 = c.xjmp(n, opcJmp)
block search:
for i in countdown(c.prc.blocks.len-1, 0):
if c.prc.blocks[i].label == n[0].sym:
c.prc.blocks[i].fixups.add lab1
break search

# the corresponding block seems to be missing?
unreachable("break target is missing")
c.prc.blocks[n[0].label.int].add lab1

proc genIf(c: var TCtx, n: CgNode) =
# if (!expr1) goto lab1;
Expand Down Expand Up @@ -3062,7 +3047,7 @@ proc gen(c: var TCtx; n: CgNode; dest: var TDest) =
of cnkPragmaStmt, cnkAsmStmt, cnkEmitStmt:
unused(c, n, dest)
of cnkInvalid, cnkMagic, cnkRange, cnkExcept, cnkFinally, cnkBranch,
cnkBinding:
cnkBinding, cnkLabel:
unreachable(n.kind)

proc initProc(c: TCtx, owner: PSym, body: sink Body): BProc =
Expand Down
Loading
Loading