mirror of
https://github.com/nim-lang/Nim.git
synced 2026-09-01 19:33:42 +00:00
cgen: replace indexed child loops with the sons/isons/sonsFrom iterators
`for i in k..<n.len: ... n[i] ...` is the dominant shape for walking a `PNode`'s children in the code generator: 41 such loops across the cgen files, and 777 indexed node accesses in total. It reads worse than iterating, it bounds-checks every subscript, and it is quadratic the moment the backend reads children off a NIF `Cursor` rather than a materialised tree (a child is `firstSon` plus one `skip` per preceding sibling, and `skip` steps over a whole subtree). 31 of the 41 are converted: * 20 to `sons`/`sonsFrom` — the index only ever subscripted `n`. * 9 to `isons`, which now takes a `start` index (defaulting to 0, so its eight existing call sites are unchanged). These genuinely need `i`: a parallel index into the routine's `PType` (`typ.n[i]`, `typ[i]`), a `needTmp[i-1]` lookup, an `i == field.position` test, `$i` in a generated struct name, or the index passed straight to `genOtherArg`. * 2 to `sonsFrom` with a variable start (`firstParam`, `offset`). `sonsFrom` is new, next to `sons`/`isons` in astdef. The remaining 10 are deliberate. Eight are not `PNode` at all — `varargs[Snippet]`, `seq[PSym]`, `string`, and `PType`, where `sons` is a `proc ...: var TTypeSeq` rather than an iterator, so a blind rewrite would compile into something quite different. Two iterate `0..<it.len-1`, excluding the last child, which no iterator expresses cleanly. Pure refactor, and verified as one: all 219 generated `.c` files of a 219-module program and the linked binary are byte-identical to the parent commit. That is the bar that matters here, because the index arithmetic (`i-1`, `i == position`, `$i`) is the easy thing to get wrong. It also caught a real slip on the way: `genFieldCheck` reassigns its loop variable, which a `for` binding cannot do. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -960,10 +960,22 @@ iterator sons*(n: PNode): PNode =
|
||||
## as it does not rely on random indexed access (see doc/ic_backend_nif_native.md).
|
||||
for i in 0..<n.safeLen: yield n[i]
|
||||
|
||||
iterator isons*(n: PNode): tuple[i: int, n: PNode] =
|
||||
## Like `sons` but also yields the child index. Replaces
|
||||
## `for i in 0..<n.len: ... n[i] ...` when `i` itself is still needed.
|
||||
for i in 0..<n.safeLen: yield (i, n[i])
|
||||
iterator isons*(n: PNode; start = 0): tuple[i: int, n: PNode] =
|
||||
## Like `sons` but also yields the child index, and optionally skips the first
|
||||
## `start` children. Replaces `for i in start..<n.len: ... n[i] ...` when `i`
|
||||
## itself is still needed — for a parameter position, a `needTmp[i-1]` lookup,
|
||||
## a parallel index into the routine's `PType`, and so on. `start` is almost
|
||||
## always 1, to step over a call's callee or a case statement's selector.
|
||||
##
|
||||
## Use `sonsFrom` instead when the index is only ever used to subscript `n`.
|
||||
for i in start..<n.safeLen: yield (i, n[i])
|
||||
|
||||
iterator sonsFrom*(n: PNode; start: int): PNode =
|
||||
## `sons` skipping the first `start` children. Replaces
|
||||
## `for i in start..<n.len: ... n[i] ...`, which is by far the commonest
|
||||
## indexed shape in the code generator — `start` is almost always 1, to step
|
||||
## over a case/try statement's selector or a call's callee.
|
||||
for i in start..<n.safeLen: yield n[i]
|
||||
|
||||
when defined(useNodeIds):
|
||||
const nodeIdToDebug* = -1 # 2322968
|
||||
|
||||
@@ -49,8 +49,7 @@ proc preventNrvo(p: BProc; dest, le, ri: PNode): bool =
|
||||
|
||||
result = false
|
||||
if le != nil:
|
||||
for i in 1..<ri.len:
|
||||
let r = ri[i]
|
||||
for r in sonsFrom(ri, 1):
|
||||
if isPartOf(le, r, {pfStructural}) != arNo: return true
|
||||
# we use the weaker 'canRaise' here in order to prevent too many
|
||||
# annoying warnings, see #14514
|
||||
@@ -59,8 +58,7 @@ proc preventNrvo(p: BProc; dest, le, ri: PNode): bool =
|
||||
message(p.config, le.info, warnObservableStores, $le)
|
||||
# bug #19613 prevent dangerous aliasing too:
|
||||
if dest != nil and dest != le:
|
||||
for i in 1..<ri.len:
|
||||
let r = ri[i]
|
||||
for r in sonsFrom(ri, 1):
|
||||
if isPartOf(dest, r, {pfStructural}) != arNo: return true
|
||||
|
||||
proc hasNoInit(call: PNode): bool {.inline.} =
|
||||
@@ -474,19 +472,19 @@ proc genParams(p: BProc, ri: PNode, typ: PType; result: var Builder, argBuilder:
|
||||
# Optimization: don't use a temp, if we would only take the address anyway
|
||||
needTmp[i - 1] = false
|
||||
|
||||
for i in 1..<ri.len:
|
||||
for i, it in isons(ri, 1):
|
||||
if i < typ.n.len:
|
||||
assert(typ.n[i].kind == nkSym)
|
||||
let paramType = typ.n[i]
|
||||
if not paramType.typ.isCompileTimeOnly:
|
||||
var arg = newBuilder("")
|
||||
genArg(p, ri[i], paramType.sym, ri, arg, needTmp[i-1])
|
||||
genArg(p, it, paramType.sym, ri, arg, needTmp[i-1])
|
||||
if arg.buf.len != 0:
|
||||
result.addArgument(argBuilder):
|
||||
result.add(extract(arg))
|
||||
else:
|
||||
var arg = newBuilder("")
|
||||
genArgNoParam(p, ri[i], arg, needTmp[i-1])
|
||||
genArgNoParam(p, it, arg, needTmp[i-1])
|
||||
if arg.buf.len != 0:
|
||||
result.addArgument(argBuilder):
|
||||
result.add(extract(arg))
|
||||
@@ -727,7 +725,7 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType; result: var Bu
|
||||
case pat[i]
|
||||
of '@':
|
||||
var callBuilder = default(CallBuilder) # not init call builder
|
||||
for k in j..<ri.len:
|
||||
for k, _ in isons(ri, j):
|
||||
genOtherArg(p, ri, k, typ, result, callBuilder)
|
||||
inc i
|
||||
of '#':
|
||||
@@ -811,7 +809,7 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
pl.add(op.snippet)
|
||||
var res = newBuilder("")
|
||||
var call = initCallBuilder(res, extract(pl))
|
||||
for i in 2..<ri.len:
|
||||
for i, _ in isons(ri, 2):
|
||||
genOtherArg(p, ri, i, typ, res, call)
|
||||
fixupCall(p, le, ri, d, res, call)
|
||||
|
||||
@@ -842,7 +840,7 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
|
||||
if ri.len > 2:
|
||||
pl.add(": ")
|
||||
genArg(p, ri[2], typ.n[2].sym, ri, pl)
|
||||
for i in start..<ri.len:
|
||||
for i, it in isons(ri, start):
|
||||
if i >= typ.n.len:
|
||||
internalError(p.config, ri.info, "varargs for objective C method?")
|
||||
assert(typ.n[i].kind == nkSym)
|
||||
@@ -850,7 +848,7 @@ proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
|
||||
pl.add(" ")
|
||||
pl.add(param.name.s)
|
||||
pl.add(": ")
|
||||
genArg(p, ri[i], param, ri, pl)
|
||||
genArg(p, it, param, ri, pl)
|
||||
if typ.returnType != nil:
|
||||
if isInvalidReturnType(p.config, typ):
|
||||
if ri.len > 1: pl.add(" ")
|
||||
|
||||
@@ -1073,8 +1073,8 @@ proc genInExprAux(p: BProc, e: PNode, a, b, d: var TLoc)
|
||||
|
||||
proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym, ty: PType) =
|
||||
var test, u, v: TLoc
|
||||
for i in 1..<e.len:
|
||||
var it = e[i]
|
||||
for child in sonsFrom(e, 1):
|
||||
var it = child
|
||||
assert(it.kind in nkCallKinds)
|
||||
assert(it.firstSon.kind == nkSym)
|
||||
let op = it.firstSon.sym
|
||||
@@ -1932,15 +1932,15 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
|
||||
r = rdLoc(d)
|
||||
discard getTypeDesc(p.module, t)
|
||||
let ty = getUniqueType(t)
|
||||
for i in 1..<e.len:
|
||||
if nfPreventCg in e[i].flags:
|
||||
for it in sonsFrom(e, 1):
|
||||
if nfPreventCg in it.flags:
|
||||
# this is an object constructor node generated by the VM and
|
||||
# this field is in an inactive case branch, don't generate assignment
|
||||
continue
|
||||
var check: PNode = nil
|
||||
if e[i].len == 3 and optFieldCheck in p.options:
|
||||
check = e[i][2]
|
||||
genFieldObjConstr(p, ty, useTemp, isRef, e[i].firstSon, e[i][1], check, d, r, e.info)
|
||||
if it.len == 3 and optFieldCheck in p.options:
|
||||
check = it[2]
|
||||
genFieldObjConstr(p, ty, useTemp, isRef, it.firstSon, it[1], check, d, r, e.info)
|
||||
|
||||
if useTemp:
|
||||
if d.k == locNone:
|
||||
@@ -2447,8 +2447,7 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) =
|
||||
b = initLoc(locExpr, e, OnUnknown)
|
||||
if e[1].len > 0:
|
||||
var val: Snippet = ""
|
||||
for i in 0..<e[1].len:
|
||||
let it = e[1][i]
|
||||
for it in sons(e[1]):
|
||||
var currentExpr: Snippet
|
||||
if it.kind == nkRange:
|
||||
x = initLocExpr(p, it.firstSon)
|
||||
@@ -3861,8 +3860,7 @@ proc containsOpaqueImportcFieldAux(t: PType; n: PNode): bool =
|
||||
of nkRecCase:
|
||||
if containsOpaqueImportcFieldAux(t, n.firstSon):
|
||||
return true
|
||||
for i in 1..<n.len:
|
||||
let branch = n[i]
|
||||
for branch in sonsFrom(n, 1):
|
||||
if branch.kind == nkOfBranch or branch.kind == nkElse:
|
||||
if containsOpaqueImportcFieldAux(t, branch.lastSon):
|
||||
return true
|
||||
@@ -4003,13 +4001,13 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
|
||||
var branch = Zero
|
||||
if constOrNil != nil:
|
||||
## find kind value, default is zero if not specified
|
||||
for i in 1..<constOrNil.len:
|
||||
if constOrNil[i].kind == nkExprColonExpr:
|
||||
if constOrNil[i].firstSon.sym.name.id == obj.firstSon.sym.name.id:
|
||||
branch = getOrdValue(constOrNil[i][1])
|
||||
for i, it in isons(constOrNil, 1):
|
||||
if it.kind == nkExprColonExpr:
|
||||
if it.firstSon.sym.name.id == obj.firstSon.sym.name.id:
|
||||
branch = getOrdValue(it[1])
|
||||
break
|
||||
elif i == obj.firstSon.sym.position:
|
||||
branch = getOrdValue(constOrNil[i])
|
||||
branch = getOrdValue(it)
|
||||
break
|
||||
|
||||
let selectedBranch = caseObjDefaultBranch(obj, branch)
|
||||
@@ -4050,14 +4048,14 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
|
||||
result.addField(init, name = sname):
|
||||
block fieldInit:
|
||||
if constOrNil != nil:
|
||||
for i in 1..<constOrNil.len:
|
||||
if constOrNil[i].kind == nkExprColonExpr:
|
||||
assert constOrNil[i].firstSon.kind == nkSym, "illformed object constr; the field is not a sym"
|
||||
if constOrNil[i].firstSon.sym.name.id == field.name.id:
|
||||
genBracedInit(p, constOrNil[i][1], isConst, field.typ, result)
|
||||
for i, it in isons(constOrNil, 1):
|
||||
if it.kind == nkExprColonExpr:
|
||||
assert it.firstSon.kind == nkSym, "illformed object constr; the field is not a sym"
|
||||
if it.firstSon.sym.name.id == field.name.id:
|
||||
genBracedInit(p, it[1], isConst, field.typ, result)
|
||||
break fieldInit
|
||||
elif i == field.position:
|
||||
genBracedInit(p, constOrNil[i], isConst, field.typ, result)
|
||||
genBracedInit(p, it, isConst, field.typ, result)
|
||||
break fieldInit
|
||||
# not found, produce default value:
|
||||
getDefaultValue(p, field.typ, info, result)
|
||||
|
||||
@@ -19,8 +19,8 @@ proc specializeResetN(p: BProc, accessor: Rope, n: PNode;
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
for i in 0..<n.len:
|
||||
specializeResetN(p, accessor, n[i], typ)
|
||||
for it in sons(n):
|
||||
specializeResetN(p, accessor, it, typ)
|
||||
of nkRecCase:
|
||||
if (n[0].kind != nkSym): internalError(p.config, n.info, "specializeResetN")
|
||||
let disc = n[0].sym
|
||||
@@ -29,8 +29,7 @@ proc specializeResetN(p: BProc, accessor: Rope, n: PNode;
|
||||
internalError(p.config, n.info, "specializeResetN()")
|
||||
let discField = dotField(accessor, disc.loc.snippet)
|
||||
p.s(cpsStmts).addSwitchStmt(discField):
|
||||
for i in 1..<n.len:
|
||||
let branch = n[i]
|
||||
for branch in sonsFrom(n, 1):
|
||||
assert branch.kind in {nkOfBranch, nkElse}
|
||||
var caseBuilder: SwitchCaseBuilder
|
||||
p.s(cpsStmts).addSwitchCase(caseBuilder):
|
||||
|
||||
@@ -329,18 +329,18 @@ proc genCppParamsForCtor(p: BProc; call: PNode; didGenTemp: var bool): Snippet =
|
||||
var argBuilder = default(CallBuilder) # not init, only building params
|
||||
let typ = skipTypes(call.firstSon.typ, abstractInst)
|
||||
assert(typ.kind == tyProc)
|
||||
for i in 1..<call.len:
|
||||
for i, child in isons(call, 1):
|
||||
#if it's a type we can just generate here another initializer as we are in an initializer context
|
||||
if call[i].kind == nkCall and call[i].firstSon.kind == nkSym and call[i].firstSon.sym.kind == skType:
|
||||
if child.kind == nkCall and child.firstSon.kind == nkSym and child.firstSon.sym.kind == skType:
|
||||
res.addArgument(argBuilder):
|
||||
res.add genCppInitializer(p.module, p, call[i].firstSon.sym.typ, didGenTemp)
|
||||
res.add genCppInitializer(p.module, p, child.firstSon.sym.typ, didGenTemp)
|
||||
else:
|
||||
#We need to test for temp in globals, see: #23657
|
||||
let param =
|
||||
if typ[i].kind in {tyVar} and call[i].kind == nkHiddenAddr:
|
||||
call[i].firstSon
|
||||
if typ[i].kind in {tyVar} and child.kind == nkHiddenAddr:
|
||||
child.firstSon
|
||||
else:
|
||||
call[i]
|
||||
child
|
||||
if not param.typ.isCompileTimeOnly and (param.kind != nkBracketExpr or param.typ.kind in
|
||||
{tyRef, tyPtr, tyUncheckedArray, tyArray, tyOpenArray,
|
||||
tyVarargs, tySequence, tyString, tyCstring, tyTuple}):
|
||||
@@ -574,10 +574,10 @@ proc genReturnStmt(p: BProc, t: PNode) =
|
||||
p.s(cpsStmts).addGoto("BeforeRet_")
|
||||
|
||||
proc genGotoForCase(p: BProc; caseStmt: PNode) =
|
||||
for i in 1..<caseStmt.len:
|
||||
for child in sonsFrom(caseStmt, 1):
|
||||
var scope: ScopeBuilder
|
||||
startSimpleBlock(p, scope)
|
||||
let it = caseStmt[i]
|
||||
let it = child
|
||||
for j in 0..<it.len-1:
|
||||
if it[j].kind == nkRange:
|
||||
localError(p.config, it.info, "range notation not available for computed goto")
|
||||
@@ -646,10 +646,10 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
||||
# first goto:
|
||||
p.s(cpsStmts).addComputedGoto(subscript(tmp, ra))
|
||||
|
||||
for i in 1..<caseStmt.len:
|
||||
for child in sonsFrom(caseStmt, 1):
|
||||
var scope: ScopeBuilder
|
||||
startSimpleBlock(p, scope)
|
||||
let it = caseStmt[i]
|
||||
let it = child
|
||||
for j in 0..<it.len-1:
|
||||
if it[j].kind == nkRange:
|
||||
localError(p.config, it.info, "range notation not available for computed goto")
|
||||
@@ -992,18 +992,18 @@ proc genCaseStringBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel,
|
||||
proc genStringCase(p: BProc, t: PNode, stringKind: TTypeKind, d: var TLoc) =
|
||||
# count how many constant strings there are in the case:
|
||||
var strings = 0
|
||||
for i in 1..<t.len:
|
||||
if t[i].kind == nkOfBranch: inc(strings, t[i].len - 1)
|
||||
for it in sonsFrom(t, 1):
|
||||
if it.kind == nkOfBranch: inc(strings, it.len - 1)
|
||||
if strings > stringCaseThreshold:
|
||||
var bitMask = math.nextPowerOfTwo(strings) - 1
|
||||
var branches: seq[Builder]
|
||||
newSeq(branches, bitMask + 1)
|
||||
var a: TLoc = initLocExpr(p, t.firstSon) # first pass: generate ifs+goto:
|
||||
var labId = p.labels
|
||||
for i in 1..<t.len:
|
||||
for it in sonsFrom(t, 1):
|
||||
inc(p.labels)
|
||||
if t[i].kind == nkOfBranch:
|
||||
genCaseStringBranch(p, t[i], a, "LA" & rope(p.labels) & "_",
|
||||
if it.kind == nkOfBranch:
|
||||
genCaseStringBranch(p, it, a, "LA" & rope(p.labels) & "_",
|
||||
stringKind, branches)
|
||||
else:
|
||||
# else statement: nothing to do yet
|
||||
@@ -1048,8 +1048,7 @@ proc branchHasTooBigRange(b: PNode): bool =
|
||||
|
||||
proc ifSwitchSplitPoint(p: BProc, n: PNode): int =
|
||||
result = 0
|
||||
for i in 1..<n.len:
|
||||
var branch = n[i]
|
||||
for i, branch in isons(n, 1):
|
||||
var stmtBlock = lastSon(branch)
|
||||
if stmtBlock.stmtsContainPragma(wLinearScanEnd):
|
||||
result = i
|
||||
@@ -1300,39 +1299,39 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
var catchAllPresent = false
|
||||
incl p.flags, noSafePoints # mark as not needing 'popCurrentException'
|
||||
if hasImportedCppExceptions:
|
||||
for i in 1..<t.len:
|
||||
if t[i].kind != nkExceptBranch: break
|
||||
for it in sonsFrom(t, 1):
|
||||
if it.kind != nkExceptBranch: break
|
||||
|
||||
# bug #4230: avoid false sharing between branches:
|
||||
if d.k == locTemp and isEmptyType(t.typ): d.k = locNone
|
||||
|
||||
if t[i].len == 1:
|
||||
if it.len == 1:
|
||||
# general except section:
|
||||
startBlockWith(p):
|
||||
p.s(cpsStmts).add("catch (...) {\n")
|
||||
genExceptBranchBody(t[i].firstSon)
|
||||
genExceptBranchBody(it.firstSon)
|
||||
endBlockWith(p):
|
||||
p.s(cpsStmts).add("}\n")
|
||||
catchAllPresent = true
|
||||
else:
|
||||
for j in 0..<t[i].len-1:
|
||||
var typeNode = t[i][j]
|
||||
if t[i][j].isInfixAs():
|
||||
typeNode = t[i][j][1]
|
||||
for j in 0..<it.len-1:
|
||||
var typeNode = it[j]
|
||||
if it[j].isInfixAs():
|
||||
typeNode = it[j][1]
|
||||
if isImportedException(typeNode.typ, p.config):
|
||||
let exvar = t[i][j][2] # ex1 in `except ExceptType as ex1:`
|
||||
let exvar = it[j][2] # ex1 in `except ExceptType as ex1:`
|
||||
fillLocalName(p, exvar.sym)
|
||||
backendEnsureMutable exvar.sym
|
||||
fillLoc(exvar.sym.locImpl, locTemp, exvar, OnStack)
|
||||
startBlockWith(p):
|
||||
lineCg(p, cpsStmts, "catch ($1& $2) {$n", [getTypeDesc(p.module, typeNode.typ), rdLoc(exvar.sym.loc)])
|
||||
genExceptBranchBody(t[i][^1]) # exception handler body will duplicated for every type
|
||||
genExceptBranchBody(it[^1]) # exception handler body will duplicated for every type
|
||||
endBlockWith(p):
|
||||
p.s(cpsStmts).add("}\n")
|
||||
elif isImportedException(typeNode.typ, p.config):
|
||||
startBlockWith(p):
|
||||
lineCg(p, cpsStmts, "catch ($1&) {$n", [getTypeDesc(p.module, t[i][j].typ)])
|
||||
genExceptBranchBody(t[i][^1]) # exception handler body will duplicated for every type
|
||||
lineCg(p, cpsStmts, "catch ($1&) {$n", [getTypeDesc(p.module, it[j].typ)])
|
||||
genExceptBranchBody(it[^1]) # exception handler body will duplicated for every type
|
||||
endBlockWith(p):
|
||||
p.s(cpsStmts).add("}\n")
|
||||
|
||||
@@ -1360,8 +1359,8 @@ proc bodyCanRaise(p: BProc; n: PNode): bool =
|
||||
result = canRaiseDisp(p, n.firstSon)
|
||||
if not result:
|
||||
# also check the arguments:
|
||||
for i in 1 ..< n.len:
|
||||
if bodyCanRaise(p, n[i]): return true
|
||||
for it in sonsFrom(n, 1):
|
||||
if bodyCanRaise(p, it): return true
|
||||
of nkRaiseStmt:
|
||||
result = true
|
||||
of nkTypeSection, nkProcDef, nkConverterDef, nkMethodDef, nkIteratorDef,
|
||||
@@ -1710,8 +1709,7 @@ proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false; result: var Rope) =
|
||||
if isAsmStmt: 1 # first son is pragmas
|
||||
else: 0
|
||||
|
||||
for i in offset..<t.len:
|
||||
let it = t[i]
|
||||
for it in sonsFrom(t, offset):
|
||||
case it.kind
|
||||
of nkStrLit..nkTripleStrLit:
|
||||
res.add(it.strVal)
|
||||
|
||||
@@ -31,8 +31,8 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, n: PNode;
|
||||
if n == nil: return
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
for i in 0..<n.len:
|
||||
genTraverseProc(c, accessor, n[i], typ)
|
||||
for it in sons(n):
|
||||
genTraverseProc(c, accessor, it, typ)
|
||||
of nkRecCase:
|
||||
if (n[0].kind != nkSym): internalError(c.p.config, n.info, "genTraverseProc")
|
||||
var p = c.p
|
||||
@@ -42,8 +42,7 @@ proc genTraverseProc(c: TTraversalClosure, accessor: Rope, n: PNode;
|
||||
internalError(c.p.config, n.info, "genTraverseProc()")
|
||||
let discField = dotField(accessor, disc.loc.snippet)
|
||||
p.s(cpsStmts).addSwitchStmt(discField):
|
||||
for i in 1..<n.len:
|
||||
let branch = n[i]
|
||||
for branch in sonsFrom(n, 1):
|
||||
assert branch.kind in {nkOfBranch, nkElse}
|
||||
var caseBuilder: SwitchCaseBuilder
|
||||
p.s(cpsStmts).addSwitchCase(caseBuilder):
|
||||
|
||||
@@ -611,9 +611,9 @@ proc genMemberProcParams(m: BModule; prc: PSym, superCall, rettype, name, params
|
||||
types.add getTypeDescWeak(m, this.typ, check, dkParam)
|
||||
|
||||
let firstParam = if isCtor: 1 else: 2
|
||||
for i in firstParam..<t.n.len:
|
||||
if t.n[i].kind != nkSym: internalError(m.config, t.n.info, "genMemberProcParams")
|
||||
var param = t.n[i].sym
|
||||
for it in sonsFrom(t.n, firstParam):
|
||||
if it.kind != nkSym: internalError(m.config, t.n.info, "genMemberProcParams")
|
||||
var param = it.sym
|
||||
var descKind = dkParam
|
||||
if optByRef in param.options:
|
||||
if param.typ.kind == tyGenericInst:
|
||||
@@ -623,7 +623,7 @@ proc genMemberProcParams(m: BModule; prc: PSym, superCall, rettype, name, params
|
||||
var typ, name: string
|
||||
backendEnsureMutable param
|
||||
fillParamName(m, param)
|
||||
fillLoc(param.locImpl, locParam, t.n[i],
|
||||
fillLoc(param.locImpl, locParam, it,
|
||||
param.paramStorageLoc)
|
||||
if ccgIntroducedPtr(m.config, param, t.returnType) and descKind == dkParam:
|
||||
typ = getTypeDescWeak(m, param.typ, check, descKind) & "*"
|
||||
@@ -668,9 +668,9 @@ proc genProcParams(m: BModule; t: PType, rettype: var Rope, params: var Builder,
|
||||
rettype = getTypeDescWeak(m, t.returnType, check, dkResult)
|
||||
var paramBuilder: ProcParamBuilder
|
||||
params.addProcParams(paramBuilder):
|
||||
for i in 1..<t.n.len:
|
||||
if t.n[i].kind != nkSym: internalError(m.config, t.n.info, "genProcParams")
|
||||
var param = t.n[i].sym
|
||||
for child in sonsFrom(t.n, 1):
|
||||
if child.kind != nkSym: internalError(m.config, t.n.info, "genProcParams")
|
||||
var param = child.sym
|
||||
# The hidden closure environment param (`:envP`) is not a real C parameter:
|
||||
# the environment is passed via the trailing `ClE_0` (added below) and
|
||||
# `closureSetup` materialises `:envP` as a local cast of it. In a from-source
|
||||
@@ -692,7 +692,7 @@ proc genProcParams(m: BModule; t: PType, rettype: var Rope, params: var Builder,
|
||||
if isCompileTimeOnly(param.typ): continue
|
||||
backendEnsureMutable param
|
||||
fillParamName(m, param)
|
||||
fillLoc(param.locImpl, locParam, t.n[i],
|
||||
fillLoc(param.locImpl, locParam, child,
|
||||
param.paramStorageLoc)
|
||||
if isClosureEnv: continue # name/loc filled, but not part of the C signature
|
||||
var typ: Rope
|
||||
@@ -775,10 +775,10 @@ proc genRecordFieldsAux(m: BModule; n: PNode,
|
||||
# prefix mangled name with "_U" to avoid clashes with other field names,
|
||||
# since identifiers are not allowed to start with '_'
|
||||
var unionBody = newBuilder("")
|
||||
for i in 1..<n.len:
|
||||
case n[i].kind
|
||||
for i, it in isons(n, 1):
|
||||
case it.kind
|
||||
of nkOfBranch, nkElse:
|
||||
let k = lastSon(n[i])
|
||||
let k = lastSon(it)
|
||||
if k.kind != nkSym:
|
||||
let structName = "_" & mangleRecFieldName(m, n.firstSon.sym) & "_" & $i
|
||||
var a = newBuilder("")
|
||||
@@ -1552,8 +1552,7 @@ proc genObjectFields(m: BModule; typ, origType: PType, n: PNode, expr: Rope;
|
||||
else:
|
||||
m.s[cfsData].addArrayVar(kind = Local, name = tmp,
|
||||
elementType = ptrType("TNimNode"), len = toInt(L)+1)
|
||||
for i in 1..<n.len:
|
||||
var b = n[i] # branch
|
||||
for b in sonsFrom(n, 1):
|
||||
var tmp2 = getNimNode(m)
|
||||
genObjectFields(m, typ, origType, lastSon(b), tmp2, info)
|
||||
case b.kind
|
||||
|
||||
@@ -22,13 +22,13 @@ proc getPragmaStmt*(n: PNode, w: TSpecialWord): PNode =
|
||||
case n.kind
|
||||
of nkStmtList:
|
||||
result = nil
|
||||
for i in 0..<n.len:
|
||||
result = getPragmaStmt(n[i], w)
|
||||
for it in sons(n):
|
||||
result = getPragmaStmt(it, w)
|
||||
if result != nil: break
|
||||
of nkPragma:
|
||||
result = nil
|
||||
for i in 0..<n.len:
|
||||
if whichPragma(n[i]) == w: return n[i]
|
||||
for it in sons(n):
|
||||
if whichPragma(it) == w: return it
|
||||
else:
|
||||
result = nil
|
||||
|
||||
|
||||
@@ -1194,8 +1194,11 @@ proc symInDynamicLib(m: BModule, sym: PSym) =
|
||||
var a: TLoc = initLocExpr(m.initProc, n.firstSon)
|
||||
let callee = rdLoc(a)
|
||||
var params: seq[Snippet] = @[]
|
||||
for i in 1..<n.len-1:
|
||||
a = initLocExpr(m.initProc, n[i])
|
||||
var remaining = n.len - 2 # children 1 ..< len-1
|
||||
for it in sonsFrom(n, 1):
|
||||
if remaining <= 0: break
|
||||
dec remaining
|
||||
a = initLocExpr(m.initProc, it)
|
||||
params.add(rdLoc(a))
|
||||
params.add(makeCString($extname))
|
||||
template load(builder: var Builder) =
|
||||
@@ -1444,8 +1447,7 @@ proc allPathsAsgnResult(p: BProc; n: PNode): InitResultEnum =
|
||||
result = InitSkippable
|
||||
var exhaustive = skipTypes(n.firstSon.typ,
|
||||
abstractVarRange-{tyTypeDesc}).kind notin {tyFloat..tyFloat128, tyString, tyCstring}
|
||||
for i in 1..<n.len:
|
||||
let it = n[i]
|
||||
for it in sonsFrom(n, 1):
|
||||
allPathsInBranch(it.lastSon)
|
||||
if it.kind == nkElse: exhaustive = true
|
||||
if not exhaustive: result = Unknown
|
||||
@@ -1477,11 +1479,11 @@ proc allPathsAsgnResult(p: BProc; n: PNode): InitResultEnum =
|
||||
# is 'finally: result = x'
|
||||
result = InitSkippable
|
||||
allPathsInBranch(n.firstSon)
|
||||
for i in 1..<n.len:
|
||||
if n[i].kind == nkFinally:
|
||||
result = allPathsAsgnResult(p, n[i].lastSon)
|
||||
for it in sonsFrom(n, 1):
|
||||
if it.kind == nkFinally:
|
||||
result = allPathsAsgnResult(p, it.lastSon)
|
||||
else:
|
||||
allPathsInBranch(n[i].lastSon)
|
||||
allPathsInBranch(it.lastSon)
|
||||
of nkCallKinds:
|
||||
if canRaiseDisp(p, n.firstSon) or
|
||||
(n.firstSon.kind == nkSym and sfNoReturn in n.firstSon.sym.flags):
|
||||
@@ -1635,8 +1637,8 @@ proc genProcLvl3*(m: BModule, prc: PSym) =
|
||||
backendEnsureMutable res
|
||||
res.locImpl.storage = OnUnknown
|
||||
|
||||
for i in 1..<prc.typ.n.len:
|
||||
let param = prc.typ.n[i].sym
|
||||
for paramNode in sonsFrom(prc.typ.n, 1):
|
||||
let param = paramNode.sym
|
||||
if param.typ.isCompileTimeOnly: continue
|
||||
if prc.typ.callConv == ccClosure and param.name.s == ":envP":
|
||||
# The hidden closure-env param is materialised by `closureSetup`, never a
|
||||
|
||||
Reference in New Issue
Block a user