mirror of
https://github.com/nim-lang/Nim.git
synced 2026-08-14 02:54:59 +00:00
backend: refactorings so that eventually it can run on BIF directly w… (#25959)
…ithout PNode constructions; also added bif2nif.nim inspection tool
This commit is contained in:
@@ -946,6 +946,16 @@ template `[]=`*(n: PNode, i: BackwardsIndex; x: PNode) = n[n.len - i.int] = x
|
||||
iterator items*(n: PNode): PNode =
|
||||
for i in 0..<n.safeLen: yield n[i]
|
||||
|
||||
iterator sons*(n: PNode): PNode =
|
||||
## Iterates over the children of `n`. Preferred over `for i in 0..<n.len: n[i]`
|
||||
## 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])
|
||||
|
||||
when defined(useNodeIds):
|
||||
const nodeIdToDebug* = -1 # 2322968
|
||||
var gNodeId: int
|
||||
|
||||
@@ -40,7 +40,7 @@ proc preventNrvo(p: BProc; dest, le, ri: PNode): bool =
|
||||
return false
|
||||
of nkDotExpr, nkBracketExpr, nkObjUpConv, nkObjDownConv,
|
||||
nkCheckedFieldExpr:
|
||||
n = n[0]
|
||||
n = n.firstSon
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
n = n[1]
|
||||
else:
|
||||
@@ -54,7 +54,7 @@ proc preventNrvo(p: BProc; dest, le, ri: PNode): bool =
|
||||
if isPartOf(le, r, {pfStructural}) != arNo: return true
|
||||
# we use the weaker 'canRaise' here in order to prevent too many
|
||||
# annoying warnings, see #14514
|
||||
if canRaise(ri[0]) and
|
||||
if canRaise(ri.firstSon) and
|
||||
locationEscapes(p, le, p.nestedTryStmts.len > 0):
|
||||
message(p.config, le.info, warnObservableStores, $le)
|
||||
# bug #19613 prevent dangerous aliasing too:
|
||||
@@ -64,7 +64,7 @@ proc preventNrvo(p: BProc; dest, le, ri: PNode): bool =
|
||||
if isPartOf(dest, r, {pfStructural}) != arNo: return true
|
||||
|
||||
proc hasNoInit(call: PNode): bool {.inline.} =
|
||||
result = call[0].kind == nkSym and sfNoInit in call[0].sym.flags
|
||||
result = call.firstSon.kind == nkSym and sfNoInit in call.firstSon.sym.flags
|
||||
|
||||
proc isHarmlessStore(p: BProc; canRaise: bool; d: TLoc): bool =
|
||||
if d.k in {locTemp, locNone} or not canRaise:
|
||||
@@ -97,10 +97,10 @@ proc cleanupTemp(p: BProc; returnType: PType, tmp: TLoc): bool =
|
||||
|
||||
proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc,
|
||||
result: var Builder, call: var CallBuilder) =
|
||||
let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri[0])
|
||||
let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri.firstSon)
|
||||
genLineDir(p, ri)
|
||||
# getUniqueType() is too expensive here:
|
||||
var typ = skipTypes(ri[0].typ, abstractInst)
|
||||
var typ = skipTypes(ri.firstSon.typ, abstractInst)
|
||||
if typ.returnType != nil:
|
||||
var flags: TAssignmentFlags = {}
|
||||
if typ.returnType.kind in {tyOpenArray, tyVarargs}:
|
||||
@@ -184,7 +184,7 @@ proc reifiedOpenArray(n: PNode): bool {.inline.} =
|
||||
while true:
|
||||
case x.kind
|
||||
of {nkAddr, nkHiddenAddr, nkHiddenDeref}:
|
||||
x = x[0]
|
||||
x = x.firstSon
|
||||
of nkHiddenStdConv:
|
||||
x = x[1]
|
||||
else:
|
||||
@@ -368,7 +368,7 @@ proc expressionsNeedsTmp(p: BProc, a: TLoc): TLoc =
|
||||
genAssignment(p, result, a, {})
|
||||
|
||||
proc genArgStringToCString(p: BProc, n: PNode; result: var Builder; needsTmp: bool) {.inline.} =
|
||||
var a = initLocExpr(p, n[0])
|
||||
var a = initLocExpr(p, n.firstSon)
|
||||
let tmp = withTmpIfNeeded(p, a, needsTmp)
|
||||
let ra = if p.config.usesSso(): byRefLoc(p, tmp) else: tmp.rdLoc
|
||||
result.addCall(cgsymValue(p.module, "nimToCStringConv"), ra)
|
||||
@@ -378,9 +378,9 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode; result: var Builder; n
|
||||
if n.kind == nkStringToCString:
|
||||
genArgStringToCString(p, n, result, needsTmp)
|
||||
elif skipTypes(param.typ, abstractVar).kind in {tyOpenArray, tyVarargs}:
|
||||
var n = if n.kind != nkHiddenAddr: n else: n[0]
|
||||
var n = if n.kind != nkHiddenAddr: n else: n.firstSon
|
||||
openArrayLoc(p, param.typ, n, result)
|
||||
elif ccgIntroducedPtr(p.config, param, call[0].typ.returnType) and
|
||||
elif ccgIntroducedPtr(p.config, param, call.firstSon.typ.returnType) and
|
||||
(optByRef notin param.options or not p.module.compileToCpp):
|
||||
a = initLocExpr(p, n)
|
||||
if n.kind in {nkCharLit..nkNilLit}:
|
||||
@@ -392,7 +392,7 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode; result: var Builder; n
|
||||
# bug #23748: we need to introduce a temporary here. The expression type
|
||||
# will be a reference in C++ and we cannot create a temporary reference
|
||||
# variable. Thus, we create a temporary pointer variable instead.
|
||||
let needsIndirect = mapType(p.config, n[0].typ, mapTypeChooser(n[0]) == skParam) != ctArray
|
||||
let needsIndirect = mapType(p.config, n.firstSon.typ, mapTypeChooser(n.firstSon) == skParam) != ctArray
|
||||
if needsIndirect:
|
||||
n.typ = n.typ.exactReplica(p.module.idgen)
|
||||
n.typ.incl tfVarIsPtr
|
||||
@@ -401,7 +401,7 @@ proc genArg(p: BProc, n: PNode, param: PSym; call: PNode; result: var Builder; n
|
||||
if needsIndirect: a.flags.incl lfIndirect
|
||||
# if the proc is 'importc'ed but not 'importcpp'ed then 'var T' still
|
||||
# means '*T'. See posix.nim for lots of examples that do that in the wild.
|
||||
let callee = call[0]
|
||||
let callee = call.firstSon
|
||||
if callee.kind == nkSym and
|
||||
{sfImportc, sfInfixCall, sfCompilerProc} * callee.sym.flags == {sfImportc} and
|
||||
{lfHeader, lfNoDecl} * callee.sym.loc.flags != {} and
|
||||
@@ -439,7 +439,7 @@ proc skipTrivialIndirections(n: PNode): PNode =
|
||||
while true:
|
||||
case result.kind
|
||||
of nkDerefExpr, nkHiddenDeref, nkAddr, nkHiddenAddr, nkObjDownConv, nkObjUpConv:
|
||||
result = result[0]
|
||||
result = result.firstSon
|
||||
of nkHiddenStdConv, nkHiddenSubConv:
|
||||
result = result[1]
|
||||
else: break
|
||||
@@ -498,14 +498,14 @@ proc addActualSuffixForHCR(res: var Rope, module: PSym, sym: PSym) =
|
||||
|
||||
proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
# this is a hotspot in the compiler
|
||||
var op = initLocExpr(p, ri[0])
|
||||
var op = initLocExpr(p, ri.firstSon)
|
||||
# getUniqueType() is too expensive here:
|
||||
var typ = skipTypes(ri[0].typ, abstractInstOwned)
|
||||
var typ = skipTypes(ri.firstSon.typ, abstractInstOwned)
|
||||
assert(typ.kind == tyProc)
|
||||
|
||||
var callee = rdLoc(op)
|
||||
if p.hcrOn and ri[0].kind == nkSym:
|
||||
callee.addActualSuffixForHCR(p.module.module, ri[0].sym)
|
||||
if p.hcrOn and ri.firstSon.kind == nkSym:
|
||||
callee.addActualSuffixForHCR(p.module.module, ri.firstSon.sym)
|
||||
|
||||
var res = newBuilder("")
|
||||
var call = initCallBuilder(res, callee)
|
||||
@@ -537,10 +537,10 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
else:
|
||||
cCall(p, params, e)
|
||||
|
||||
var op = initLocExpr(p, ri[0])
|
||||
var op = initLocExpr(p, ri.firstSon)
|
||||
|
||||
# getUniqueType() is too expensive here:
|
||||
var typ = skipTypes(ri[0].typ, abstractInstOwned)
|
||||
var typ = skipTypes(ri.firstSon.typ, abstractInstOwned)
|
||||
assert(typ.kind == tyProc)
|
||||
|
||||
var params = newBuilder("")
|
||||
@@ -557,7 +557,7 @@ proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
p.s(cpsStmts).add(callProc(rp, pars, rawProc))
|
||||
|
||||
let rawProc = getClosureType(p.module, typ, clHalf)
|
||||
let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri[0])
|
||||
let canRaise = p.config.exc == excGoto and canRaiseDisp(p, ri.firstSon)
|
||||
if typ.returnType != nil:
|
||||
if isInvalidReturnType(p.config, typ):
|
||||
# beware of 'result = p(result)'. We may need to allocate a temporary:
|
||||
@@ -619,7 +619,7 @@ proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType; result: var Builder;
|
||||
discard
|
||||
elif paramType.typ.kind in {tyVar} and ri[i].kind == nkHiddenAddr:
|
||||
result.addArgument(argBuilder):
|
||||
genArgNoParam(p, ri[i][0], result)
|
||||
genArgNoParam(p, ri[i].firstSon, result)
|
||||
else:
|
||||
result.addArgument(argBuilder):
|
||||
genArgNoParam(p, ri[i], result) #, typ.n[i].sym)
|
||||
@@ -672,16 +672,16 @@ proc skipAddrDeref(node: PNode): PNode =
|
||||
var isAddr = false
|
||||
case n.kind
|
||||
of nkAddr, nkHiddenAddr:
|
||||
n = n[0]
|
||||
n = n.firstSon
|
||||
isAddr = true
|
||||
of nkDerefExpr, nkHiddenDeref:
|
||||
n = n[0]
|
||||
n = n.firstSon
|
||||
else: return n
|
||||
if n.kind == nkObjDownConv: n = n[0]
|
||||
if n.kind == nkObjDownConv: n = n.firstSon
|
||||
if isAddr and n.kind in {nkDerefExpr, nkHiddenDeref}:
|
||||
result = n[0]
|
||||
result = n.firstSon
|
||||
elif n.kind in {nkAddr, nkHiddenAddr}:
|
||||
result = n[0]
|
||||
result = n.firstSon
|
||||
else:
|
||||
result = node
|
||||
|
||||
@@ -694,29 +694,29 @@ proc genThisArg(p: BProc; ri: PNode; i: int; typ: PType; result: var Builder) =
|
||||
# if the parameter is lying (tyVar) and thus we required an additional deref,
|
||||
# skip the deref:
|
||||
var ri = ri[i]
|
||||
while ri.kind == nkObjDownConv: ri = ri[0]
|
||||
while ri.kind == nkObjDownConv: ri = ri.firstSon
|
||||
let t = typ[i].skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
if t.kind in {tyVar}:
|
||||
let x = if ri.kind == nkHiddenAddr: ri[0] else: ri
|
||||
let x = if ri.kind == nkHiddenAddr: ri.firstSon else: ri
|
||||
if x.typ.kind == tyPtr:
|
||||
genArgNoParam(p, x, result)
|
||||
result.add("->")
|
||||
elif x.kind in {nkHiddenDeref, nkDerefExpr} and x[0].typ.kind == tyPtr:
|
||||
genArgNoParam(p, x[0], result)
|
||||
elif x.kind in {nkHiddenDeref, nkDerefExpr} and x.firstSon.typ.kind == tyPtr:
|
||||
genArgNoParam(p, x.firstSon, result)
|
||||
result.add("->")
|
||||
else:
|
||||
genArgNoParam(p, x, result)
|
||||
result.add(".")
|
||||
elif t.kind == tyPtr:
|
||||
if ri.kind in {nkAddr, nkHiddenAddr}:
|
||||
genArgNoParam(p, ri[0], result)
|
||||
genArgNoParam(p, ri.firstSon, result)
|
||||
result.add(".")
|
||||
else:
|
||||
genArgNoParam(p, ri, result)
|
||||
result.add("->")
|
||||
else:
|
||||
ri = skipAddrDeref(ri)
|
||||
if ri.kind in {nkAddr, nkHiddenAddr}: ri = ri[0]
|
||||
if ri.kind in {nkAddr, nkHiddenAddr}: ri = ri.firstSon
|
||||
genArgNoParam(p, ri, result) #, typ.n[i].sym)
|
||||
result.add(".")
|
||||
|
||||
@@ -734,8 +734,8 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType; result: var Bu
|
||||
if i+1 < pat.len and pat[i+1] in {'+', '@'}:
|
||||
let ri = ri[j]
|
||||
if ri.kind in nkCallKinds:
|
||||
let typ = skipTypes(ri[0].typ, abstractInst)
|
||||
if pat[i+1] == '+': genArgNoParam(p, ri[0], result)
|
||||
let typ = skipTypes(ri.firstSon.typ, abstractInst)
|
||||
if pat[i+1] == '+': genArgNoParam(p, ri.firstSon, result)
|
||||
result.add("(")
|
||||
if 1 < ri.len:
|
||||
var callBuilder: CallBuilder = default(CallBuilder)
|
||||
@@ -752,7 +752,7 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType; result: var Bu
|
||||
inc i
|
||||
elif i+1 < pat.len and pat[i+1] == '[':
|
||||
var arg = ri[j].skipAddrDeref
|
||||
while arg.kind in {nkAddr, nkHiddenAddr, nkObjDownConv}: arg = arg[0]
|
||||
while arg.kind in {nkAddr, nkHiddenAddr, nkObjDownConv}: arg = arg.firstSon
|
||||
genArgNoParam(p, arg, result)
|
||||
#result.add debugTree(arg, 0, 10)
|
||||
else:
|
||||
@@ -775,18 +775,18 @@ proc genPatternCall(p: BProc; ri: PNode; pat: string; typ: PType; result: var Bu
|
||||
result.add(substr(pat, start, i - 1))
|
||||
|
||||
proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
var op = initLocExpr(p, ri[0])
|
||||
var op = initLocExpr(p, ri.firstSon)
|
||||
# getUniqueType() is too expensive here:
|
||||
var typ = skipTypes(ri[0].typ, abstractInst)
|
||||
var typ = skipTypes(ri.firstSon.typ, abstractInst)
|
||||
assert(typ.kind == tyProc)
|
||||
# don't call '$' here for efficiency:
|
||||
let pat = $ri[0].sym.loc.snippet
|
||||
let pat = $ri.firstSon.sym.loc.snippet
|
||||
internalAssert p.config, pat.len > 0
|
||||
if pat.contains({'#', '(', '@', '\''}):
|
||||
var pl = newBuilder("")
|
||||
genPatternCall(p, ri, pat, typ, pl)
|
||||
# simpler version of 'fixupCall' that works with the pl+params combination:
|
||||
var typ = skipTypes(ri[0].typ, abstractInst)
|
||||
var typ = skipTypes(ri.firstSon.typ, abstractInst)
|
||||
if typ.returnType != nil:
|
||||
if p.module.compileToCpp and lfSingleUse in d.flags:
|
||||
# do not generate spurious temporaries for C++! For C we're better off
|
||||
@@ -817,14 +817,14 @@ proc genInfixCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
|
||||
proc genNamedParamCall(p: BProc, ri: PNode, d: var TLoc) =
|
||||
# generates a crappy ObjC call
|
||||
var op = initLocExpr(p, ri[0])
|
||||
var op = initLocExpr(p, ri.firstSon)
|
||||
var pl = newBuilder("[")
|
||||
# getUniqueType() is too expensive here:
|
||||
var typ = skipTypes(ri[0].typ, abstractInst)
|
||||
var typ = skipTypes(ri.firstSon.typ, abstractInst)
|
||||
assert(typ.kind == tyProc)
|
||||
|
||||
# don't call '$' here for efficiency:
|
||||
let pat = $ri[0].sym.loc.snippet
|
||||
let pat = $ri.firstSon.sym.loc.snippet
|
||||
internalAssert p.config, pat.len > 0
|
||||
var start = 3
|
||||
if ' ' in pat:
|
||||
@@ -903,27 +903,27 @@ proc isInactiveDestructorCall(p: BProc, e: PNode): bool =
|
||||
We want to return early but the 'finally' section is traversed before
|
||||
the 'let args = ...' statement. We exploit this to generate better
|
||||
code for 'return'. ]#
|
||||
result = e.len == 2 and e[0].kind == nkSym and
|
||||
e[0].sym.name.s == "=destroy" and notYetAlive(e[1].skipAddr)
|
||||
result = e.len == 2 and e.firstSon.kind == nkSym and
|
||||
e.firstSon.sym.name.s == "=destroy" and notYetAlive(e[1].skipAddr)
|
||||
|
||||
proc genAsgnCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||
if p.withinBlockLeaveActions > 0 and isInactiveDestructorCall(p, ri):
|
||||
return
|
||||
when defined(icDbgHash):
|
||||
if ri[0].typ == nil:
|
||||
echo "NILCALLEE kind=", ri[0].kind,
|
||||
" sym=", (if ri[0].kind == nkSym: ri[0].sym.name.s else: "-"),
|
||||
" symKind=", (if ri[0].kind == nkSym: $ri[0].sym.kind else: "-"),
|
||||
" flags=", (if ri[0].kind == nkSym: $ri[0].sym.flags else: "-"),
|
||||
" lazy=", nfLazyType in ri[0].flags,
|
||||
if ri.firstSon.typ == nil:
|
||||
echo "NILCALLEE kind=", ri.firstSon.kind,
|
||||
" sym=", (if ri.firstSon.kind == nkSym: ri.firstSon.sym.name.s else: "-"),
|
||||
" symKind=", (if ri.firstSon.kind == nkSym: $ri.firstSon.sym.kind else: "-"),
|
||||
" flags=", (if ri.firstSon.kind == nkSym: $ri.firstSon.sym.flags else: "-"),
|
||||
" lazy=", nfLazyType in ri.firstSon.flags,
|
||||
" inProc=", (if p.prc != nil: p.prc.name.s else: "NIL"),
|
||||
" module=", p.module.module.name.s
|
||||
raiseAssert "nil callee type, see NILCALLEE above"
|
||||
if ri[0].typ.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).callConv == ccClosure:
|
||||
if ri.firstSon.typ.skipTypes({tyGenericInst, tyAlias, tySink, tyOwned}).callConv == ccClosure:
|
||||
genClosureCall(p, le, ri, d)
|
||||
elif ri[0].kind == nkSym and sfInfixCall in ri[0].sym.flags:
|
||||
elif ri.firstSon.kind == nkSym and sfInfixCall in ri.firstSon.sym.flags:
|
||||
genInfixCall(p, le, ri, d)
|
||||
elif ri[0].kind == nkSym and sfNamedParamCall in ri[0].sym.flags:
|
||||
elif ri.firstSon.kind == nkSym and sfNamedParamCall in ri.firstSon.sym.flags:
|
||||
genNamedParamCall(p, ri, d)
|
||||
else:
|
||||
genPrefixCall(p, le, ri, d)
|
||||
|
||||
@@ -137,7 +137,7 @@ proc getStorageLoc(n: PNode): TStorageLoc =
|
||||
else: result = OnUnknown
|
||||
else: result = OnUnknown
|
||||
of nkDerefExpr, nkHiddenDeref:
|
||||
case n[0].typ.kind
|
||||
case n.firstSon.typ.kind
|
||||
of tyVar, tyLent: result = OnUnknown
|
||||
of tyPtr: result = OnStack
|
||||
of tyRef: result = OnHeap
|
||||
@@ -145,7 +145,7 @@ proc getStorageLoc(n: PNode): TStorageLoc =
|
||||
result = OnUnknown
|
||||
doAssert(false, "getStorageLoc")
|
||||
of nkBracketExpr, nkDotExpr, nkObjDownConv, nkObjUpConv:
|
||||
result = getStorageLoc(n[0])
|
||||
result = getStorageLoc(n.firstSon)
|
||||
else: result = OnUnknown
|
||||
|
||||
proc canMove(p: BProc, n: PNode; dest: TLoc): bool =
|
||||
@@ -904,27 +904,27 @@ proc isCppRef(p: BProc; typ: PType): bool {.inline.} =
|
||||
tfVarIsPtr notin skipTypes(typ, abstractInstOwned).flags
|
||||
|
||||
proc genDeref(p: BProc, e: PNode, d: var TLoc) =
|
||||
let mt = mapType(p.config, e[0].typ, mapTypeChooser(e[0]) == skParam)
|
||||
let mt = mapType(p.config, e.firstSon.typ, mapTypeChooser(e.firstSon) == skParam)
|
||||
if mt in {ctArray, ctPtrToArray} and lfEnforceDeref notin d.flags:
|
||||
# XXX the amount of hacks for C's arrays is incredible, maybe we should
|
||||
# simply wrap them in a struct? --> Losing auto vectorization then?
|
||||
expr(p, e[0], d)
|
||||
if e[0].typ.skipTypes(abstractInstOwned).kind == tyRef:
|
||||
expr(p, e.firstSon, d)
|
||||
if e.firstSon.typ.skipTypes(abstractInstOwned).kind == tyRef:
|
||||
d.storage = OnHeap
|
||||
else:
|
||||
var a: TLoc
|
||||
var typ = e[0].typ
|
||||
var typ = e.firstSon.typ
|
||||
if typ.kind in {tyUserTypeClass, tyUserTypeClassInst} and typ.isResolvedUserTypeClass:
|
||||
typ = typ.last
|
||||
typ = typ.skipTypes(abstractInstOwned)
|
||||
if typ.kind in {tyVar} and tfVarIsPtr notin typ.flags and
|
||||
p.module.compileToCpp and e[0].kind == nkHiddenAddr and
|
||||
p.module.compileToCpp and e.firstSon.kind == nkHiddenAddr and
|
||||
# don't override existing location:
|
||||
d.k == locNone:
|
||||
d = initLocExprSingleUse(p, e[0][0])
|
||||
d = initLocExprSingleUse(p, e.firstSon.firstSon)
|
||||
return
|
||||
else:
|
||||
a = initLocExprSingleUse(p, e[0])
|
||||
a = initLocExprSingleUse(p, e.firstSon)
|
||||
|
||||
# bug #23453 #25265
|
||||
if e.typ != nil and e.typ.skipTypes(abstractInst).kind == tyObject:
|
||||
@@ -964,14 +964,14 @@ proc genDeref(p: BProc, e: PNode, d: var TLoc) =
|
||||
proc cowBracket(p: BProc; n: PNode) =
|
||||
if n.kind == nkBracketExpr and optSeqDestructors in p.config.globalOptions and
|
||||
not p.config.usesSso():
|
||||
let strCandidate = n[0]
|
||||
let strCandidate = n.firstSon
|
||||
if strCandidate.typ.skipTypes(abstractInst).kind == tyString:
|
||||
var a: TLoc = initLocExpr(p, strCandidate)
|
||||
let raa = byRefLoc(p, a)
|
||||
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "nimPrepareStrMutationV2"), raa)
|
||||
|
||||
proc cow(p: BProc; n: PNode) {.inline.} =
|
||||
if n.kind == nkHiddenAddr: cowBracket(p, n[0])
|
||||
if n.kind == nkHiddenAddr: cowBracket(p, n.firstSon)
|
||||
|
||||
template ignoreConv(e: PNode): bool =
|
||||
let destType = e.typ.skipTypes({tyVar, tyLent, tyGenericInst, tyAlias, tySink})
|
||||
@@ -980,22 +980,22 @@ template ignoreConv(e: PNode): bool =
|
||||
|
||||
proc genAddr(p: BProc, e: PNode, d: var TLoc) =
|
||||
# careful 'addr(myptrToArray)' needs to get the ampersand:
|
||||
if e[0].typ.skipTypes(abstractInstOwned).kind in {tyRef, tyPtr}:
|
||||
var a: TLoc = initLocExpr(p, e[0])
|
||||
if e.firstSon.typ.skipTypes(abstractInstOwned).kind in {tyRef, tyPtr}:
|
||||
var a: TLoc = initLocExpr(p, e.firstSon)
|
||||
putIntoDest(p, d, e, cAddr(a.snippet), a.storage)
|
||||
#Message(e.info, warnUser, "HERE NEW &")
|
||||
elif mapType(p.config, e[0].typ, mapTypeChooser(e[0]) == skParam) == ctArray or isCppRef(p, e.typ):
|
||||
expr(p, e[0], d)
|
||||
elif mapType(p.config, e.firstSon.typ, mapTypeChooser(e.firstSon) == skParam) == ctArray or isCppRef(p, e.typ):
|
||||
expr(p, e.firstSon, d)
|
||||
# bug #19497
|
||||
d.lode = e
|
||||
else:
|
||||
let ssoStrSub = p.config.usesSso() and e[0].kind == nkBracketExpr and
|
||||
e[0][0].typ.skipTypes(abstractVar).kind == tyString
|
||||
var a: TLoc = initLocExpr(p, e[0], if ssoStrSub: {lfEnforceDeref, lfPrepareForMutation} else: {})
|
||||
if e[0].kind in {nkHiddenStdConv, nkHiddenSubConv, nkConv} and not ignoreConv(e[0]):
|
||||
let ssoStrSub = p.config.usesSso() and e.firstSon.kind == nkBracketExpr and
|
||||
e.firstSon.firstSon.typ.skipTypes(abstractVar).kind == tyString
|
||||
var a: TLoc = initLocExpr(p, e.firstSon, if ssoStrSub: {lfEnforceDeref, lfPrepareForMutation} else: {})
|
||||
if e.firstSon.kind in {nkHiddenStdConv, nkHiddenSubConv, nkConv} and not ignoreConv(e.firstSon):
|
||||
# addr (conv x) introduces a temp because `conv x` is not a rvalue
|
||||
# transform addr ( conv ( x ) ) -> conv ( addr ( x ) )
|
||||
var exprLoc: TLoc = initLocExpr(p, e[0][1])
|
||||
var exprLoc: TLoc = initLocExpr(p, e.firstSon[1])
|
||||
var tmp = getTemp(p, e.typ, needsInit=false)
|
||||
putIntoDest(p, tmp, e, cCast(getTypeDesc(p.module, e.typ), addrLoc(p.config, exprLoc)))
|
||||
putIntoDest(p, d, e, rdLoc(tmp))
|
||||
@@ -1006,7 +1006,7 @@ template inheritLocation(d: var TLoc, a: TLoc) =
|
||||
if d.k == locNone: d.storage = a.storage
|
||||
|
||||
proc genRecordFieldAux(p: BProc, e: PNode, d: var TLoc, a: var TLoc) =
|
||||
a = initLocExpr(p, e[0])
|
||||
a = initLocExpr(p, e.firstSon)
|
||||
if e[1].kind != nkSym: internalError(p.config, e.info, "genRecordFieldAux")
|
||||
d.inheritLocation(a)
|
||||
discard getTypeDesc(p.module, a.t) # fill the record's fields.loc
|
||||
@@ -1014,7 +1014,7 @@ proc genRecordFieldAux(p: BProc, e: PNode, d: var TLoc, a: var TLoc) =
|
||||
proc genTupleElem(p: BProc, e: PNode, d: var TLoc) =
|
||||
var
|
||||
i: int = 0
|
||||
var a: TLoc = initLocExpr(p, e[0])
|
||||
var a: TLoc = initLocExpr(p, e.firstSon)
|
||||
let tupType = a.t.skipTypes(abstractInst+{tyVar}+tyUserTypeClasses) # ref #25227
|
||||
assert tupType.kind == tyTuple
|
||||
d.inheritLocation(a)
|
||||
@@ -1076,8 +1076,8 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym, ty: PType) =
|
||||
for i in 1..<e.len:
|
||||
var it = e[i]
|
||||
assert(it.kind in nkCallKinds)
|
||||
assert(it[0].kind == nkSym)
|
||||
let op = it[0].sym
|
||||
assert(it.firstSon.kind == nkSym)
|
||||
let op = it.firstSon.sym
|
||||
if op.magic == mNot: it = it[1]
|
||||
let disc = it[2].skipConv
|
||||
assert(disc.kind == nkSym)
|
||||
@@ -1154,23 +1154,23 @@ proc genFieldCheck(p: BProc, e: PNode, obj: Rope, field: PSym, ty: PType) =
|
||||
raiseInstr(p, p.s(cpsStmts))
|
||||
|
||||
proc genCheckedRecordField(p: BProc, e: PNode, d: var TLoc) =
|
||||
assert e[0].kind == nkDotExpr
|
||||
assert e.firstSon.kind == nkDotExpr
|
||||
if optFieldCheck in p.options:
|
||||
var a: TLoc = default(TLoc)
|
||||
genRecordFieldAux(p, e[0], d, a)
|
||||
genRecordFieldAux(p, e.firstSon, d, a)
|
||||
let ty = skipTypes(a.t, abstractInst + tyUserTypeClasses)
|
||||
var r = rdLoc(a)
|
||||
let f = e[0][1].sym
|
||||
let f = e.firstSon[1].sym
|
||||
let field = lookupFieldAgain(p, ty, f, r)
|
||||
if field.loc.snippet == "": fillObjectFields(p.module, ty)
|
||||
if field.loc.snippet == "":
|
||||
internalError(p.config, e.info, "genCheckedRecordField") # generate the checks:
|
||||
genFieldCheck(p, e, r, field, ty)
|
||||
r = dotField(r, field.loc.snippet)
|
||||
putIntoDest(p, d, e[0], r, a.storage)
|
||||
putIntoDest(p, d, e.firstSon, r, a.storage)
|
||||
r.freeze
|
||||
else:
|
||||
genRecordField(p, e[0], d)
|
||||
genRecordField(p, e.firstSon, d)
|
||||
|
||||
proc genUncheckedArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
|
||||
var a = initLocExpr(p, x)
|
||||
@@ -1345,14 +1345,14 @@ proc genSeqElem(p: BProc, n, x, y: PNode, d: var TLoc) =
|
||||
putIntoDest(p, d, n, subscript(dataField(p, ra), rcb), a.storage)
|
||||
|
||||
proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) =
|
||||
var ty = skipTypes(n[0].typ, abstractVarRange + tyUserTypeClasses)
|
||||
var ty = skipTypes(n.firstSon.typ, abstractVarRange + tyUserTypeClasses)
|
||||
if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.elementType, abstractVarRange)
|
||||
case ty.kind
|
||||
of tyUncheckedArray: genUncheckedArrayElem(p, n, n[0], n[1], d)
|
||||
of tyArray: genArrayElem(p, n, n[0], n[1], d)
|
||||
of tyOpenArray, tyVarargs: genOpenArrayElem(p, n, n[0], n[1], d)
|
||||
of tySequence, tyString: genSeqElem(p, n, n[0], n[1], d)
|
||||
of tyCstring: genCStringElem(p, n, n[0], n[1], d)
|
||||
of tyUncheckedArray: genUncheckedArrayElem(p, n, n.firstSon, n[1], d)
|
||||
of tyArray: genArrayElem(p, n, n.firstSon, n[1], d)
|
||||
of tyOpenArray, tyVarargs: genOpenArrayElem(p, n, n.firstSon, n[1], d)
|
||||
of tySequence, tyString: genSeqElem(p, n, n.firstSon, n[1], d)
|
||||
of tyCstring: genCStringElem(p, n, n.firstSon, n[1], d)
|
||||
of tyTuple: genTupleElem(p, n, d)
|
||||
else: internalError(p.config, n.info, "expr(nkBracketExpr, " & $ty.kind & ')')
|
||||
discard getTypeDesc(p.module, n.typ)
|
||||
@@ -1940,7 +1940,7 @@ proc genObjConstr(p: BProc, e: PNode, d: var TLoc) =
|
||||
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][0], e[i][1], check, d, r, e.info)
|
||||
genFieldObjConstr(p, ty, useTemp, isRef, e[i].firstSon, e[i][1], check, d, r, e.info)
|
||||
|
||||
if useTemp:
|
||||
if d.k == locNone:
|
||||
@@ -1980,13 +1980,13 @@ proc genSeqConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||
else:
|
||||
# generate call to newSeq before adding the elements per hand:
|
||||
genNewSeqAux(p, dest[], lit, n.len == 0)
|
||||
for i in 0..<n.len:
|
||||
arr = initLoc(locExpr, n[i], OnHeap)
|
||||
for i, ni in isons(n):
|
||||
arr = initLoc(locExpr, ni, OnHeap)
|
||||
let lit = cIntLiteral(i)
|
||||
let rd = rdLoc dest[]
|
||||
arr.snippet = subscript(dataField(p, rd), lit)
|
||||
arr.storage = OnHeap # we know that sequences are on the heap
|
||||
expr(p, n[i], arr)
|
||||
expr(p, ni, arr)
|
||||
gcUsage(p.config, n)
|
||||
if doesAlias:
|
||||
if d.k == locNone:
|
||||
@@ -2176,7 +2176,7 @@ proc genRepr(p: BProc, e: PNode, d: var TLoc) =
|
||||
let ra = rdLoc(a)
|
||||
let la = cIntValue(lengthOrd(p.config, a.t))
|
||||
putIntoDest(p, b, e, ra & cArgumentSeparator & la, a.storage)
|
||||
else: internalError(p.config, e[0].info, "genRepr()")
|
||||
else: internalError(p.config, e.firstSon.info, "genRepr()")
|
||||
let rb = rdLoc(b)
|
||||
let rti = genTypeInfoV1(p.module, elemType(t), e.info)
|
||||
putIntoDest(p, d, e, cgCall("reprOpenArray", rb, rti), a.storage)
|
||||
@@ -2218,7 +2218,7 @@ proc genGetTypeInfo(p: BProc, e: PNode, d: var TLoc) =
|
||||
|
||||
proc genGetTypeInfoV2(p: BProc, e: PNode, d: var TLoc) =
|
||||
let t = e[1].typ
|
||||
if isFinal(t) or e[0].sym.name.s != "getDynamicTypeInfo":
|
||||
if isFinal(t) or e.firstSon.sym.name.s != "getDynamicTypeInfo":
|
||||
# ordinary static type information
|
||||
putIntoDest(p, d, e, genTypeInfoV2(p.module, t, e.info))
|
||||
else:
|
||||
@@ -2249,12 +2249,12 @@ template genDollarIt(p: BProc, n: PNode, d: var TLoc, frmt: untyped) =
|
||||
|
||||
proc genArrayLen(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
var a = e[1]
|
||||
if a.kind == nkHiddenAddr: a = a[0]
|
||||
if a.kind == nkHiddenAddr: a = a.firstSon
|
||||
var typ = skipTypes(a.typ, abstractVar + tyUserTypeClasses)
|
||||
case typ.kind
|
||||
of tyOpenArray, tyVarargs:
|
||||
# Bug #9279, len(toOpenArray()) has to work:
|
||||
if a.kind in nkCallKinds and a[0].kind == nkSym and a[0].sym.magic == mSlice:
|
||||
if a.kind in nkCallKinds and a.firstSon.kind == nkSym and a.firstSon.sym.magic == mSlice:
|
||||
# magic: pass slice to openArray:
|
||||
var m = initLocExpr(p, a[1])
|
||||
var b = initLocExpr(p, a[2])
|
||||
@@ -2318,7 +2318,7 @@ proc genSetLengthSeq(p: BProc, e: PNode, d: var TLoc, noinit = false) =
|
||||
return
|
||||
assert(d.k == locNone)
|
||||
var x = e[1]
|
||||
if x.kind in {nkAddr, nkHiddenAddr}: x = x[0]
|
||||
if x.kind in {nkAddr, nkHiddenAddr}: x = x.firstSon
|
||||
var a = initLocExpr(p, x)
|
||||
var b = initLocExpr(p, e[2])
|
||||
let t = skipTypes(e[1].typ, {tyVar})
|
||||
@@ -2440,7 +2440,7 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) =
|
||||
# so, we skip the unnecessary range check: This is a semantical extension
|
||||
# that code now relies on. :-/ XXX
|
||||
let ea = if e[2].kind in {nkChckRange, nkChckRange64}:
|
||||
e[2][0]
|
||||
e[2].firstSon
|
||||
else:
|
||||
e[2]
|
||||
a = initLocExpr(p, ea)
|
||||
@@ -2451,7 +2451,7 @@ proc genInOp(p: BProc, e: PNode, d: var TLoc) =
|
||||
let it = e[1][i]
|
||||
var currentExpr: Snippet
|
||||
if it.kind == nkRange:
|
||||
x = initLocExpr(p, it[0])
|
||||
x = initLocExpr(p, it.firstSon)
|
||||
y = initLocExpr(p, it[1])
|
||||
let rca = rdCharLoc(a)
|
||||
let rcx = rdCharLoc(x)
|
||||
@@ -2689,13 +2689,13 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
|
||||
genSomeCast(p, e, d)
|
||||
|
||||
proc genRangeChck(p: BProc, n: PNode, d: var TLoc) =
|
||||
var a: TLoc = initLocExpr(p, n[0])
|
||||
var a: TLoc = initLocExpr(p, n.firstSon)
|
||||
var dest = skipTypes(n.typ, abstractVar)
|
||||
if optRangeCheck notin p.options or (dest.kind in {tyUInt..tyUInt64} and
|
||||
checkUnsignedConversions notin p.config.legacyFeatures):
|
||||
discard "no need to generate a check because it was disabled"
|
||||
else:
|
||||
let n0t = n[0].typ
|
||||
let n0t = n.firstSon.typ
|
||||
|
||||
# emit range check:
|
||||
if n0t.kind in {tyUInt, tyUInt64}:
|
||||
@@ -2735,7 +2735,7 @@ proc genRangeChck(p: BProc, n: PNode, d: var TLoc) =
|
||||
p.s(cpsStmts).addCallStmt(raiser, rca, firstVal, lastVal)
|
||||
raiseInstr(p, p.s(cpsStmts))
|
||||
|
||||
if sameBackendTypeIgnoreRange(dest, n[0].typ):
|
||||
if sameBackendTypeIgnoreRange(dest, n.firstSon.typ):
|
||||
# don't cast so an address can be taken for `var` conversions
|
||||
let val = rdCharLoc(a)
|
||||
putIntoDest(p, d, n, wrapPar(val), a.storage)
|
||||
@@ -2751,14 +2751,14 @@ proc genConv(p: BProc, e: PNode, d: var TLoc) =
|
||||
genSomeCast(p, e, d)
|
||||
|
||||
proc convStrToCStr(p: BProc, n: PNode, d: var TLoc) =
|
||||
var a: TLoc = initLocExpr(p, n[0])
|
||||
var a: TLoc = initLocExpr(p, n.firstSon)
|
||||
let arg = if p.config.usesSso(): byRefLoc(p, a) else: rdLoc(a)
|
||||
putIntoDest(p, d, n,
|
||||
cgCall(p, "nimToCStringConv", arg),
|
||||
a.storage)
|
||||
|
||||
proc convCStrToStr(p: BProc, n: PNode, d: var TLoc) =
|
||||
var a: TLoc = initLocExpr(p, n[0])
|
||||
var a: TLoc = initLocExpr(p, n.firstSon)
|
||||
if p.module.compileToCpp:
|
||||
# fixes for const qualifier; bug #12703; bug #19588
|
||||
putIntoDest(p, d, n,
|
||||
@@ -2941,7 +2941,7 @@ proc genEnumToStr(p: BProc, e: PNode, d: var TLoc) =
|
||||
proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
case op
|
||||
of mAsgn:
|
||||
let kind = if e[0].sym.name.s == "=sink": nkSinkAsgn else: nkAsgn
|
||||
let kind = if e.firstSon.sym.name.s == "=sink": nkSinkAsgn else: nkAsgn
|
||||
let lhs = e[1].skipHiddenAddr
|
||||
let n = newTreeI(kind, e.info, lhs, e[2])
|
||||
n.typ = e.typ
|
||||
@@ -3056,11 +3056,11 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
if e[1].kind == nkDotExpr:
|
||||
dotExpr = e[1]
|
||||
elif e[1].kind == nkCheckedFieldExpr:
|
||||
dotExpr = e[1][0]
|
||||
dotExpr = e[1].firstSon
|
||||
else:
|
||||
dotExpr = nil
|
||||
internalError(p.config, e.info, "unknown ast")
|
||||
let t = dotExpr[0].typ.skipTypes({tyTypeDesc})
|
||||
let t = dotExpr.firstSon.typ.skipTypes({tyTypeDesc})
|
||||
let tname = getTypeDesc(p.module, t, dkVar)
|
||||
let member =
|
||||
if t.kind == tyTuple:
|
||||
@@ -3090,7 +3090,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
mInSet, mXorSet:
|
||||
genSetOp(p, e, d, op)
|
||||
of mNewString, mNewStringOfCap, mExit, mParseBiggestFloat:
|
||||
var opr = e[0].sym
|
||||
var opr = e.firstSon.sym
|
||||
# Why would anyone want to set nodecl to one of these hardcoded magics?
|
||||
# - not sure, and it wouldn't work if the symbol behind the magic isn't
|
||||
# somehow forward-declared from some other usage, but it is *possible*
|
||||
@@ -3125,7 +3125,7 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) =
|
||||
of mEcho: genEcho(p, e[1].skipConv)
|
||||
of mArrToSeq: genArrToSeq(p, e, d)
|
||||
of mNLen..mNError, mSlurp..mQuoteAst:
|
||||
localError(p.config, e.info, strutils.`%`(errXMustBeCompileTime, e[0].sym.name.s))
|
||||
localError(p.config, e.info, strutils.`%`(errXMustBeCompileTime, e.firstSon.sym.name.s))
|
||||
of mSpawn:
|
||||
when defined(leanCompiler):
|
||||
p.config.quitOrRaise "compiler built without support for the 'spawn' statement"
|
||||
@@ -3193,7 +3193,7 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
|
||||
for it in e.sons:
|
||||
if it.kind == nkRange:
|
||||
idx = getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt)) # our counter
|
||||
a = initLocExpr(p, it[0])
|
||||
a = initLocExpr(p, it.firstSon)
|
||||
b = initLocExpr(p, it[1])
|
||||
var aa: Snippet = ""
|
||||
rdSetElemLoc(p.config, a, e.typ, aa)
|
||||
@@ -3222,7 +3222,7 @@ proc genSetConstr(p: BProc, e: PNode, d: var TLoc) =
|
||||
for it in e.sons:
|
||||
if it.kind == nkRange:
|
||||
idx = getTemp(p, getSysType(p.module.g.graph, unknownLineInfo, tyInt)) # our counter
|
||||
a = initLocExpr(p, it[0])
|
||||
a = initLocExpr(p, it.firstSon)
|
||||
b = initLocExpr(p, it[1])
|
||||
var aa: Snippet = ""
|
||||
rdSetElemLoc(p.config, a, e.typ, aa)
|
||||
@@ -3258,8 +3258,8 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||
elif d.k == locNone:
|
||||
d = getTemp(p, n.typ)
|
||||
|
||||
for i in 0..<n.len:
|
||||
var it = n[i]
|
||||
for i, ni in isons(n):
|
||||
var it = ni
|
||||
if it.kind == nkExprColonExpr: it = it[1]
|
||||
# Do not produce code for void types
|
||||
if it.typ != nil and isEmptyType(it.typ): continue
|
||||
@@ -3275,7 +3275,7 @@ proc genTupleConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||
genAssignment(p, d, tmp, {})
|
||||
|
||||
proc isConstClosure(n: PNode): bool {.inline.} =
|
||||
result = n[0].kind == nkSym and isRoutine(n[0].sym) and
|
||||
result = n.firstSon.kind == nkSym and isRoutine(n.firstSon.sym) and
|
||||
n[1].kind == nkNilLit
|
||||
|
||||
proc genClosure(p: BProc, n: PNode, d: var TLoc) =
|
||||
@@ -3292,9 +3292,9 @@ proc genClosure(p: BProc, n: PNode, d: var TLoc) =
|
||||
putIntoDest(p, d, n, tmp, OnStatic)
|
||||
else:
|
||||
var tmp: TLoc
|
||||
var a = initLocExpr(p, n[0])
|
||||
var a = initLocExpr(p, n.firstSon)
|
||||
var b = initLocExpr(p, n[1])
|
||||
if n[0].skipConv.kind == nkClosure:
|
||||
if n.firstSon.skipConv.kind == nkClosure:
|
||||
internalError(p.config, n.info, "closure to closure created")
|
||||
# tasyncawait.nim breaks with this optimization:
|
||||
when false:
|
||||
@@ -3313,11 +3313,11 @@ proc genArrayConstr(p: BProc, n: PNode, d: var TLoc) =
|
||||
var arr: TLoc
|
||||
if not handleConstExpr(p, n, d):
|
||||
if d.k == locNone: d = getTemp(p, n.typ)
|
||||
for i in 0..<n.len:
|
||||
for i, ni in isons(n):
|
||||
arr = initLoc(locExpr, lodeTyp elemType(skipTypes(n.typ, abstractInst)), d.storage)
|
||||
let lit = cIntLiteral(i)
|
||||
arr.snippet = subscript(rdLoc(d), lit)
|
||||
expr(p, n[i], arr)
|
||||
expr(p, ni, arr)
|
||||
|
||||
proc genComplexConst(p: BProc, sym: PSym, d: var TLoc) =
|
||||
requestConstImpl(p, sym)
|
||||
@@ -3336,7 +3336,7 @@ template genStmtListExprImpl(exprOrStmt) {.dirty.} =
|
||||
if hasNimFrame and frameName == "":
|
||||
inc p.labels
|
||||
frameName = "FR" & rope(p.labels) & "_"
|
||||
let theMacro = it[0].sym
|
||||
let theMacro = it.firstSon.sym
|
||||
add p.s(cpsStmts), initFrameNoDebug(p, frameName,
|
||||
makeCString theMacro.name.s,
|
||||
quotedFilename(p.config, theMacro.info), it.info.line.int)
|
||||
@@ -3357,7 +3357,7 @@ proc genStmtList(p: BProc, n: PNode) =
|
||||
from parampatterns import isLValue
|
||||
|
||||
proc upConv(p: BProc, n: PNode, d: var TLoc) =
|
||||
var a: TLoc = initLocExpr(p, n[0])
|
||||
var a: TLoc = initLocExpr(p, n.firstSon)
|
||||
let dest = skipTypes(n.typ, abstractPtrs)
|
||||
if optObjCheck in p.options and not isObjLackingTypeField(dest):
|
||||
var nilCheck = ""
|
||||
@@ -3381,9 +3381,9 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
|
||||
|
||||
# skip cast when types map to the same C type
|
||||
# this avoids invalid C code like `*(T*)&x` for types that can't have their address taken (e.g., WASM __externref_t)
|
||||
if getTypeDesc(p.module, n.typ) == getTypeDesc(p.module, n[0].typ):
|
||||
expr(p, n[0], d)
|
||||
elif n[0].typ.kind != tyObject:
|
||||
if getTypeDesc(p.module, n.typ) == getTypeDesc(p.module, n.firstSon.typ):
|
||||
expr(p, n.firstSon, d)
|
||||
elif n.firstSon.typ.kind != tyObject:
|
||||
let destTyp = getTypeDesc(p.module, n.typ)
|
||||
let val = rdLoc(a)
|
||||
if n.isLValue:
|
||||
@@ -3407,8 +3407,8 @@ proc upConv(p: BProc, n: PNode, d: var TLoc) =
|
||||
a.storage)
|
||||
|
||||
proc downConv(p: BProc, n: PNode, d: var TLoc) =
|
||||
var arg = n[0]
|
||||
while arg.kind == nkObjDownConv: arg = arg[0]
|
||||
var arg = n.firstSon
|
||||
while arg.kind == nkObjDownConv: arg = arg.firstSon
|
||||
|
||||
let dest = skipTypes(n.typ, abstractPtrs)
|
||||
let src = skipTypes(arg.typ, abstractPtrs)
|
||||
@@ -3566,8 +3566,8 @@ proc genConstStmt(p: BProc, n: PNode) =
|
||||
assert delayedCodegen(p.module)
|
||||
let m = p.module
|
||||
for it in n:
|
||||
if it[0].kind == nkSym:
|
||||
let sym = it[0].sym
|
||||
if it.firstSon.kind == nkSym:
|
||||
let sym = it.firstSon.sym
|
||||
if not isSimpleConst(sym.typ) and sym.itemId.item in m.alive and genConstSetup(p, sym):
|
||||
genConstDefinition(m, p, sym)
|
||||
|
||||
@@ -3698,7 +3698,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkPostfix, nkCommand,
|
||||
nkCallStrLit:
|
||||
genLineDir(p, n) # may be redundant, it is generated in fixupCall as well
|
||||
let op = n[0]
|
||||
let op = n.firstSon
|
||||
if n.typ.isNil:
|
||||
# discard the value:
|
||||
var a: TLoc = default(TLoc)
|
||||
@@ -3747,7 +3747,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
of nkIfExpr, nkIfStmt: genIf(p, n, d)
|
||||
of nkWhen:
|
||||
# This should be a "when nimvm" node.
|
||||
expr(p, n[1][0], d)
|
||||
expr(p, n[1].firstSon, d)
|
||||
of nkObjDownConv: downConv(p, n, d)
|
||||
of nkObjUpConv: upConv(p, n, d)
|
||||
of nkChckRangeF, nkChckRange64, nkChckRange: genRangeChck(p, n, d)
|
||||
@@ -3770,7 +3770,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
else: # enforce addressable consts for exportc
|
||||
let m = p.module
|
||||
for it in n:
|
||||
let symNode = skipPragmaExpr(it[0])
|
||||
let symNode = skipPragmaExpr(it.firstSon)
|
||||
if symNode.kind == nkSym and sfExportc in symNode.sym.flags:
|
||||
requestConstImpl(p, symNode.sym)
|
||||
# else: consts generated lazily on use
|
||||
@@ -3789,7 +3789,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
# See tests/run/tcnstseq3 for an example that would fail otherwise.
|
||||
genAsgn(p, n, fastAsgn=p.prc != nil)
|
||||
of nkDiscardStmt:
|
||||
let ex = n[0]
|
||||
let ex = n.firstSon
|
||||
if ex.kind != nkEmpty:
|
||||
genLineDir(p, n)
|
||||
var a: TLoc = initLocExprSingleUse(p, ex)
|
||||
@@ -3815,7 +3815,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
of nkPragma: genPragma(p, n)
|
||||
of nkPragmaBlock:
|
||||
var inUncheckedAssignSection = 0
|
||||
let pragmaList = n[0]
|
||||
let pragmaList = n.firstSon
|
||||
for pi in pragmaList:
|
||||
if whichPragma(pi) == wCast:
|
||||
case whichPragma(pi[1])
|
||||
@@ -3877,7 +3877,7 @@ proc containsOpaqueImportcFieldAux(t: PType; n: PNode): bool =
|
||||
if containsOpaqueImportcFieldAux(t, child):
|
||||
return true
|
||||
of nkRecCase:
|
||||
if containsOpaqueImportcFieldAux(t, n[0]):
|
||||
if containsOpaqueImportcFieldAux(t, n.firstSon):
|
||||
return true
|
||||
for i in 1..<n.len:
|
||||
let branch = n[i]
|
||||
@@ -4017,16 +4017,16 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
|
||||
# generate only 1 field for default value of union
|
||||
return
|
||||
of nkRecCase:
|
||||
getNullValueAux(p, t, obj[0], constOrNil, result, init, isConst, info)
|
||||
getNullValueAux(p, t, obj.firstSon, constOrNil, result, init, isConst, info)
|
||||
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][0].sym.name.id == obj[0].sym.name.id:
|
||||
if constOrNil[i].firstSon.sym.name.id == obj.firstSon.sym.name.id:
|
||||
branch = getOrdValue(constOrNil[i][1])
|
||||
break
|
||||
elif i == obj[0].sym.position:
|
||||
elif i == obj.firstSon.sym.position:
|
||||
branch = getOrdValue(constOrNil[i])
|
||||
break
|
||||
|
||||
@@ -4036,7 +4036,7 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
|
||||
# branches are allowed to have no members (b.len == 0), in this case they don't need initializer
|
||||
var fieldName: string = ""
|
||||
if b.kind == nkRecList and not isEmptyCaseObjectBranch(b):
|
||||
fieldName = "_" & mangleRecFieldName(p.module, obj[0].sym) & "_" & $selectedBranch
|
||||
fieldName = "_" & mangleRecFieldName(p.module, obj.firstSon.sym) & "_" & $selectedBranch
|
||||
result.addField(init, name = ""): # anonymous union
|
||||
var branchInit: StructInitializer
|
||||
result.addStructInitializer(branchInit, kind = siNamedStruct):
|
||||
@@ -4070,8 +4070,8 @@ proc getNullValueAux(p: BProc; t: PType; obj, constOrNil: PNode,
|
||||
if constOrNil != nil:
|
||||
for i in 1..<constOrNil.len:
|
||||
if constOrNil[i].kind == nkExprColonExpr:
|
||||
assert constOrNil[i][0].kind == nkSym, "illformed object constr; the field is not a sym"
|
||||
if constOrNil[i][0].sym.name.id == field.name.id:
|
||||
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)
|
||||
break fieldInit
|
||||
elif i == field.position:
|
||||
@@ -4121,11 +4121,10 @@ proc genConstSimpleList(p: BProc, n: PNode; isConst: bool; result: var Builder)
|
||||
if p.vccAndC and n.len == 0 and n.typ.kind == tyArray:
|
||||
result.addField(arrInit, name = ""):
|
||||
getDefaultValue(p, n.typ.elementType, n.info, result)
|
||||
for i in 0..<n.len:
|
||||
let it = n[i]
|
||||
for it in n.sons:
|
||||
var ind, val: PNode
|
||||
if it.kind == nkExprColonExpr:
|
||||
ind = it[0]
|
||||
ind = it.firstSon
|
||||
val = it[1]
|
||||
else:
|
||||
ind = it
|
||||
@@ -4139,8 +4138,8 @@ proc genConstTuple(p: BProc, n: PNode; isConst: bool; tup: PType; result: var Bu
|
||||
if p.vccAndC and n.len == 0:
|
||||
result.addField(tupleInit, name = "dummy"):
|
||||
result.addIntValue(0)
|
||||
for i in 0..<n.len:
|
||||
var it = n[i]
|
||||
for i, ni in isons(n):
|
||||
var it = ni
|
||||
if it.kind == nkExprColonExpr:
|
||||
it = it[1]
|
||||
# Do not produce code for void types
|
||||
@@ -4174,9 +4173,9 @@ proc genConstSeq(p: BProc, n: PNode, t: PType; isConst: bool; result: var Builde
|
||||
def.addField(structInit, name = "data"):
|
||||
var arrInit: StructInitializer
|
||||
def.addStructInitializer(arrInit, kind = siArray):
|
||||
for i in 0..<n.len:
|
||||
for ni in n.sons:
|
||||
def.addField(arrInit, name = ""):
|
||||
genBracedInit(p, n[i], isConst, base, def)
|
||||
genBracedInit(p, ni, isConst, base, def)
|
||||
p.module.s[cfsStrData].add extract(def)
|
||||
|
||||
result.add cCast(typ = getTypeDesc(p.module, t), value = cAddr(tmpName))
|
||||
@@ -4202,9 +4201,9 @@ proc genConstSeqV2(p: BProc, n: PNode, t: PType; isConst: bool; result: var Buil
|
||||
def.addField(structInit, name = "data"):
|
||||
var arrInit: StructInitializer
|
||||
def.addStructInitializer(arrInit, kind = siArray):
|
||||
for i in 0..<n.len:
|
||||
for ni in n.sons:
|
||||
def.addField(arrInit, name = ""):
|
||||
genBracedInit(p, n[i], isConst, base, def)
|
||||
genBracedInit(p, ni, isConst, base, def)
|
||||
p.module.s[cfsStrData].add extract(def)
|
||||
|
||||
var resultInit: StructInitializer
|
||||
@@ -4252,10 +4251,10 @@ proc genBracedInit(p: BProc, n: PNode; isConst: bool; optionalType: PType; resul
|
||||
var closureInit: StructInitializer
|
||||
result.addStructInitializer(closureInit, kind = siOrderedStruct):
|
||||
result.addField(closureInit, name = "ClP_0"):
|
||||
if n[0].kind == nkNilLit:
|
||||
if n.firstSon.kind == nkNilLit:
|
||||
result.add(NimNil)
|
||||
else:
|
||||
var d: TLoc = initLocExpr(p, n[0])
|
||||
var d: TLoc = initLocExpr(p, n.firstSon)
|
||||
result.add(cCast(typ = getClosureType(p.module, typ, clHalfWithEnv), value = rdLoc(d)))
|
||||
result.addField(closureInit, name = "ClE_0"):
|
||||
result.add(NimNil)
|
||||
|
||||
@@ -34,10 +34,10 @@ proc registerTraverseProc(p: BProc, v: PSym) =
|
||||
proc isAssignedImmediately(conf: ConfigRef; n: PNode): bool {.inline.} =
|
||||
if n.kind == nkEmpty:
|
||||
result = false
|
||||
elif n.kind in nkCallKinds and n[0] != nil and n[0].typ != nil and n[0].typ.skipTypes(abstractInst).kind == tyProc:
|
||||
if n[0].kind == nkSym and sfConstructor in n[0].sym.flags:
|
||||
elif n.kind in nkCallKinds and n.firstSon != nil and n.firstSon.typ != nil and n.firstSon.typ.skipTypes(abstractInst).kind == tyProc:
|
||||
if n.firstSon.kind == nkSym and sfConstructor in n.firstSon.sym.flags:
|
||||
result = true
|
||||
elif isInvalidReturnType(conf, n[0].typ, true):
|
||||
elif isInvalidReturnType(conf, n.firstSon.typ, true):
|
||||
# var v = f()
|
||||
# is transformed into: var v; f(addr v)
|
||||
# where 'f' **does not** initialize the result!
|
||||
@@ -104,7 +104,7 @@ proc genVarTuple(p: BProc, n: PNode) =
|
||||
return
|
||||
|
||||
# check only the first son
|
||||
var forHcr = treatGlobalDifferentlyForHCR(p.module, n[0].sym)
|
||||
var forHcr = treatGlobalDifferentlyForHCR(p.module, n.firstSon.sym)
|
||||
let hcrCond = if forHcr: getTempName(p.module) else: ""
|
||||
var hcrGlobals: seq[tuple[loc: TLoc, tp: Rope]] = @[]
|
||||
# determine if the tuple is constructed at top-level scope or inside of a block (if/while/block)
|
||||
@@ -166,7 +166,7 @@ proc genVarTuple(p: BProc, n: PNode) =
|
||||
p.s(cpsLocals).addInPlaceOp(BitOr, NimBool,
|
||||
hcrCond,
|
||||
cCall("hcrRegisterGlobal",
|
||||
getModuleDllPath(p.module, n[0].sym),
|
||||
getModuleDllPath(p.module, n.firstSon.sym),
|
||||
'"' & curr.loc.snippet & '"',
|
||||
cSizeof(rc),
|
||||
curr.tp,
|
||||
@@ -174,8 +174,8 @@ proc genVarTuple(p: BProc, n: PNode) =
|
||||
|
||||
|
||||
proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} =
|
||||
if ri.kind in nkCallKinds and (ri[0].kind != nkSym or
|
||||
ri[0].sym.magic == mNone):
|
||||
if ri.kind in nkCallKinds and (ri.firstSon.kind != nkSym or
|
||||
ri.firstSon.sym.magic == mNone):
|
||||
genAsgnCall(p, le, ri, a)
|
||||
else:
|
||||
# this is a hacky way to fix #1181 (tmissingderef)::
|
||||
@@ -219,9 +219,9 @@ template preserveBreakIdx(body: untyped): untyped =
|
||||
|
||||
proc genState(p: BProc, n: PNode) =
|
||||
internalAssert p.config, n.len == 1
|
||||
let n0 = n[0]
|
||||
let n0 = n.firstSon
|
||||
if n0.kind == nkIntLit:
|
||||
let idx = n[0].intVal
|
||||
let idx = n.firstSon.intVal
|
||||
p.s(cpsStmts).addLabel("STATE" & $idx)
|
||||
elif n0.kind == nkStrLit:
|
||||
p.s(cpsStmts).addLabel(n0.strVal)
|
||||
@@ -248,7 +248,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int, isReturnStmt
|
||||
# and generate a copy of its sons
|
||||
var finallyStmt = tryStmt.fin
|
||||
if finallyStmt != nil:
|
||||
genStmts(p, finallyStmt[0])
|
||||
genStmts(p, finallyStmt.firstSon)
|
||||
|
||||
dec p.withinBlockLeaveActions
|
||||
|
||||
@@ -268,7 +268,7 @@ proc genGotoState(p: BProc, n: PNode) =
|
||||
# switch (x.state) {
|
||||
# case 0: goto STATE0;
|
||||
# ...
|
||||
var a: TLoc = initLocExpr(p, n[0])
|
||||
var a: TLoc = initLocExpr(p, n.firstSon)
|
||||
let ra = rdLoc(a)
|
||||
p.s(cpsStmts).addSwitchStmt(ra):
|
||||
p.flags.incl beforeRetNeeded
|
||||
@@ -277,7 +277,7 @@ proc genGotoState(p: BProc, n: PNode) =
|
||||
howManyTrys = p.nestedTryStmts.len,
|
||||
howManyExcepts = p.inExceptBlockLen)
|
||||
p.s(cpsStmts).addGoto("BeforeRet_")
|
||||
var statesCounter = lastOrd(p.config, n[0].typ)
|
||||
var statesCounter = lastOrd(p.config, n.firstSon.typ)
|
||||
if n.len >= 2 and n[1].kind == nkIntLit:
|
||||
statesCounter = getInt(n[1])
|
||||
let prefix = if n.len == 3 and n[2].kind == nkStrLit: n[2].strVal.rope
|
||||
@@ -290,8 +290,8 @@ proc genBreakState(p: BProc, n: PNode, d: var TLoc) =
|
||||
var a: TLoc
|
||||
d = initLoc(locExpr, n, OnUnknown)
|
||||
|
||||
if n[0].kind == nkClosure:
|
||||
a = initLocExpr(p, n[0][1])
|
||||
if n.firstSon.kind == nkClosure:
|
||||
a = initLocExpr(p, n.firstSon[1])
|
||||
let ra = a.rdLoc
|
||||
d.snippet = cOp(LessThan,
|
||||
subscript(
|
||||
@@ -299,7 +299,7 @@ proc genBreakState(p: BProc, n: PNode, d: var TLoc) =
|
||||
cIntValue(1)),
|
||||
cIntValue(0))
|
||||
else:
|
||||
a = initLocExpr(p, n[0])
|
||||
a = initLocExpr(p, n.firstSon)
|
||||
let ra = a.rdLoc
|
||||
# the environment is guaranteed to contain the 'state' field at offset 1:
|
||||
d.snippet = cOp(LessThan,
|
||||
@@ -327,18 +327,18 @@ proc potentialValueInit(p: BProc; v: PSym; value: PNode; result: var Builder) =
|
||||
proc genCppParamsForCtor(p: BProc; call: PNode; didGenTemp: var bool): Snippet =
|
||||
var res = newBuilder("")
|
||||
var argBuilder = default(CallBuilder) # not init, only building params
|
||||
let typ = skipTypes(call[0].typ, abstractInst)
|
||||
let typ = skipTypes(call.firstSon.typ, abstractInst)
|
||||
assert(typ.kind == tyProc)
|
||||
for i in 1..<call.len:
|
||||
#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][0].kind == nkSym and call[i][0].sym.kind == skType:
|
||||
if call[i].kind == nkCall and call[i].firstSon.kind == nkSym and call[i].firstSon.sym.kind == skType:
|
||||
res.addArgument(argBuilder):
|
||||
res.add genCppInitializer(p.module, p, call[i][0].sym.typ, didGenTemp)
|
||||
res.add genCppInitializer(p.module, p, call[i].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][0]
|
||||
call[i].firstSon
|
||||
else:
|
||||
call[i]
|
||||
if not param.typ.isCompileTimeOnly and (param.kind != nkBracketExpr or param.typ.kind in
|
||||
@@ -356,8 +356,8 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||
return
|
||||
let imm = isAssignedImmediately(p.config, value)
|
||||
let isCppCtorCall = p.module.compileToCpp and imm and
|
||||
value.kind in nkCallKinds and value[0].kind == nkSym and
|
||||
v.typ.kind != tyPtr and sfConstructor in value[0].sym.flags
|
||||
value.kind in nkCallKinds and value.firstSon.kind == nkSym and
|
||||
v.typ.kind != tyPtr and sfConstructor in value.firstSon.sym.flags
|
||||
var targetProc = p
|
||||
var valueBuilder = newBuilder("")
|
||||
potentialValueInit(p, v, value, valueBuilder)
|
||||
@@ -470,7 +470,7 @@ proc genSingleVar(p: BProc, v: PSym; vn, value: PNode) =
|
||||
finishIfStmt(p.s(cpsStmts), hcrInit)
|
||||
|
||||
proc genSingleVar(p: BProc, a: PNode) =
|
||||
let v = a[0].sym
|
||||
let v = a.firstSon.sym
|
||||
if sfCompileTime in v.flags:
|
||||
# fix issue #12640
|
||||
# {.global, compileTime.} pragma in proc
|
||||
@@ -478,15 +478,15 @@ proc genSingleVar(p: BProc, a: PNode) =
|
||||
discard
|
||||
else:
|
||||
return
|
||||
genSingleVar(p, v, a[0], a[2])
|
||||
genSingleVar(p, v, a.firstSon, a[2])
|
||||
|
||||
proc genClosureVar(p: BProc, a: PNode) =
|
||||
var immediateAsgn = a[2].kind != nkEmpty
|
||||
var v: TLoc = initLocExpr(p, a[0])
|
||||
var v: TLoc = initLocExpr(p, a.firstSon)
|
||||
genLineDir(p, a)
|
||||
if immediateAsgn:
|
||||
loadInto(p, a[0], a[2], v)
|
||||
elif sfNoInit notin a[0][1].sym.flags:
|
||||
loadInto(p, a.firstSon, a[2], v)
|
||||
elif sfNoInit notin a.firstSon[1].sym.flags:
|
||||
constructLoc(p, v)
|
||||
|
||||
proc genVarStmt(p: BProc, n: PNode) =
|
||||
@@ -495,7 +495,7 @@ proc genVarStmt(p: BProc, n: PNode) =
|
||||
of nkCommentStmt: discard
|
||||
of nkIdentDefs:
|
||||
# can be a lifted var nowadays ...
|
||||
if it[0].kind == nkSym:
|
||||
if it.firstSon.kind == nkSym:
|
||||
genSingleVar(p, it)
|
||||
else:
|
||||
genClosureVar(p, it)
|
||||
@@ -529,7 +529,7 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) =
|
||||
if it.len == 2:
|
||||
var scope: ScopeBuilder
|
||||
startSimpleBlock(p, scope)
|
||||
a = initLocExprSingleUse(p, it[0])
|
||||
a = initLocExprSingleUse(p, it.firstSon)
|
||||
lelse = getLabel(p)
|
||||
inc(p.labels)
|
||||
let ra = rdLoc(a)
|
||||
@@ -548,7 +548,7 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) =
|
||||
elif it.len == 1:
|
||||
var scope: ScopeBuilder
|
||||
startSimpleBlock(p, scope)
|
||||
expr(p, it[0], d)
|
||||
expr(p, it.firstSon, d)
|
||||
endSimpleBlock(p, scope)
|
||||
else: internalError(p.config, n.info, "genIf()")
|
||||
if n.len > 1: fixLabel(p, lend)
|
||||
@@ -557,7 +557,7 @@ proc genReturnStmt(p: BProc, t: PNode) =
|
||||
if nfPreventCg in t.flags: return
|
||||
p.flags.incl beforeRetNeeded
|
||||
genLineDir(p, t)
|
||||
if (t[0].kind != nkEmpty): genStmts(p, t[0])
|
||||
if (t.firstSon.kind != nkEmpty): genStmts(p, t.firstSon)
|
||||
blockLeaveActions(p,
|
||||
howManyTrys = p.nestedTryStmts.len,
|
||||
howManyExcepts = p.inExceptBlockLen,
|
||||
@@ -605,22 +605,21 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
||||
let n = n.flattenStmts()
|
||||
var casePos = -1
|
||||
var arraySize: int = 0
|
||||
for i in 0..<n.len:
|
||||
let it = n[i]
|
||||
for i, it in isons(n):
|
||||
if it.kind == nkCaseStmt:
|
||||
if lastSon(it).kind != nkOfBranch:
|
||||
localError(p.config, it.info,
|
||||
"case statement must be exhaustive for computed goto"); return
|
||||
casePos = i
|
||||
if enumHasHoles(it[0].typ):
|
||||
if enumHasHoles(it.firstSon.typ):
|
||||
localError(p.config, it.info,
|
||||
"case statement cannot work on enums with holes for computed goto"); return
|
||||
let aSize = lengthOrd(p.config, it[0].typ)
|
||||
let aSize = lengthOrd(p.config, it.firstSon.typ)
|
||||
if aSize > 10_000:
|
||||
localError(p.config, it.info,
|
||||
"case statement has too many cases for computed goto"); return
|
||||
arraySize = toInt(aSize)
|
||||
if firstOrd(p.config, it[0].typ) != 0:
|
||||
if firstOrd(p.config, it.firstSon.typ) != 0:
|
||||
localError(p.config, it.info,
|
||||
"case statement has to start at 0 for computed goto"); return
|
||||
if casePos < 0:
|
||||
@@ -642,7 +641,7 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
||||
genStmts(p, n[j])
|
||||
|
||||
let caseStmt = n[casePos]
|
||||
var a: TLoc = initLocExpr(p, caseStmt[0])
|
||||
var a: TLoc = initLocExpr(p, caseStmt.firstSon)
|
||||
let ra = a.rdLoc
|
||||
# first goto:
|
||||
p.s(cpsStmts).addComputedGoto(subscript(tmp, ra))
|
||||
@@ -681,7 +680,7 @@ proc genComputedGoto(p: BProc; n: PNode) =
|
||||
else:
|
||||
genStmts(p, it)
|
||||
|
||||
var a: TLoc = initLocExpr(p, caseStmt[0])
|
||||
var a: TLoc = initLocExpr(p, caseStmt.firstSon)
|
||||
let ra = a.rdLoc
|
||||
p.s(cpsStmts).addComputedGoto(subscript(tmp, ra))
|
||||
endSimpleBlock(p, scope)
|
||||
@@ -704,7 +703,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
|
||||
if loopBody.stmtsContainPragma(wComputedGoto) and
|
||||
hasComputedGoto in CC[p.config.cCompiler].props:
|
||||
# for closure support weird loop bodies are generated:
|
||||
if loopBody.len == 2 and loopBody[0].kind == nkEmpty:
|
||||
if loopBody.len == 2 and loopBody.firstSon.kind == nkEmpty:
|
||||
loopBody = loopBody[1]
|
||||
genComputedGoto(p, loopBody)
|
||||
else:
|
||||
@@ -712,8 +711,8 @@ proc genWhileStmt(p: BProc, t: PNode) =
|
||||
p.breakIdx = startBlockWith(p):
|
||||
stmt = initWhileStmt(p.s(cpsStmts), cIntValue(1))
|
||||
p.blocks[p.breakIdx].isLoop = true
|
||||
a = initLocExpr(p, t[0])
|
||||
if (t[0].kind != nkIntLit) or (t[0].intVal == 0):
|
||||
a = initLocExpr(p, t.firstSon)
|
||||
if (t.firstSon.kind != nkIntLit) or (t.firstSon.intVal == 0):
|
||||
let ra = a.rdLoc
|
||||
var label: TLabel = ""
|
||||
assignLabel(p.blocks[p.breakIdx], label)
|
||||
@@ -739,10 +738,10 @@ proc genBlock(p: BProc, n: PNode, d: var TLoc) =
|
||||
preserveBreakIdx:
|
||||
var scope: ScopeBuilder
|
||||
p.breakIdx = startSimpleBlock(p, scope)
|
||||
if n[0].kind != nkEmpty:
|
||||
if n.firstSon.kind != nkEmpty:
|
||||
# named block?
|
||||
assert(n[0].kind == nkSym)
|
||||
var sym = n[0].sym
|
||||
assert(n.firstSon.kind == nkSym)
|
||||
var sym = n.firstSon.sym
|
||||
backendEnsureMutable sym
|
||||
sym.locImpl.k = locOther
|
||||
sym.positionImpl = p.breakIdx+1
|
||||
@@ -756,8 +755,8 @@ proc genParForStmt(p: BProc, t: PNode) =
|
||||
genLineDir(p, t)
|
||||
|
||||
preserveBreakIdx:
|
||||
let forLoopVar = t[0].sym
|
||||
assignLocalVar(p, t[0])
|
||||
let forLoopVar = t.firstSon.sym
|
||||
assignLocalVar(p, t.firstSon)
|
||||
#initLoc(forLoopVar.loc, locLocalVar, forLoopVar.typ, onStack)
|
||||
#discard mangleName(forLoopVar)
|
||||
let call = t[1]
|
||||
@@ -768,7 +767,7 @@ proc genParForStmt(p: BProc, t: PNode) =
|
||||
var stepNode: PNode = nil
|
||||
# $n at the beginning because of #9710
|
||||
if call.len == 4: # procName(a, b, annotation)
|
||||
if call[0].sym.name.s == "||": # `||`(a, b, annotation)
|
||||
if call.firstSon.sym.name.s == "||": # `||`(a, b, annotation)
|
||||
p.s(cpsStmts).addCPragma("omp " & call[3].getStr)
|
||||
else:
|
||||
p.s(cpsStmts).addCPragma(call[3].getStr)
|
||||
@@ -791,10 +790,10 @@ proc genParForStmt(p: BProc, t: PNode) =
|
||||
|
||||
proc genBreakStmt(p: BProc, t: PNode) =
|
||||
var idx = p.breakIdx
|
||||
if t[0].kind != nkEmpty:
|
||||
if t.firstSon.kind != nkEmpty:
|
||||
# named break?
|
||||
assert(t[0].kind == nkSym)
|
||||
var sym = t[0].sym
|
||||
assert(t.firstSon.kind == nkSym)
|
||||
var sym = t.firstSon.sym
|
||||
doAssert(sym.loc.k == locOther)
|
||||
idx = sym.position-1
|
||||
else:
|
||||
@@ -854,7 +853,7 @@ proc finallyActions(p: BProc) =
|
||||
if p.nestedTryStmts[i].inExcept:
|
||||
let finallyBlock = p.nestedTryStmts[i].fin
|
||||
if finallyBlock != nil:
|
||||
genSimpleBlock(p, finallyBlock[0])
|
||||
genSimpleBlock(p, finallyBlock.firstSon)
|
||||
return
|
||||
|
||||
proc raiseInstr(p: BProc; result: var Builder) =
|
||||
@@ -871,12 +870,12 @@ proc raiseInstr(p: BProc; result: var Builder) =
|
||||
# + ord(p.nestedTryStmts[L-1].inExcept)])
|
||||
|
||||
proc genRaiseStmt(p: BProc, t: PNode) =
|
||||
if t[0].kind != nkEmpty:
|
||||
var a: TLoc = initLocExprSingleUse(p, t[0])
|
||||
if t.firstSon.kind != nkEmpty:
|
||||
var a: TLoc = initLocExprSingleUse(p, t.firstSon)
|
||||
finallyActions(p)
|
||||
var e = rdLoc(a)
|
||||
discard getTypeDesc(p.module, t[0].typ)
|
||||
var typ = skipTypes(t[0].typ, abstractPtrs)
|
||||
discard getTypeDesc(p.module, t.firstSon.typ)
|
||||
var typ = skipTypes(t.firstSon.typ, abstractPtrs)
|
||||
case p.config.exc
|
||||
of excCpp:
|
||||
blockLeaveActions(p, howManyTrys = 0, howManyExcepts = p.inExceptBlockLen)
|
||||
@@ -913,7 +912,7 @@ template genCaseGenericBranch(p: BProc, b: PNode, e: TLoc, labl: TLabel,
|
||||
for i in 0..<b.len - 1:
|
||||
let rlabel {.inject.} = labl
|
||||
if b[i].kind == nkRange:
|
||||
x = initLocExpr(p, b[i][0])
|
||||
x = initLocExpr(p, b[i].firstSon)
|
||||
y = initLocExpr(p, b[i][1])
|
||||
let ra {.inject.} = rdCharLoc(e)
|
||||
let rb {.inject.} = rdCharLoc(x)
|
||||
@@ -936,7 +935,7 @@ proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc,
|
||||
exprBlock(p, t[i][^1], d)
|
||||
p.s(cpsStmts).addGoto(lend)
|
||||
else:
|
||||
exprBlock(p, t[i][0], d)
|
||||
exprBlock(p, t[i].firstSon, d)
|
||||
result = lend
|
||||
|
||||
template genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc,
|
||||
@@ -964,7 +963,7 @@ template genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc,
|
||||
|
||||
template genCaseGeneric(p: BProc, t: PNode, d: var TLoc,
|
||||
rangeFormat, eqFormat: untyped) =
|
||||
var a: TLoc = initLocExpr(p, t[0])
|
||||
var a: TLoc = initLocExpr(p, t.firstSon)
|
||||
var lend = genIfForCaseUntil(p, t, d, t.len-1, a, rangeFormat, eqFormat)
|
||||
fixLabel(p, lend)
|
||||
|
||||
@@ -999,7 +998,7 @@ proc genStringCase(p: BProc, t: PNode, stringKind: TTypeKind, d: var TLoc) =
|
||||
var bitMask = math.nextPowerOfTwo(strings) - 1
|
||||
var branches: seq[Builder]
|
||||
newSeq(branches, bitMask + 1)
|
||||
var a: TLoc = initLocExpr(p, t[0]) # first pass: generate ifs+goto:
|
||||
var a: TLoc = initLocExpr(p, t.firstSon) # first pass: generate ifs+goto:
|
||||
var labId = p.labels
|
||||
for i in 1..<t.len:
|
||||
inc(p.labels)
|
||||
@@ -1044,7 +1043,7 @@ proc branchHasTooBigRange(b: PNode): bool =
|
||||
for it in b:
|
||||
# last son is block
|
||||
if (it.kind == nkRange) and
|
||||
it[1].intVal - it[0].intVal > RangeExpandLimit:
|
||||
it[1].intVal - it.firstSon.intVal > RangeExpandLimit:
|
||||
return true
|
||||
|
||||
proc ifSwitchSplitPoint(p: BProc, n: PNode): int =
|
||||
@@ -1064,11 +1063,11 @@ proc genCaseRange(p: BProc, branch: PNode, info: var SwitchCaseBuilder) =
|
||||
if hasSwitchRange in CC[p.config.cCompiler].props:
|
||||
var litA = newBuilder("")
|
||||
var litB = newBuilder("")
|
||||
genLiteral(p, branch[j][0], litA)
|
||||
genLiteral(p, branch[j].firstSon, litA)
|
||||
genLiteral(p, branch[j][1], litB)
|
||||
p.s(cpsStmts).addCaseRange(info, extract(litA), extract(litB))
|
||||
else:
|
||||
var v = copyNode(branch[j][0])
|
||||
var v = copyNode(branch[j].firstSon)
|
||||
while v.intVal <= branch[j][1].intVal:
|
||||
var litA = newBuilder("")
|
||||
genLiteral(p, v, litA)
|
||||
@@ -1084,7 +1083,7 @@ proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) =
|
||||
var splitPoint = ifSwitchSplitPoint(p, n)
|
||||
|
||||
# generate if part (might be empty):
|
||||
var a: TLoc = initLocExpr(p, n[0])
|
||||
var a: TLoc = initLocExpr(p, n.firstSon)
|
||||
var lend: TLabel = ""
|
||||
if splitPoint > 0:
|
||||
lend = genIfForCaseUntil(p, n, d, splitPoint, a):
|
||||
@@ -1130,7 +1129,7 @@ proc genCase(p: BProc, t: PNode, d: var TLoc) =
|
||||
genLineDir(p, t)
|
||||
if not isEmptyType(t.typ) and d.k == locNone:
|
||||
d = getTemp(p, t.typ)
|
||||
case skipTypes(t[0].typ, abstractVarRange).kind
|
||||
case skipTypes(t.firstSon.typ, abstractVarRange).kind
|
||||
of tyString:
|
||||
genStringCase(p, t, tyString, d)
|
||||
of tyCstring:
|
||||
@@ -1146,7 +1145,7 @@ proc genCase(p: BProc, t: PNode, d: var TLoc) =
|
||||
removeSinglePar(cOp(Equal, ra, rb))):
|
||||
p.s(cpsStmts).addGoto(rlabel)
|
||||
else:
|
||||
if t[0].kind == nkSym and sfGoto in t[0].sym.flags:
|
||||
if t.firstSon.kind == nkSym and sfGoto in t.firstSon.sym.flags:
|
||||
genGotoForCase(p, t)
|
||||
else:
|
||||
genOrdinalCase(p, t, d)
|
||||
@@ -1203,12 +1202,12 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
|
||||
if t.kind == nkHiddenTryStmt:
|
||||
lineCg(p, cpsStmts, "try {$n", [])
|
||||
expr(p, t[0], d)
|
||||
expr(p, t.firstSon, d)
|
||||
lineCg(p, cpsStmts, "}$n", [])
|
||||
else:
|
||||
startBlockWith(p):
|
||||
p.s(cpsStmts).add("try {\n")
|
||||
expr(p, t[0], d)
|
||||
expr(p, t.firstSon, d)
|
||||
endBlockWith(p):
|
||||
p.s(cpsStmts).add("}\n")
|
||||
|
||||
@@ -1238,7 +1237,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
scope = initScope(p.s(cpsStmts))
|
||||
# we handled the error:
|
||||
linefmt(p, cpsStmts, "T$1_ = nullptr;$n", [etmp])
|
||||
expr(p, t[i][0], d)
|
||||
expr(p, t[i].firstSon, d)
|
||||
linefmt(p, cpsStmts, "#popCurrentException();$n", [])
|
||||
endBlockWith(p):
|
||||
if hasIf:
|
||||
@@ -1311,7 +1310,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
# general except section:
|
||||
startBlockWith(p):
|
||||
p.s(cpsStmts).add("catch (...) {\n")
|
||||
genExceptBranchBody(t[i][0])
|
||||
genExceptBranchBody(t[i].firstSon)
|
||||
endBlockWith(p):
|
||||
p.s(cpsStmts).add("}\n")
|
||||
catchAllPresent = true
|
||||
@@ -1351,7 +1350,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
|
||||
|
||||
var scope: ScopeBuilder
|
||||
startSimpleBlock(p, scope)
|
||||
genStmts(p, t[^1][0])
|
||||
genStmts(p, t[^1].firstSon)
|
||||
linefmt(p, cpsStmts, "if (T$1_) std::rethrow_exception(T$1_);$n", [etmp])
|
||||
endSimpleBlock(p, scope)
|
||||
|
||||
@@ -1389,7 +1388,7 @@ proc genTryCppOld(p: BProc, t: PNode, d: var TLoc) =
|
||||
p.nestedTryStmts.add((fin, false, t.kind == nkHiddenTryStmt, 0.Natural))
|
||||
startBlockWith(p):
|
||||
p.s(cpsStmts).add("try {\n")
|
||||
expr(p, t[0], d)
|
||||
expr(p, t.firstSon, d)
|
||||
endBlockWith(p):
|
||||
p.s(cpsStmts).add("}\n")
|
||||
|
||||
@@ -1407,7 +1406,7 @@ proc genTryCppOld(p: BProc, t: PNode, d: var TLoc) =
|
||||
catchAllPresent = true
|
||||
startBlockWith(p):
|
||||
p.s(cpsStmts).add("catch (...) {\n")
|
||||
genExceptBranchBody(t[i][0])
|
||||
genExceptBranchBody(t[i].firstSon)
|
||||
endBlockWith(p):
|
||||
p.s(cpsStmts).add("}\n")
|
||||
else:
|
||||
@@ -1434,17 +1433,17 @@ proc genTryCppOld(p: BProc, t: PNode, d: var TLoc) =
|
||||
# finally requires catch all presence
|
||||
startBlockWith(p):
|
||||
p.s(cpsStmts).add("catch (...) {\n")
|
||||
genStmts(p, t[^1][0])
|
||||
genStmts(p, t[^1].firstSon)
|
||||
line(p, cpsStmts, "throw;\n")
|
||||
endBlockWith(p):
|
||||
p.s(cpsStmts).add("}\n")
|
||||
|
||||
genSimpleBlock(p, t[^1][0])
|
||||
genSimpleBlock(p, t[^1].firstSon)
|
||||
|
||||
proc bodyCanRaise(p: BProc; n: PNode): bool =
|
||||
case n.kind
|
||||
of nkCallKinds:
|
||||
result = canRaiseDisp(p, n[0])
|
||||
result = canRaiseDisp(p, n.firstSon)
|
||||
if not result:
|
||||
# also check the arguments:
|
||||
for i in 1 ..< n.len:
|
||||
@@ -1472,7 +1471,7 @@ proc genTryGoto(p: BProc; t: PNode; d: var TLoc) =
|
||||
if not isEmptyType(t.typ) and d.k == locNone:
|
||||
d = getTemp(p, t.typ)
|
||||
|
||||
expr(p, t[0], d)
|
||||
expr(p, t.firstSon, d)
|
||||
|
||||
var ifStmt = default(IfBuilder)
|
||||
var scope = default(ScopeBuilder)
|
||||
@@ -1511,7 +1510,7 @@ proc genTryGoto(p: BProc; t: PNode; d: var TLoc) =
|
||||
innerScope = initScope(p.s(cpsStmts))
|
||||
# we handled the exception, remember this:
|
||||
p.s(cpsStmts).addAssignment(cDeref("nimErr_"), NimFalse)
|
||||
expr(p, t[i][0], d)
|
||||
expr(p, t[i].firstSon, d)
|
||||
else:
|
||||
if not innerIsIf:
|
||||
innerIsIf = true
|
||||
@@ -1570,16 +1569,16 @@ proc genTryGoto(p: BProc; t: PNode; d: var TLoc) =
|
||||
if i < t.len and t[i].kind == nkFinally:
|
||||
var finallyScope: ScopeBuilder
|
||||
startSimpleBlock(p, finallyScope)
|
||||
if not bodyCanRaise(p, t[i][0]):
|
||||
if not bodyCanRaise(p, t[i].firstSon):
|
||||
# this is an important optimization; most destroy blocks are detected not to raise an
|
||||
# exception and so we help the C optimizer by not mutating nimErr_ pointlessly:
|
||||
genStmts(p, t[i][0])
|
||||
genStmts(p, t[i].firstSon)
|
||||
else:
|
||||
# pretend we did handle the error for the safe execution of the 'finally' section:
|
||||
p.procSec(cpsLocals).addVar(kind = Local, name = "oldNimErrFin" & $lab & "_", typ = NimBool)
|
||||
p.s(cpsStmts).addAssignment("oldNimErrFin" & $lab & "_", cDeref("nimErr_"))
|
||||
p.s(cpsStmts).addAssignment(cDeref("nimErr_"), NimFalse)
|
||||
genStmts(p, t[i][0])
|
||||
genStmts(p, t[i].firstSon)
|
||||
# this is correct for all these cases:
|
||||
# 1. finally is run during ordinary control flow
|
||||
# 2. finally is run after 'except' block handling: these however set the
|
||||
@@ -1672,7 +1671,7 @@ proc genTrySetjmp(p: BProc, t: PNode, d: var TLoc) =
|
||||
cOp(Equal, dotField(safePoint, "status"), cIntValue(0))))
|
||||
let fin = if t[^1].kind == nkFinally: t[^1] else: nil
|
||||
p.nestedTryStmts.add((fin, quirkyExceptions, t.kind == nkHiddenTryStmt, 0.Natural))
|
||||
expr(p, t[0], d)
|
||||
expr(p, t.firstSon, d)
|
||||
var quirkyIf = default(IfBuilder)
|
||||
var quirkyScope = default(ScopeBuilder)
|
||||
var isScope = false
|
||||
@@ -1709,7 +1708,7 @@ proc genTrySetjmp(p: BProc, t: PNode, d: var TLoc) =
|
||||
scope = initScope(p.s(cpsStmts))
|
||||
if not quirkyExceptions:
|
||||
p.s(cpsStmts).addFieldAssignment(safePoint, "status", cIntValue(0))
|
||||
expr(p, t[i][0], d)
|
||||
expr(p, t[i].firstSon, d)
|
||||
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "popCurrentException"))
|
||||
endBlockWith(p):
|
||||
if exceptIfInited:
|
||||
@@ -1772,7 +1771,7 @@ proc genTrySetjmp(p: BProc, t: PNode, d: var TLoc) =
|
||||
p.finallySafePoints.add(safePoint)
|
||||
var finallyScope: ScopeBuilder
|
||||
startSimpleBlock(p, finallyScope)
|
||||
genStmts(p, t[i][0])
|
||||
genStmts(p, t[i].firstSon)
|
||||
# pretend we handled the exception in a 'finally' so that we don't
|
||||
# re-raise the unhandled one but instead keep the old one (it was
|
||||
# not popped either):
|
||||
@@ -1844,7 +1843,7 @@ proc genAsmStmt(p: BProc, t: PNode) =
|
||||
var s = newRopeAppender()
|
||||
|
||||
var asmSyntax = ""
|
||||
if (let p = t[0]; p.kind == nkPragma):
|
||||
if (let p = t.firstSon; p.kind == nkPragma):
|
||||
for i in p:
|
||||
if whichPragma(i) == wAsmSyntax:
|
||||
asmSyntax = i[1].strVal
|
||||
@@ -1870,8 +1869,8 @@ proc genAsmStmt(p: BProc, t: PNode) =
|
||||
|
||||
proc determineSection(n: PNode): TCFileSection =
|
||||
result = cfsProcHeaders
|
||||
if n.len >= 1 and n[0].kind in {nkStrLit..nkTripleStrLit}:
|
||||
let sec = n[0].strVal
|
||||
if n.len >= 1 and n.firstSon.kind in {nkStrLit..nkTripleStrLit}:
|
||||
let sec = n.firstSon.strVal
|
||||
if sec.startsWith("/*TYPESECTION*/"): result = cfsForwardTypes # TODO WORKAROUND
|
||||
elif sec.startsWith("/*VARSECTION*/"): result = cfsVars
|
||||
elif sec.startsWith("/*INCLUDESECTION*/"): result = cfsHeaders
|
||||
@@ -1889,8 +1888,7 @@ proc genEmit(p: BProc, t: PNode) =
|
||||
line(p, cpsStmts, s)
|
||||
|
||||
proc genPragma(p: BProc, n: PNode) =
|
||||
for i in 0..<n.len:
|
||||
let it = n[i]
|
||||
for i, it in isons(n):
|
||||
case whichPragma(it)
|
||||
of wEmit: genEmit(p, it)
|
||||
of wPush:
|
||||
@@ -1937,35 +1935,35 @@ when false:
|
||||
expr(p, call, d)
|
||||
|
||||
proc asgnFieldDiscriminant(p: BProc, e: PNode) =
|
||||
var dotExpr = e[0]
|
||||
if dotExpr.kind == nkCheckedFieldExpr: dotExpr = dotExpr[0]
|
||||
var a = initLocExpr(p, e[0])
|
||||
var dotExpr = e.firstSon
|
||||
if dotExpr.kind == nkCheckedFieldExpr: dotExpr = dotExpr.firstSon
|
||||
var a = initLocExpr(p, e.firstSon)
|
||||
var tmp: TLoc = getTemp(p, a.t)
|
||||
expr(p, e[1], tmp)
|
||||
if p.inUncheckedAssignSection == 0:
|
||||
let field = dotExpr[1].sym
|
||||
genDiscriminantCheck(p, a, tmp, dotExpr[0].typ, field)
|
||||
genDiscriminantCheck(p, a, tmp, dotExpr.firstSon.typ, field)
|
||||
message(p.config, e.info, warnCaseTransition)
|
||||
genAssignment(p, a, tmp, {})
|
||||
|
||||
proc genAsgn(p: BProc, e: PNode, fastAsgn: bool) =
|
||||
if e[0].kind == nkSym and sfGoto in e[0].sym.flags:
|
||||
if e.firstSon.kind == nkSym and sfGoto in e.firstSon.sym.flags:
|
||||
genLineDir(p, e)
|
||||
genGotoVar(p, e[1])
|
||||
elif optFieldCheck in p.options and isDiscriminantField(e[0]):
|
||||
elif optFieldCheck in p.options and isDiscriminantField(e.firstSon):
|
||||
genLineDir(p, e)
|
||||
asgnFieldDiscriminant(p, e)
|
||||
elif p.config.usesSso() and e[0].kind == nkBracketExpr and
|
||||
e[0][0].typ.skipTypes(abstractVar).kind == tyString:
|
||||
elif p.config.usesSso() and e.firstSon.kind == nkBracketExpr and
|
||||
e.firstSon.firstSon.typ.skipTypes(abstractVar).kind == tyString:
|
||||
# nimsso: s[i] = c → nimStrPutV3(&s, i, c) (handles COW internally)
|
||||
genLineDir(p, e)
|
||||
var base = initLocExpr(p, e[0][0])
|
||||
var idx = initLocExpr(p, e[0][1])
|
||||
var base = initLocExpr(p, e.firstSon.firstSon)
|
||||
var idx = initLocExpr(p, e.firstSon[1])
|
||||
var rhs = initLocExpr(p, e[1])
|
||||
p.s(cpsStmts).addCallStmt(cgsymValue(p.module, "nimStrPutV3"),
|
||||
byRefLoc(p, base), rdLoc(idx), rdCharLoc(rhs))
|
||||
else:
|
||||
let le = e[0]
|
||||
let le = e.firstSon
|
||||
let ri = e[1]
|
||||
var a: TLoc = initLoc(locNone, le, OnUnknown)
|
||||
discard getTypeDesc(p.module, le.typ.skipTypes(skipPtrs), dkVar)
|
||||
|
||||
@@ -767,11 +767,11 @@ proc genRecordFieldsAux(m: BModule; n: PNode,
|
||||
check: var IntSet; result: var Builder; unionPrefix = "") =
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
for i in 0..<n.len:
|
||||
genRecordFieldsAux(m, n[i], rectype, check, result, unionPrefix)
|
||||
for ni in n.sons:
|
||||
genRecordFieldsAux(m, ni, rectype, check, result, unionPrefix)
|
||||
of nkRecCase:
|
||||
if n[0].kind != nkSym: internalError(m.config, n.info, "genRecordFieldsAux")
|
||||
genRecordFieldsAux(m, n[0], rectype, check, result, unionPrefix)
|
||||
if n.firstSon.kind != nkSym: internalError(m.config, n.info, "genRecordFieldsAux")
|
||||
genRecordFieldsAux(m, n.firstSon, rectype, check, result, unionPrefix)
|
||||
# prefix mangled name with "_U" to avoid clashes with other field names,
|
||||
# since identifiers are not allowed to start with '_'
|
||||
var unionBody = newBuilder("")
|
||||
@@ -780,7 +780,7 @@ proc genRecordFieldsAux(m: BModule; n: PNode,
|
||||
of nkOfBranch, nkElse:
|
||||
let k = lastSon(n[i])
|
||||
if k.kind != nkSym:
|
||||
let structName = "_" & mangleRecFieldName(m, n[0].sym) & "_" & $i
|
||||
let structName = "_" & mangleRecFieldName(m, n.firstSon.sym) & "_" & $i
|
||||
var a = newBuilder("")
|
||||
genRecordFieldsAux(m, k, rectype, check, a, unionPrefix & $structName & ".")
|
||||
if a.buf.len != 0:
|
||||
@@ -1075,9 +1075,9 @@ proc getTypeDescAux(m: BModule; origTyp: PType, check: var IntSet; kind: TypeDes
|
||||
let owner = hashOwner(t.sym)
|
||||
if not gDebugInfo.hasEnum(t.sym.name.s, t.sym.info.line, owner):
|
||||
var vals: seq[(string, int)] = @[]
|
||||
for i in 0..<t.n.len:
|
||||
assert(t.n[i].kind == nkSym)
|
||||
let field = t.n[i].sym
|
||||
for son in t.n.sons:
|
||||
assert(son.kind == nkSym)
|
||||
let field = son.sym
|
||||
vals.add((field.name.s, field.position.int))
|
||||
gDebugInfo.registerEnum(EnumDesc(size: size, owner: owner, id: t.sym.id,
|
||||
name: t.sym.name.s, values: vals))
|
||||
@@ -1497,14 +1497,14 @@ proc genObjectFields(m: BModule; typ, origType: PType, n: PNode, expr: Rope;
|
||||
case n.kind
|
||||
of nkRecList:
|
||||
if n.len == 1:
|
||||
genObjectFields(m, typ, origType, n[0], expr, info)
|
||||
genObjectFields(m, typ, origType, n.firstSon, expr, info)
|
||||
elif n.len > 0:
|
||||
var tmp = getTempName(m) & "_" & $n.len
|
||||
genTNimNodeArray(m, tmp, n.len)
|
||||
for i in 0..<n.len:
|
||||
for i, ni in isons(n):
|
||||
var tmp2 = getNimNode(m)
|
||||
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, cIntValue(i), cAddr(tmp2))
|
||||
genObjectFields(m, typ, origType, n[i], tmp2, info)
|
||||
genObjectFields(m, typ, origType, ni, tmp2, info)
|
||||
m.s[cfsTypeInit3].addFieldAssignment(expr, "len", n.len)
|
||||
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind", 2)
|
||||
m.s[cfsTypeInit3].addFieldAssignment(expr, "sons",
|
||||
@@ -1513,8 +1513,8 @@ proc genObjectFields(m: BModule; typ, origType: PType, n: PNode, expr: Rope;
|
||||
m.s[cfsTypeInit3].addFieldAssignment(expr, "len", n.len)
|
||||
m.s[cfsTypeInit3].addFieldAssignment(expr, "kind", 2)
|
||||
of nkRecCase:
|
||||
assert(n[0].kind == nkSym)
|
||||
var field = n[0].sym
|
||||
assert(n.firstSon.kind == nkSym)
|
||||
var field = n.firstSon.sym
|
||||
var tmp = discriminatorTableName(m, typ, field)
|
||||
var L = lengthOrd(m.config, field.typ)
|
||||
assert L > 0
|
||||
@@ -1558,7 +1558,7 @@ proc genObjectFields(m: BModule; typ, origType: PType, n: PNode, expr: Rope;
|
||||
internalError(m.config, b.info, "genObjectFields; nkOfBranch broken")
|
||||
for j in 0..<b.len - 1:
|
||||
if b[j].kind == nkRange:
|
||||
var x = toInt(getOrdValue(b[j][0]))
|
||||
var x = toInt(getOrdValue(b[j].firstSon))
|
||||
var y = toInt(getOrdValue(b[j][1]))
|
||||
while x <= y:
|
||||
m.s[cfsTypeInit3].addSubscriptAssignment(tmp, cIntValue(x), cAddr(tmp2))
|
||||
@@ -1649,9 +1649,9 @@ proc genEnumInfo(m: BModule; typ: PType, name: Rope; info: TLineInfo) =
|
||||
var firstNimNode = m.typeNodes
|
||||
var hasHoles = false
|
||||
enumNames.addStructInitializer(enumNamesInit, kind = siArray):
|
||||
for i in 0..<typ.n.len:
|
||||
assert(typ.n[i].kind == nkSym)
|
||||
var field = typ.n[i].sym
|
||||
for i, son in isons(typ.n):
|
||||
assert(son.kind == nkSym)
|
||||
var field = son.sym
|
||||
var elemNode = getNimNode(m)
|
||||
enumNames.addField(enumNamesInit, name = ""):
|
||||
if field.ast == nil:
|
||||
@@ -2268,7 +2268,7 @@ proc genTypeInfo*(config: ConfigRef, m: BModule; t: PType; info: TLineInfo): Rop
|
||||
proc retrieveSym(n: PNode): PSym =
|
||||
case n.kind
|
||||
of nkPostfix: result = retrieveSym(n[1])
|
||||
of nkPragmaExpr, nkTypeDef: result = retrieveSym(n[0])
|
||||
of nkPragmaExpr, nkTypeDef: result = retrieveSym(n.firstSon)
|
||||
of nkSym: result = n.sym
|
||||
else: result = nil
|
||||
|
||||
|
||||
@@ -955,12 +955,12 @@ proc initLocExpr(p: BProc, e: PNode, flags: TLocFlags = {}): TLoc =
|
||||
|
||||
proc initLocExprSingleUse(p: BProc, e: PNode): TLoc =
|
||||
result = initLoc(locNone, e, OnUnknown)
|
||||
if e.kind in nkCallKinds and (e[0].kind != nkSym or e[0].sym.magic == mNone):
|
||||
if e.kind in nkCallKinds and (e.firstSon.kind != nkSym or e.firstSon.sym.magic == mNone):
|
||||
# We cannot check for tfNoSideEffect here because of mutable parameters.
|
||||
discard "bug #8202; enforce evaluation order for nested calls for C++ too"
|
||||
# We may need to consider that 'f(g())' cannot be rewritten to 'tmp = g(); f(tmp)'
|
||||
# if 'tmp' lacks a move/assignment operator.
|
||||
if e[0].kind == nkSym and sfCompileToCpp in e[0].sym.flags:
|
||||
if e.firstSon.kind == nkSym and sfCompileToCpp in e.firstSon.sym.flags:
|
||||
result.flags.incl lfSingleUse
|
||||
else:
|
||||
result.flags.incl lfSingleUse
|
||||
@@ -1104,7 +1104,7 @@ proc symInDynamicLib(m: BModule, sym: PSym) =
|
||||
inc(m.labels, 2)
|
||||
if isCall:
|
||||
let n = lib.path
|
||||
var a: TLoc = initLocExpr(m.initProc, n[0])
|
||||
var a: TLoc = initLocExpr(m.initProc, n.firstSon)
|
||||
let callee = rdLoc(a)
|
||||
var params: seq[Snippet] = @[]
|
||||
for i in 1..<n.len-1:
|
||||
@@ -1260,15 +1260,15 @@ proc containsResult(n: PNode): bool =
|
||||
of succ(nkEmpty)..pred(nkSym), succ(nkSym)..nkNilLit, harmless:
|
||||
discard
|
||||
of nkReturnStmt:
|
||||
for i in 0..<n.len:
|
||||
if containsResult(n[i]): return true
|
||||
result = n.len > 0 and n[0].kind == nkEmpty
|
||||
for ni in n.sons:
|
||||
if containsResult(ni): return true
|
||||
result = n.len > 0 and n.firstSon.kind == nkEmpty
|
||||
of nkSym:
|
||||
if n.sym.kind == skResult:
|
||||
result = true
|
||||
else:
|
||||
for i in 0..<n.len:
|
||||
if containsResult(n[i]): return true
|
||||
for ni in n.sons:
|
||||
if containsResult(ni): return true
|
||||
|
||||
proc easyResultAsgn(n: PNode): PNode =
|
||||
result = nil
|
||||
@@ -1278,12 +1278,12 @@ proc easyResultAsgn(n: PNode): PNode =
|
||||
while i < n.len and n[i].kind in harmless: inc i
|
||||
if i < n.len: result = easyResultAsgn(n[i])
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
if n[0].kind == nkSym and n[0].sym.kind == skResult and not containsResult(n[1]):
|
||||
if n.firstSon.kind == nkSym and n.firstSon.sym.kind == skResult and not containsResult(n[1]):
|
||||
incl n.flags, nfPreventCg
|
||||
return n[1]
|
||||
of nkReturnStmt:
|
||||
if n.len > 0:
|
||||
result = easyResultAsgn(n[0])
|
||||
result = easyResultAsgn(n.firstSon)
|
||||
if result != nil: incl n.flags, nfPreventCg
|
||||
else: discard
|
||||
|
||||
@@ -1320,7 +1320,7 @@ proc allPathsAsgnResult(p: BProc; n: PNode): InitResultEnum =
|
||||
result = allPathsAsgnResult(p, it)
|
||||
if result != Unknown: return result
|
||||
of nkAsgn, nkFastAsgn, nkSinkAsgn:
|
||||
if n[0].kind == nkSym and n[0].sym.kind == skResult:
|
||||
if n.firstSon.kind == nkSym and n.firstSon.sym.kind == skResult:
|
||||
if not containsResult(n[1]):
|
||||
if allPathsAsgnResult(p, n[1]) == InitRequired:
|
||||
result = InitRequired
|
||||
@@ -1333,19 +1333,19 @@ proc allPathsAsgnResult(p: BProc; n: PNode): InitResultEnum =
|
||||
result = allPathsAsgnResult(p, n[1])
|
||||
of nkReturnStmt:
|
||||
if n.len > 0:
|
||||
if n[0].kind == nkEmpty and result != InitSkippable:
|
||||
if n.firstSon.kind == nkEmpty and result != InitSkippable:
|
||||
# This is a bare `return` statement, if `result` was not initialized
|
||||
# anywhere else (or if we're not sure about this) let's require it to be
|
||||
# initialized. This avoids cases like #9286 where this heuristic lead to
|
||||
# wrong code being generated.
|
||||
result = InitRequired
|
||||
else: result = allPathsAsgnResult(p, n[0])
|
||||
else: result = allPathsAsgnResult(p, n.firstSon)
|
||||
of nkIfStmt, nkIfExpr:
|
||||
var exhaustive = false
|
||||
result = InitSkippable
|
||||
for it in n:
|
||||
# Every condition must not use 'result':
|
||||
if it.len == 2 and containsResult(it[0]):
|
||||
if it.len == 2 and containsResult(it.firstSon):
|
||||
return InitRequired
|
||||
if it.len == 1: exhaustive = true
|
||||
allPathsInBranch(it.lastSon)
|
||||
@@ -1353,9 +1353,9 @@ proc allPathsAsgnResult(p: BProc; n: PNode): InitResultEnum =
|
||||
# in some way, say Unknown.
|
||||
if not exhaustive: result = Unknown
|
||||
of nkCaseStmt:
|
||||
if containsResult(n[0]): return InitRequired
|
||||
if containsResult(n.firstSon): return InitRequired
|
||||
result = InitSkippable
|
||||
var exhaustive = skipTypes(n[0].typ,
|
||||
var exhaustive = skipTypes(n.firstSon.typ,
|
||||
abstractVarRange-{tyTypeDesc}).kind notin {tyFloat..tyFloat128, tyString, tyCstring}
|
||||
for i in 1..<n.len:
|
||||
let it = n[i]
|
||||
@@ -1365,7 +1365,7 @@ proc allPathsAsgnResult(p: BProc; n: PNode): InitResultEnum =
|
||||
of nkWhileStmt:
|
||||
# some dubious code can assign the result in the 'while'
|
||||
# condition and that would be fine. Everything else isn't:
|
||||
result = allPathsAsgnResult(p, n[0])
|
||||
result = allPathsAsgnResult(p, n.firstSon)
|
||||
if result == Unknown:
|
||||
result = allPathsAsgnResult(p, n[1])
|
||||
# we cannot assume that the 'while' loop is really executed at least once:
|
||||
@@ -1389,19 +1389,19 @@ proc allPathsAsgnResult(p: BProc; n: PNode): InitResultEnum =
|
||||
# assignment this is not good enough! The only pattern we allow for
|
||||
# is 'finally: result = x'
|
||||
result = InitSkippable
|
||||
allPathsInBranch(n[0])
|
||||
allPathsInBranch(n.firstSon)
|
||||
for i in 1..<n.len:
|
||||
if n[i].kind == nkFinally:
|
||||
result = allPathsAsgnResult(p, n[i].lastSon)
|
||||
else:
|
||||
allPathsInBranch(n[i].lastSon)
|
||||
of nkCallKinds:
|
||||
if canRaiseDisp(p, n[0]) or
|
||||
(n[0].kind == nkSym and sfNoReturn in n[0].sym.flags):
|
||||
if canRaiseDisp(p, n.firstSon) or
|
||||
(n.firstSon.kind == nkSym and sfNoReturn in n.firstSon.sym.flags):
|
||||
# requires initializations when encountering unreachable code
|
||||
result = InitRequired
|
||||
elif n[0].kind == nkSym and
|
||||
n[0].sym.magic in {mUnaryMinusI..mAbsI, mAddI..mPred} and
|
||||
elif n.firstSon.kind == nkSym and
|
||||
n.firstSon.sym.magic in {mUnaryMinusI..mAbsI, mAddI..mPred} and
|
||||
optOverflowCheck in p.config.options:
|
||||
# arithmetic operations may raise exceptions
|
||||
result = InitRequired
|
||||
|
||||
Reference in New Issue
Block a user