mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-09 06:23:25 +00:00
transf and vmgen compile again
This commit is contained in:
@@ -116,7 +116,8 @@ Remarks: Rule 1.2 is not yet implemented because ``sink`` is currently
|
||||
|
||||
import
|
||||
intsets, ast, astalgo, msgs, renderer, magicsys, types, idents, trees,
|
||||
strutils, options, dfa, lowerings, rodread, tables
|
||||
strutils, options, dfa, lowerings, rodread, tables, modulegraphs,
|
||||
configuration
|
||||
|
||||
const
|
||||
InterestingSyms = {skVar, skResult, skLet}
|
||||
@@ -130,6 +131,7 @@ type
|
||||
tmp: PSym
|
||||
destroys, topLevelVars: PNode
|
||||
toDropBit: Table[int, PSym]
|
||||
graph: ModuleGraph
|
||||
|
||||
proc getTemp(c: var Con; typ: PType; info: TLineInfo): PNode =
|
||||
# XXX why are temps fields in an object here?
|
||||
@@ -222,21 +224,21 @@ proc patchHead(s: PSym) =
|
||||
template genOp(opr, opname) =
|
||||
let op = opr
|
||||
if op == nil:
|
||||
globalError(dest.info, "internal error: '" & opname & "' operator not found for type " & typeToString(t))
|
||||
globalError(c.graph.config, dest.info, "internal error: '" & opname & "' operator not found for type " & typeToString(t))
|
||||
elif op.ast[genericParamsPos].kind != nkEmpty:
|
||||
globalError(dest.info, "internal error: '" & opname & "' operator is generic")
|
||||
globalError(c.graph.config, dest.info, "internal error: '" & opname & "' operator is generic")
|
||||
patchHead op
|
||||
result = newTree(nkCall, newSymNode(op), newTree(nkHiddenAddr, dest))
|
||||
|
||||
proc genSink(t: PType; dest: PNode): PNode =
|
||||
proc genSink(c: Con; t: PType; dest: PNode): PNode =
|
||||
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
genOp(if t.sink != nil: t.sink else: t.assignment, "=sink")
|
||||
|
||||
proc genCopy(t: PType; dest: PNode): PNode =
|
||||
proc genCopy(c: Con; t: PType; dest: PNode): PNode =
|
||||
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
genOp(t.assignment, "=")
|
||||
|
||||
proc genDestroy(t: PType; dest: PNode): PNode =
|
||||
proc genDestroy(c: Con; t: PType; dest: PNode): PNode =
|
||||
let t = t.skipTypes({tyGenericInst, tyAlias, tySink})
|
||||
genOp(t.destructor, "=destroy")
|
||||
|
||||
@@ -249,14 +251,14 @@ proc dropBit(c: var Con; s: PSym): PSym =
|
||||
|
||||
proc registerDropBit(c: var Con; s: PSym) =
|
||||
let result = newSym(skTemp, getIdent(s.name.s & "_AliveBit"), c.owner, s.info)
|
||||
result.typ = getSysType(tyBool)
|
||||
result.typ = getSysType(c.graph, s.info, tyBool)
|
||||
let trueVal = newIntTypeNode(nkIntLit, 1, result.typ)
|
||||
c.topLevelVars.add newTree(nkIdentDefs, newSymNode result, emptyNode, trueVal)
|
||||
c.toDropBit[s.id] = result
|
||||
# generate:
|
||||
# if not sinkParam_AliveBit: `=destroy`(sinkParam)
|
||||
c.destroys.add newTree(nkIfStmt,
|
||||
newTree(nkElifBranch, newSymNode result, genDestroy(s.typ, newSymNode s)))
|
||||
newTree(nkElifBranch, newSymNode result, genDestroy(c, s.typ, newSymNode s)))
|
||||
|
||||
proc p(n: PNode; c: var Con): PNode
|
||||
|
||||
@@ -274,36 +276,36 @@ proc destructiveMoveSink(n: PNode; c: var Con): PNode =
|
||||
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
|
||||
let bit = newSymNode dropBit(c, n.sym)
|
||||
if optMoveCheck in c.owner.options:
|
||||
result.add callCodegenProc("chckMove", bit)
|
||||
result.add callCodegenProc(c.graph, "chckMove", bit)
|
||||
result.add newTree(nkAsgn, bit,
|
||||
newIntTypeNode(nkIntLit, 0, getSysType(tyBool)))
|
||||
newIntTypeNode(nkIntLit, 0, getSysType(c.graph, n.info, tyBool)))
|
||||
result.add n
|
||||
|
||||
proc moveOrCopy(dest, ri: PNode; c: var Con): PNode =
|
||||
if ri.kind in constrExprs:
|
||||
result = genSink(ri.typ, dest)
|
||||
result = genSink(c, ri.typ, dest)
|
||||
# watch out and no not transform 'ri' twice if it's a call:
|
||||
let ri2 = copyNode(ri)
|
||||
recurse(ri, ri2)
|
||||
result.add ri2
|
||||
elif ri.kind == nkSym and isHarmlessVar(ri.sym, c):
|
||||
result = genSink(ri.typ, dest)
|
||||
result = genSink(c, ri.typ, dest)
|
||||
result.add p(ri, c)
|
||||
elif ri.kind == nkSym and isSinkParam(ri.sym):
|
||||
result = genSink(ri.typ, dest)
|
||||
result = genSink(c, ri.typ, dest)
|
||||
result.add destructiveMoveSink(ri, c)
|
||||
else:
|
||||
result = genCopy(ri.typ, dest)
|
||||
result = genCopy(c, ri.typ, dest)
|
||||
result.add p(ri, c)
|
||||
|
||||
proc passCopyToSink(n: PNode; c: var Con): PNode =
|
||||
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
|
||||
let tmp = getTemp(c, n.typ, n.info)
|
||||
if hasDestructor(n.typ):
|
||||
var m = genCopy(n.typ, tmp)
|
||||
var m = genCopy(c, n.typ, tmp)
|
||||
m.add p(n, c)
|
||||
result.add m
|
||||
message(n.info, hintPerformance,
|
||||
message(c.graph.config, n.info, hintPerformance,
|
||||
"passing '$1' to a sink parameter introduces an implicit copy; " &
|
||||
"use 'move($1)' to prevent it" % $n)
|
||||
else:
|
||||
@@ -312,7 +314,7 @@ proc passCopyToSink(n: PNode; c: var Con): PNode =
|
||||
|
||||
proc genReset(n: PNode; c: var Con): PNode =
|
||||
result = newNodeI(nkCall, n.info)
|
||||
result.add(newSymNode(createMagic("reset", mReset)))
|
||||
result.add(newSymNode(createMagic(c.graph, "reset", mReset)))
|
||||
# The mReset builtin does not take the address:
|
||||
result.add n
|
||||
|
||||
@@ -345,7 +347,7 @@ proc p(n: PNode; c: var Con): PNode =
|
||||
let L = it.len-1
|
||||
let ri = it[L]
|
||||
if it.kind == nkVarTuple and hasDestructor(ri.typ):
|
||||
let x = lowerTupleUnpacking(it, c.owner)
|
||||
let x = lowerTupleUnpacking(c.graph, it, c.owner)
|
||||
result.add p(x, c)
|
||||
elif it.kind == nkIdentDefs and hasDestructor(it[0].typ):
|
||||
for j in 0..L-2:
|
||||
@@ -354,7 +356,7 @@ proc p(n: PNode; c: var Con): PNode =
|
||||
# move the variable declaration to the top of the frame:
|
||||
c.addTopVar v
|
||||
# make sure it's destroyed at the end of the proc:
|
||||
c.destroys.add genDestroy(v.typ, v)
|
||||
c.destroys.add genDestroy(c, v.typ, v)
|
||||
if ri.kind != nkEmpty:
|
||||
let r = moveOrCopy(v, ri, c)
|
||||
result.add r
|
||||
@@ -400,11 +402,11 @@ proc p(n: PNode; c: var Con): PNode =
|
||||
discard "produce temp creation"
|
||||
result = newNodeIT(nkStmtListExpr, n.info, n.typ)
|
||||
let tmp = getTemp(c, n.typ, n.info)
|
||||
var sinkExpr = genSink(n.typ, tmp)
|
||||
var sinkExpr = genSink(c, n.typ, tmp)
|
||||
sinkExpr.add n
|
||||
result.add sinkExpr
|
||||
result.add tmp
|
||||
c.destroys.add genDestroy(n.typ, tmp)
|
||||
c.destroys.add genDestroy(c, n.typ, tmp)
|
||||
else:
|
||||
result = n
|
||||
of nkAsgn, nkFastAsgn:
|
||||
@@ -420,17 +422,18 @@ proc p(n: PNode; c: var Con): PNode =
|
||||
result = copyNode(n)
|
||||
recurse(n, result)
|
||||
|
||||
proc injectDestructorCalls*(owner: PSym; n: PNode): PNode =
|
||||
proc injectDestructorCalls*(g: ModuleGraph; owner: PSym; n: PNode): PNode =
|
||||
when defined(nimDebugDestroys):
|
||||
echo "injecting into ", n
|
||||
var c: Con
|
||||
c.owner = owner
|
||||
c.tmp = newSym(skTemp, getIdent":d", owner, n.info)
|
||||
c.tmpObj = createObj(owner, n.info)
|
||||
c.tmpObj = createObj(g, owner, n.info)
|
||||
c.tmp.typ = c.tmpObj
|
||||
c.destroys = newNodeI(nkStmtList, n.info)
|
||||
c.topLevelVars = newNodeI(nkVarSection, n.info)
|
||||
c.toDropBit = initTable[int, PSym]()
|
||||
c.graph = g
|
||||
let cfg = constructCfg(owner, n)
|
||||
shallowCopy(c.g, cfg)
|
||||
c.jumpTargets = initIntSet()
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
## "A Graph–Free Approach to Data–Flow Analysis" by Markus Mohnen.
|
||||
## https://link.springer.com/content/pdf/10.1007/3-540-45937-5_6.pdf
|
||||
|
||||
import ast, astalgo, types, intsets, tables, msgs
|
||||
import ast, astalgo, types, intsets, tables, msgs, options
|
||||
|
||||
type
|
||||
InstrKind* = enum
|
||||
@@ -160,7 +160,7 @@ proc genBreak(c: var Con; n: PNode) =
|
||||
if c.blocks[i].label == n.sons[0].sym:
|
||||
c.blocks[i].fixups.add L1
|
||||
return
|
||||
globalError(n.info, errGenerated, "VM problem: cannot find 'break' target")
|
||||
#globalError(n.info, "VM problem: cannot find 'break' target")
|
||||
else:
|
||||
c.blocks[c.blocks.high].fixups.add L1
|
||||
|
||||
@@ -334,7 +334,7 @@ proc gen(c: var Con; n: PNode) =
|
||||
of nkVarSection, nkLetSection: genVarSection(c, n)
|
||||
else: discard
|
||||
|
||||
proc dfa(code: seq[Instr]) =
|
||||
proc dfa(code: seq[Instr]; conf: ConfigRef) =
|
||||
var u = newSeq[IntSet](code.len) # usages
|
||||
var d = newSeq[IntSet](code.len) # defs
|
||||
var c = newSeq[IntSet](code.len) # consumed
|
||||
@@ -426,17 +426,17 @@ proc dfa(code: seq[Instr]) =
|
||||
of use, useWithinCall:
|
||||
let s = code[i].sym
|
||||
if s.id notin d[i]:
|
||||
localError(code[i].n.info, "usage of uninitialized variable: " & s.name.s)
|
||||
localError(conf, code[i].n.info, "usage of uninitialized variable: " & s.name.s)
|
||||
if s.id in c[i]:
|
||||
localError(code[i].n.info, "usage of an already consumed variable: " & s.name.s)
|
||||
localError(conf, code[i].n.info, "usage of an already consumed variable: " & s.name.s)
|
||||
|
||||
else: discard
|
||||
|
||||
proc dataflowAnalysis*(s: PSym; body: PNode) =
|
||||
proc dataflowAnalysis*(s: PSym; body: PNode; conf: ConfigRef) =
|
||||
var c = Con(code: @[], blocks: @[])
|
||||
gen(c, body)
|
||||
when defined(useDfa) and defined(debugDfa): echoCfg(c.code)
|
||||
dfa(c.code)
|
||||
dfa(c.code, conf)
|
||||
|
||||
proc constructCfg*(s: PSym; body: PNode): ControlFlowGraph =
|
||||
## constructs a control flow graph for ``body``.
|
||||
|
||||
@@ -21,11 +21,11 @@ proc readOutput(p: Process): (string, int) =
|
||||
result[0].setLen(result[0].len - "\n".len)
|
||||
result[1] = p.waitForExit
|
||||
|
||||
proc opGorge*(cmd, input, cache: string, info: TLineInfo): (string, int) =
|
||||
proc opGorge*(cmd, input, cache: string, info: TLineInfo; conf: ConfigRef): (string, int) =
|
||||
let workingDir = parentDir(info.toFullPath)
|
||||
if cache.len > 0:# and optForceFullMake notin gGlobalOptions:
|
||||
let h = secureHash(cmd & "\t" & input & "\t" & cache)
|
||||
let filename = options.toGeneratedFile("gorge_" & $h, "txt")
|
||||
let filename = options.toGeneratedFile(conf, "gorge_" & $h, "txt")
|
||||
var f: File
|
||||
if open(f, filename):
|
||||
result = (f.readAll, 0)
|
||||
|
||||
@@ -52,17 +52,17 @@ proc lookupParam(params, dest: PNode): PSym =
|
||||
if params[i].kind == nkSym and params[i].sym.name.id == dest.ident.id:
|
||||
return params[i].sym
|
||||
|
||||
proc liftLocalsIfRequested*(prc: PSym; n: PNode): PNode =
|
||||
proc liftLocalsIfRequested*(prc: PSym; n: PNode; conf: ConfigRef): PNode =
|
||||
let liftDest = getPragmaVal(prc.ast, wLiftLocals)
|
||||
if liftDest == nil: return n
|
||||
let partialParam = lookupParam(prc.typ.n, liftDest)
|
||||
if partialParam.isNil:
|
||||
localError(liftDest.info, "'$1' is not a parameter of '$2'" %
|
||||
localError(conf, liftDest.info, "'$1' is not a parameter of '$2'" %
|
||||
[$liftDest, prc.name.s])
|
||||
return n
|
||||
let objType = partialParam.typ.skipTypes(abstractPtrs)
|
||||
if objType.kind != tyObject or tfPartial notin objType.flags:
|
||||
localError(liftDest.info, "parameter '$1' is not a pointer to a partial object" % $liftDest)
|
||||
localError(conf, liftDest.info, "parameter '$1' is not a pointer to a partial object" % $liftDest)
|
||||
return n
|
||||
var c = Ctx(partialParam: partialParam, objType: objType)
|
||||
let w = newTree(nkStmtList, n)
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
import
|
||||
intsets, strutils, options, ast, astalgo, trees, treetab, msgs, os,
|
||||
idents, renderer, types, passes, semfold, magicsys, cgmeth, rodread,
|
||||
lambdalifting, sempass2, lowerings, lookups, destroyer, liftlocals
|
||||
lambdalifting, sempass2, lowerings, lookups, destroyer, liftlocals,
|
||||
modulegraphs
|
||||
|
||||
type
|
||||
PTransNode* = distinct PNode
|
||||
@@ -44,6 +45,7 @@ type
|
||||
nestedProcs: int # > 0 if we are in a nested proc
|
||||
contSyms, breakSyms: seq[PSym] # to transform 'continue' and 'break'
|
||||
deferDetected, tooEarly, needsDestroyPass: bool
|
||||
graph: ModuleGraph
|
||||
PTransf = ref TTransfContext
|
||||
|
||||
proc newTransNode(a: PNode): PTransNode {.inline.} =
|
||||
@@ -84,7 +86,7 @@ proc pushTransCon(c: PTransf, t: PTransCon) =
|
||||
c.transCon = t
|
||||
|
||||
proc popTransCon(c: PTransf) =
|
||||
if (c.transCon == nil): internalError("popTransCon")
|
||||
if (c.transCon == nil): internalError(c.graph.config, "popTransCon")
|
||||
c.transCon = c.transCon.next
|
||||
|
||||
proc getCurrOwner(c: PTransf): PSym =
|
||||
@@ -97,7 +99,7 @@ proc newTemp(c: PTransf, typ: PType, info: TLineInfo): PNode =
|
||||
incl(r.flags, sfFromGeneric)
|
||||
let owner = getCurrOwner(c)
|
||||
if owner.isIterator and not c.tooEarly:
|
||||
result = freshVarForClosureIter(r, owner)
|
||||
result = freshVarForClosureIter(c.graph, r, owner)
|
||||
else:
|
||||
result = newSymNode(r)
|
||||
|
||||
@@ -118,10 +120,10 @@ proc transformSymAux(c: PTransf, n: PNode): PNode =
|
||||
if s.typ != nil and s.typ.callConv == ccClosure:
|
||||
if s.kind == skIterator:
|
||||
if c.tooEarly: return n
|
||||
else: return liftIterSym(n, getCurrOwner(c))
|
||||
else: return liftIterSym(c.graph, n, getCurrOwner(c))
|
||||
elif s.kind in {skProc, skFunc, skConverter, skMethod} and not c.tooEarly:
|
||||
# top level .closure procs are still somewhat supported for 'Nake':
|
||||
return makeClosure(s, nil, n.info)
|
||||
return makeClosure(c.graph, s, nil, n.info)
|
||||
#elif n.sym.kind in {skVar, skLet} and n.sym.typ.callConv == ccClosure:
|
||||
# echo n.info, " come heer for ", c.tooEarly
|
||||
# if not c.tooEarly:
|
||||
@@ -130,7 +132,7 @@ proc transformSymAux(c: PTransf, n: PNode): PNode =
|
||||
if sfBorrow in s.flags and s.kind in routineKinds:
|
||||
# simply exchange the symbol:
|
||||
b = s.getBody
|
||||
if b.kind != nkSym: internalError(n.info, "wrong AST for borrowed symbol")
|
||||
if b.kind != nkSym: internalError(c.graph.config, n.info, "wrong AST for borrowed symbol")
|
||||
b = newSymNode(b.sym, n.info)
|
||||
else:
|
||||
b = n
|
||||
@@ -151,7 +153,7 @@ proc transformSym(c: PTransf, n: PNode): PTransNode =
|
||||
proc freshVar(c: PTransf; v: PSym): PNode =
|
||||
let owner = getCurrOwner(c)
|
||||
if owner.isIterator and not c.tooEarly:
|
||||
result = freshVarForClosureIter(v, owner)
|
||||
result = freshVarForClosureIter(c.graph, v, owner)
|
||||
else:
|
||||
var newVar = copySym(v)
|
||||
incl(newVar.flags, sfFromGeneric)
|
||||
@@ -166,11 +168,11 @@ proc transformVarSection(c: PTransf, v: PNode): PTransNode =
|
||||
result[i] = PTransNode(it)
|
||||
elif it.kind == nkIdentDefs:
|
||||
if it.sons[0].kind == nkSym:
|
||||
internalAssert(it.len == 3)
|
||||
internalAssert(c.graph.config, it.len == 3)
|
||||
let x = freshVar(c, it.sons[0].sym)
|
||||
idNodeTablePut(c.transCon.mapping, it.sons[0].sym, x)
|
||||
var defs = newTransNode(nkIdentDefs, it.info, 3)
|
||||
if importantComments():
|
||||
if importantComments(c.graph.config):
|
||||
# keep documentation information:
|
||||
PNode(defs).comment = it.comment
|
||||
defs[0] = x.PTransNode
|
||||
@@ -184,7 +186,7 @@ proc transformVarSection(c: PTransf, v: PNode): PTransNode =
|
||||
result[i] = transform(c, it)
|
||||
else:
|
||||
if it.kind != nkVarTuple:
|
||||
internalError(it.info, "transformVarSection: not nkVarTuple")
|
||||
internalError(c.graph.config, it.info, "transformVarSection: not nkVarTuple")
|
||||
var L = sonsLen(it)
|
||||
var defs = newTransNode(it.kind, it.info, L)
|
||||
for j in countup(0, L-3):
|
||||
@@ -203,9 +205,9 @@ proc transformConstSection(c: PTransf, v: PNode): PTransNode =
|
||||
if it.kind == nkCommentStmt:
|
||||
result[i] = PTransNode(it)
|
||||
else:
|
||||
if it.kind != nkConstDef: internalError(it.info, "transformConstSection")
|
||||
if it.kind != nkConstDef: internalError(c.graph.config, it.info, "transformConstSection")
|
||||
if it.sons[0].kind != nkSym:
|
||||
internalError(it.info, "transformConstSection")
|
||||
internalError(c.graph.config, it.info, "transformConstSection")
|
||||
|
||||
result[i] = PTransNode(it)
|
||||
|
||||
@@ -301,7 +303,7 @@ proc unpackTuple(c: PTransf, n: PNode, father: PTransNode) =
|
||||
# XXX: BUG: what if `n` is an expression with side-effects?
|
||||
for i in countup(0, sonsLen(c.transCon.forStmt) - 3):
|
||||
add(father, newAsgnStmt(c, c.transCon.forStmt.sons[i],
|
||||
transform(c, newTupleAccess(n, i))))
|
||||
transform(c, newTupleAccess(c.graph, n, i))))
|
||||
|
||||
proc introduceNewLocalVars(c: PTransf, n: PNode): PTransNode =
|
||||
case n.kind
|
||||
@@ -382,7 +384,7 @@ proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PTransNode =
|
||||
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
|
||||
PNode(result).typ = n.typ
|
||||
|
||||
proc generateThunk(prc: PNode, dest: PType): PNode =
|
||||
proc generateThunk(c: PTransf; prc: PNode, dest: PType): PNode =
|
||||
## Converts 'prc' into '(thunk, nil)' so that it's compatible with
|
||||
## a closure.
|
||||
|
||||
@@ -394,9 +396,9 @@ proc generateThunk(prc: PNode, dest: PType): PNode =
|
||||
conv.add(emptyNode)
|
||||
conv.add(prc)
|
||||
if prc.kind == nkClosure:
|
||||
internalError(prc.info, "closure to closure created")
|
||||
internalError(c.graph.config, prc.info, "closure to closure created")
|
||||
result.add(conv)
|
||||
result.add(newNodeIT(nkNilLit, prc.info, getSysType(tyNil)))
|
||||
result.add(newNodeIT(nkNilLit, prc.info, getSysType(c.graph, prc.info, tyNil)))
|
||||
|
||||
proc transformConv(c: PTransf, n: PNode): PTransNode =
|
||||
# numeric types need range checks:
|
||||
@@ -481,7 +483,7 @@ proc transformConv(c: PTransf, n: PNode): PTransNode =
|
||||
of tyProc:
|
||||
result = transformSons(c, n)
|
||||
if dest.callConv == ccClosure and source.callConv == ccDefault:
|
||||
result = generateThunk(result[1].PNode, dest).PTransNode
|
||||
result = generateThunk(c, result[1].PNode, dest).PTransNode
|
||||
else:
|
||||
result = transformSons(c, n)
|
||||
|
||||
@@ -513,7 +515,7 @@ proc findWrongOwners(c: PTransf, n: PNode) =
|
||||
if n.kind == nkVarSection:
|
||||
let x = n.sons[0].sons[0]
|
||||
if x.kind == nkSym and x.sym.owner != getCurrOwner(c):
|
||||
internalError(x.info, "bah " & x.sym.name.s & " " &
|
||||
internalError(c.graph.config, x.info, "bah " & x.sym.name.s & " " &
|
||||
x.sym.owner.name.s & " " & getCurrOwner(c).name.s)
|
||||
else:
|
||||
for i in 0 ..< safeLen(n): findWrongOwners(c, n.sons[i])
|
||||
@@ -521,7 +523,7 @@ proc findWrongOwners(c: PTransf, n: PNode) =
|
||||
proc transformFor(c: PTransf, n: PNode): PTransNode =
|
||||
# generate access statements for the parameters (unless they are constant)
|
||||
# put mapping from formal parameters to actual parameters
|
||||
if n.kind != nkForStmt: internalError(n.info, "transformFor")
|
||||
if n.kind != nkForStmt: internalError(c.graph.config, n.info, "transformFor")
|
||||
|
||||
var length = sonsLen(n)
|
||||
var call = n.sons[length - 2]
|
||||
@@ -539,7 +541,7 @@ proc transformFor(c: PTransf, n: PNode): PTransNode =
|
||||
n.sons[length-1] = transformLoopBody(c, n.sons[length-1]).PNode
|
||||
if not c.tooEarly:
|
||||
n.sons[length-2] = transform(c, n.sons[length-2]).PNode
|
||||
result[1] = lambdalifting.liftForLoop(n, getCurrOwner(c)).PTransNode
|
||||
result[1] = lambdalifting.liftForLoop(c.graph, n, getCurrOwner(c)).PTransNode
|
||||
else:
|
||||
result[1] = newNode(nkEmpty).PTransNode
|
||||
discard c.breakSyms.pop
|
||||
@@ -689,7 +691,7 @@ proc transformCall(c: PTransf, n: PNode): PTransNode =
|
||||
while (j < sonsLen(n)):
|
||||
let b = transform(c, n.sons[j]).PNode
|
||||
if not isConstExpr(b): break
|
||||
a = evalOp(op.magic, n, a, b, nil)
|
||||
a = evalOp(op.magic, n, a, b, nil, c.graph)
|
||||
inc(j)
|
||||
add(result, a.PTransNode)
|
||||
if len(result) == 2: result = result[1]
|
||||
@@ -708,7 +710,7 @@ proc transformCall(c: PTransf, n: PNode): PTransNode =
|
||||
let t = lastSon(s.sons[0].sym.ast)
|
||||
if t.kind != nkSym or sfDispatcher notin t.sym.flags:
|
||||
methodDef(s.sons[0].sym, false)
|
||||
result = methodCall(s).PTransNode
|
||||
result = methodCall(s, c.graph.config).PTransNode
|
||||
else:
|
||||
result = s.PTransNode
|
||||
|
||||
@@ -719,7 +721,7 @@ proc transformExceptBranch(c: PTransf, n: PNode): PTransNode =
|
||||
let actions = newTransNode(nkStmtListExpr, n[1], 2)
|
||||
# Generating `let exc = (excType)(getCurrentException())`
|
||||
# -> getCurrentException()
|
||||
let excCall = PTransNode(callCodegenProc("getCurrentException", ast.emptyNode))
|
||||
let excCall = PTransNode(callCodegenProc(c.graph, "getCurrentException", ast.emptyNode))
|
||||
# -> (excType)
|
||||
let convNode = newTransNode(nkHiddenSubConv, n[1].info, 2)
|
||||
convNode[0] = PTransNode(ast.emptyNode)
|
||||
@@ -748,10 +750,10 @@ proc dontInlineConstant(orig, cnst: PNode): bool {.inline.} =
|
||||
result = orig.kind == nkSym and cnst.kind in {nkCurly, nkPar, nkTupleConstr, nkBracket} and
|
||||
cnst.len != 0
|
||||
|
||||
proc commonOptimizations*(c: PSym, n: PNode): PNode =
|
||||
proc commonOptimizations*(g: ModuleGraph; c: PSym, n: PNode): PNode =
|
||||
result = n
|
||||
for i in 0 ..< n.safeLen:
|
||||
result.sons[i] = commonOptimizations(c, n.sons[i])
|
||||
result.sons[i] = commonOptimizations(g, c, n.sons[i])
|
||||
var op = getMergeOp(n)
|
||||
if (op != nil) and (op.magic != mNone) and (sonsLen(n) >= 3):
|
||||
result = newNodeIT(nkCall, n.info, n.typ)
|
||||
@@ -766,12 +768,12 @@ proc commonOptimizations*(c: PSym, n: PNode): PNode =
|
||||
while j < sonsLen(args):
|
||||
let b = args.sons[j]
|
||||
if not isConstExpr(b): break
|
||||
a = evalOp(op.magic, result, a, b, nil)
|
||||
a = evalOp(op.magic, result, a, b, nil, g)
|
||||
inc(j)
|
||||
add(result, a)
|
||||
if len(result) == 2: result = result[1]
|
||||
else:
|
||||
var cnst = getConstExpr(c, n)
|
||||
var cnst = getConstExpr(c, n, g)
|
||||
# we inline constants if they are not complex constants:
|
||||
if cnst != nil and not dontInlineConstant(n, cnst):
|
||||
result = cnst
|
||||
@@ -888,7 +890,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
|
||||
let L = n.len-1
|
||||
result[L] = transform(c, n.sons[L])
|
||||
# XXX comment handling really sucks:
|
||||
if importantComments():
|
||||
if importantComments(c.graph.config):
|
||||
PNode(result).comment = n.comment
|
||||
of nkClosure:
|
||||
# it can happen that for-loop-inlining produced a fresh
|
||||
@@ -905,7 +907,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
|
||||
when false:
|
||||
if oldDeferAnchor != nil: c.deferAnchor = oldDeferAnchor
|
||||
|
||||
var cnst = getConstExpr(c.module, PNode(result))
|
||||
var cnst = getConstExpr(c.module, PNode(result), c.graph)
|
||||
# we inline constants if they are not complex constants:
|
||||
if cnst != nil and not dontInlineConstant(n, cnst):
|
||||
result = PTransNode(cnst) # do not miss an optimization
|
||||
@@ -920,11 +922,12 @@ proc processTransf(c: PTransf, n: PNode, owner: PSym): PNode =
|
||||
popTransCon(c)
|
||||
incl(result.flags, nfTransf)
|
||||
|
||||
proc openTransf(module: PSym, filename: string): PTransf =
|
||||
proc openTransf(g: ModuleGraph; module: PSym, filename: string): PTransf =
|
||||
new(result)
|
||||
result.contSyms = @[]
|
||||
result.breakSyms = @[]
|
||||
result.module = module
|
||||
result.graph = g
|
||||
|
||||
proc flattenStmts(n: PNode) =
|
||||
var goOn = true
|
||||
@@ -967,46 +970,46 @@ template liftDefer(c, root) =
|
||||
if c.deferDetected:
|
||||
liftDeferAux(root)
|
||||
|
||||
proc transformBody*(module: PSym, n: PNode, prc: PSym): PNode =
|
||||
proc transformBody*(g: ModuleGraph; module: PSym, n: PNode, prc: PSym): PNode =
|
||||
if nfTransf in n.flags or prc.kind in {skTemplate}:
|
||||
result = n
|
||||
else:
|
||||
var c = openTransf(module, "")
|
||||
result = liftLambdas(prc, n, c.tooEarly)
|
||||
var c = openTransf(g, module, "")
|
||||
result = liftLambdas(g, prc, n, c.tooEarly)
|
||||
#result = n
|
||||
result = processTransf(c, result, prc)
|
||||
liftDefer(c, result)
|
||||
#result = liftLambdas(prc, result)
|
||||
when useEffectSystem: trackProc(prc, result)
|
||||
result = liftLocalsIfRequested(prc, result)
|
||||
when useEffectSystem: trackProc(g, prc, result)
|
||||
result = liftLocalsIfRequested(prc, result, g.config)
|
||||
if c.needsDestroyPass: #and newDestructors:
|
||||
result = injectDestructorCalls(prc, result)
|
||||
result = injectDestructorCalls(g, prc, result)
|
||||
incl(result.flags, nfTransf)
|
||||
#if prc.name.s == "testbody":
|
||||
# echo renderTree(result)
|
||||
|
||||
proc transformStmt*(module: PSym, n: PNode): PNode =
|
||||
proc transformStmt*(g: ModuleGraph; module: PSym, n: PNode): PNode =
|
||||
if nfTransf in n.flags:
|
||||
result = n
|
||||
else:
|
||||
var c = openTransf(module, "")
|
||||
var c = openTransf(g, module, "")
|
||||
result = processTransf(c, n, module)
|
||||
liftDefer(c, result)
|
||||
#result = liftLambdasForTopLevel(module, result)
|
||||
when useEffectSystem: trackTopLevelStmt(module, result)
|
||||
when useEffectSystem: trackTopLevelStmt(g, module, result)
|
||||
#if n.info ?? "temp.nim":
|
||||
# echo renderTree(result, {renderIds})
|
||||
if c.needsDestroyPass:
|
||||
result = injectDestructorCalls(module, result)
|
||||
result = injectDestructorCalls(g, module, result)
|
||||
incl(result.flags, nfTransf)
|
||||
|
||||
proc transformExpr*(module: PSym, n: PNode): PNode =
|
||||
proc transformExpr*(g: ModuleGraph; module: PSym, n: PNode): PNode =
|
||||
if nfTransf in n.flags:
|
||||
result = n
|
||||
else:
|
||||
var c = openTransf(module, "")
|
||||
var c = openTransf(g, module, "")
|
||||
result = processTransf(c, n, module)
|
||||
liftDefer(c, result)
|
||||
if c.needsDestroyPass:
|
||||
result = injectDestructorCalls(module, result)
|
||||
result = injectDestructorCalls(g, module, result)
|
||||
incl(result.flags, nfTransf)
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
## This module contains the type definitions for the new evaluation engine.
|
||||
## An instruction is 1-3 int32s in memory, it is a register based VM.
|
||||
|
||||
import ast, passes, msgs, idents, intsets, options
|
||||
import ast, passes, msgs, idents, intsets, options, modulegraphs
|
||||
|
||||
const
|
||||
byteExcess* = 128 # we use excess-K for immediates
|
||||
@@ -207,18 +207,18 @@ type
|
||||
errorFlag*: string
|
||||
cache*: IdentCache
|
||||
config*: ConfigRef
|
||||
graph*: ModuleGraph
|
||||
|
||||
TPosition* = distinct int
|
||||
|
||||
PEvalContext* = PCtx
|
||||
|
||||
proc newCtx*(module: PSym; cache: IdentCache; config: ConfigRef = nil): PCtx =
|
||||
let conf = if config != nil: config else: newConfigRef()
|
||||
proc newCtx*(module: PSym; cache: IdentCache; g: ModuleGraph): PCtx =
|
||||
PCtx(code: @[], debug: @[],
|
||||
globals: newNode(nkStmtListExpr), constants: newNode(nkStmtList), types: @[],
|
||||
prc: PProc(blocks: @[]), module: module, loopIterations: MaxLoopIterations,
|
||||
comesFromHeuristic: unknownLineInfo(), callbacks: @[], errorFlag: "",
|
||||
cache: cache, config: conf)
|
||||
cache: cache, config: g.config, graph: g)
|
||||
|
||||
proc refresh*(c: PCtx, module: PSym) =
|
||||
c.module = module
|
||||
|
||||
@@ -9,18 +9,18 @@
|
||||
|
||||
import ast, types, msgs, os, streams, options, idents
|
||||
|
||||
proc opSlurp*(file: string, info: TLineInfo, module: PSym): string =
|
||||
proc opSlurp*(file: string, info: TLineInfo, module: PSym; conf: ConfigRef): string =
|
||||
try:
|
||||
var filename = parentDir(info.toFullPath) / file
|
||||
if not fileExists(filename):
|
||||
filename = file.findFile
|
||||
filename = findFile(conf, file)
|
||||
result = readFile(filename)
|
||||
# we produce a fake include statement for every slurped filename, so that
|
||||
# the module dependencies are accurate:
|
||||
appendToModule(module, newNode(nkIncludeStmt, info, @[
|
||||
newStrNode(nkStrLit, filename)]))
|
||||
except IOError:
|
||||
localError(info, errCannotOpenFile, file)
|
||||
localError(conf, info, "cannot open file: " & file)
|
||||
result = ""
|
||||
|
||||
proc atomicTypeX(name: string; m: TMagic; t: PType; info: TLineInfo): PNode =
|
||||
@@ -271,7 +271,7 @@ proc mapTypeToAstX(t: PType; info: TLineInfo;
|
||||
of tyOr: result = mapTypeToBracket("or", mOr, t, info)
|
||||
of tyNot: result = mapTypeToBracket("not", mNot, t, info)
|
||||
of tyAnything: result = atomicType("anything", mNone)
|
||||
of tyInferred: internalAssert false
|
||||
of tyInferred: assert false
|
||||
of tyStatic, tyFromExpr:
|
||||
if inst:
|
||||
if t.n != nil: result = t.n.copyTree
|
||||
@@ -281,7 +281,7 @@ proc mapTypeToAstX(t: PType; info: TLineInfo;
|
||||
result.add atomicType("static", mNone)
|
||||
if t.n != nil:
|
||||
result.add t.n.copyTree
|
||||
of tyUnused, tyOptAsRef: internalError("mapTypeToAstX")
|
||||
of tyUnused, tyOptAsRef: assert(false, "mapTypeToAstX")
|
||||
|
||||
proc opMapTypeToAst*(t: PType; info: TLineInfo): PNode =
|
||||
result = mapTypeToAstX(t, info, false, true)
|
||||
|
||||
@@ -120,7 +120,7 @@ proc gABI(c: PCtx; n: PNode; opc: TOpcode; a, b: TRegister; imm: BiggestInt) =
|
||||
c.code.add(ins)
|
||||
c.debug.add(n.info)
|
||||
else:
|
||||
localError(n.info, errGenerated,
|
||||
localError(c.config, n.info,
|
||||
"VM: immediate value does not fit into an int8")
|
||||
|
||||
proc gABx(c: PCtx; n: PNode; opc: TOpcode; a: TRegister = 0; bx: int) =
|
||||
@@ -137,7 +137,7 @@ proc gABx(c: PCtx; n: PNode; opc: TOpcode; a: TRegister = 0; bx: int) =
|
||||
c.code.add(ins)
|
||||
c.debug.add(n.info)
|
||||
else:
|
||||
localError(n.info, errGenerated,
|
||||
localError(c.config, n.info,
|
||||
"VM: immediate value does not fit into an int16")
|
||||
|
||||
proc xjmp(c: PCtx; n: PNode; opc: TOpcode; a: TRegister = 0): TPosition =
|
||||
@@ -151,7 +151,7 @@ proc genLabel(c: PCtx): TPosition =
|
||||
|
||||
proc jmpBack(c: PCtx, n: PNode, p = TPosition(0)) =
|
||||
let dist = p.int - c.code.len
|
||||
internalAssert(-0x7fff < dist and dist < 0x7fff)
|
||||
internalAssert(c.config, -0x7fff < dist and dist < 0x7fff)
|
||||
gABx(c, n, opcJmpBack, 0, dist)
|
||||
|
||||
proc patch(c: PCtx, p: TPosition) =
|
||||
@@ -159,7 +159,7 @@ proc patch(c: PCtx, p: TPosition) =
|
||||
let p = p.int
|
||||
let diff = c.code.len - p
|
||||
#c.jumpTargets.incl(c.code.len)
|
||||
internalAssert(-0x7fff < diff and diff < 0x7fff)
|
||||
internalAssert(c.config, -0x7fff < diff and diff < 0x7fff)
|
||||
let oldInstr = c.code[p]
|
||||
# opcode and regA stay the same:
|
||||
c.code[p] = ((oldInstr.uint32 and 0xffff'u32).uint32 or
|
||||
@@ -201,7 +201,7 @@ proc getTemp(cc: PCtx; tt: PType): TRegister =
|
||||
c.slots[i] = (inUse: true, kind: k)
|
||||
return TRegister(i)
|
||||
if c.maxSlots >= high(TRegister):
|
||||
globalError(cc.bestEffort, "VM problem: too many registers required")
|
||||
globalError(cc.config, cc.bestEffort, "VM problem: too many registers required")
|
||||
result = TRegister(c.maxSlots)
|
||||
c.slots[c.maxSlots] = (inUse: true, kind: k)
|
||||
inc c.maxSlots
|
||||
@@ -223,7 +223,7 @@ proc getTempRange(cc: PCtx; n: int; kind: TSlotKind): TRegister =
|
||||
for k in result .. result+n-1: c.slots[k] = (inUse: true, kind: kind)
|
||||
return
|
||||
if c.maxSlots+n >= high(TRegister):
|
||||
globalError(cc.bestEffort, "VM problem: too many registers required")
|
||||
globalError(cc.config, cc.bestEffort, "VM problem: too many registers required")
|
||||
result = TRegister(c.maxSlots)
|
||||
inc c.maxSlots, n
|
||||
for k in result .. result+n-1: c.slots[k] = (inUse: true, kind: kind)
|
||||
@@ -251,7 +251,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {})
|
||||
proc gen(c: PCtx; n: PNode; dest: TRegister; flags: TGenFlags = {}) =
|
||||
var d: TDest = dest
|
||||
gen(c, n, d, flags)
|
||||
#internalAssert d == dest # issue #7407
|
||||
#internalAssert c.config, d == dest # issue #7407
|
||||
|
||||
proc gen(c: PCtx; n: PNode; flags: TGenFlags = {}) =
|
||||
var tmp: TDest = -1
|
||||
@@ -261,7 +261,7 @@ proc gen(c: PCtx; n: PNode; flags: TGenFlags = {}) =
|
||||
proc genx(c: PCtx; n: PNode; flags: TGenFlags = {}): TRegister =
|
||||
var tmp: TDest = -1
|
||||
gen(c, n, tmp, flags)
|
||||
#internalAssert tmp >= 0 # 'nim check' does not like this internalAssert.
|
||||
#internalAssert c.config, tmp >= 0 # 'nim check' does not like this internalAssert.
|
||||
if tmp >= 0:
|
||||
result = TRegister(tmp)
|
||||
|
||||
@@ -320,7 +320,7 @@ proc genBreak(c: PCtx; n: PNode) =
|
||||
if c.prc.blocks[i].label == n.sons[0].sym:
|
||||
c.prc.blocks[i].fixups.add L1
|
||||
return
|
||||
globalError(n.info, errGenerated, "VM problem: cannot find 'break' target")
|
||||
globalError(c.config, n.info, "VM problem: cannot find 'break' target")
|
||||
else:
|
||||
c.prc.blocks[c.prc.blocks.high].fixups.add L1
|
||||
|
||||
@@ -378,7 +378,7 @@ proc rawGenLiteral(c: PCtx; n: PNode): int =
|
||||
#assert(n.kind != nkCall)
|
||||
n.flags.incl nfAllConst
|
||||
c.constants.add n.canonValue
|
||||
internalAssert result < 0x7fff
|
||||
internalAssert c.config, result < 0x7fff
|
||||
|
||||
proc sameConstant*(a, b: PNode): bool =
|
||||
result = false
|
||||
@@ -405,10 +405,10 @@ proc genLiteral(c: PCtx; n: PNode): int =
|
||||
if sameConstant(c.constants[i], n): return i
|
||||
result = rawGenLiteral(c, n)
|
||||
|
||||
proc unused(n: PNode; x: TDest) {.inline.} =
|
||||
proc unused(c: PCtx; n: PNode; x: TDest) {.inline.} =
|
||||
if x >= 0:
|
||||
#debug(n)
|
||||
globalError(n.info, "not unused")
|
||||
globalError(c.config, n.info, "not unused")
|
||||
|
||||
proc genCase(c: PCtx; n: PNode; dest: var TDest) =
|
||||
# if (!expr1) goto L1;
|
||||
@@ -424,7 +424,7 @@ proc genCase(c: PCtx; n: PNode; dest: var TDest) =
|
||||
if not isEmptyType(n.typ):
|
||||
if dest < 0: dest = getTemp(c, n.typ)
|
||||
else:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
var endings: seq[TPosition] = @[]
|
||||
withTemp(tmp, n.sons[0].typ):
|
||||
c.gen(n.sons[0], tmp)
|
||||
@@ -451,7 +451,7 @@ proc genType(c: PCtx; typ: PType): int =
|
||||
if sameType(t, typ): return i
|
||||
result = c.types.len
|
||||
c.types.add(typ)
|
||||
internalAssert(result <= 0x7fff)
|
||||
internalAssert(c.config, result <= 0x7fff)
|
||||
|
||||
proc genTry(c: PCtx; n: PNode; dest: var TDest) =
|
||||
if dest < 0 and not isEmptyType(n.typ): dest = getTemp(c, n.typ)
|
||||
@@ -525,7 +525,7 @@ proc genCall(c: PCtx; n: PNode; dest: var TDest) =
|
||||
var r: TRegister = x+i
|
||||
c.gen(n.sons[i], r)
|
||||
if i >= fntyp.len:
|
||||
internalAssert tfVarargs in fntyp.flags
|
||||
internalAssert c.config, tfVarargs in fntyp.flags
|
||||
c.gABx(n, opcSetType, r, c.genType(n.sons[i].typ))
|
||||
if dest < 0:
|
||||
c.gABC(n, opcIndCall, 0, x, n.len)
|
||||
@@ -540,12 +540,12 @@ proc needsAsgnPatch(n: PNode): bool =
|
||||
n.kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr,
|
||||
nkDerefExpr, nkHiddenDeref} or (n.kind == nkSym and n.sym.isGlobal)
|
||||
|
||||
proc genField(n: PNode): TRegister =
|
||||
proc genField(c: PCtx; n: PNode): TRegister =
|
||||
if n.kind != nkSym or n.sym.kind != skField:
|
||||
globalError(n.info, "no field symbol")
|
||||
globalError(c.config, n.info, "no field symbol")
|
||||
let s = n.sym
|
||||
if s.position > high(result):
|
||||
globalError(n.info,
|
||||
globalError(c.config, n.info,
|
||||
"too large offset! cannot generate code for: " & s.name.s)
|
||||
result = s.position
|
||||
|
||||
@@ -572,7 +572,7 @@ proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
|
||||
# XXX field checks here
|
||||
let left = if le.kind == nkDotExpr: le else: le.sons[0]
|
||||
let dest = c.genx(left.sons[0], {gfAddrOf, gfFieldAccess})
|
||||
let idx = genField(left.sons[1])
|
||||
let idx = genField(c, left.sons[1])
|
||||
c.gABC(left, opcWrObj, dest, idx, value)
|
||||
c.freeTemp(dest)
|
||||
of nkDerefExpr, nkHiddenDeref:
|
||||
@@ -779,7 +779,7 @@ proc genIntCast(c: PCtx; n: PNode; dest: var TDest) =
|
||||
let tmp3 = c.getTemp(n.sons[1].typ)
|
||||
if dest < 0: dest = c.getTemp(n[0].typ)
|
||||
proc mkIntLit(ival: int): int =
|
||||
result = genLiteral(c, newIntTypeNode(nkIntLit, ival, getSysType(tyInt)))
|
||||
result = genLiteral(c, newIntTypeNode(nkIntLit, ival, getSysType(c.graph, n.info, tyInt)))
|
||||
if src.kind in unsignedIntegers and dst.kind in signedIntegers:
|
||||
# cast unsigned to signed integer of same size
|
||||
# signedVal = (unsignedVal xor offset) -% offset
|
||||
@@ -802,7 +802,7 @@ proc genIntCast(c: PCtx; n: PNode; dest: var TDest) =
|
||||
c.freeTemp(tmp2)
|
||||
c.freeTemp(tmp3)
|
||||
else:
|
||||
globalError(n.info, errGenerated, "VM is only allowed to 'cast' between integers of same size")
|
||||
globalError(c.config, n.info, "VM is only allowed to 'cast' between integers of same size")
|
||||
|
||||
proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
case m
|
||||
@@ -818,7 +818,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
of mSucc, mAddI:
|
||||
c.genAddSubInt(n, dest, opcAddInt)
|
||||
of mInc, mDec:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
let opc = if m == mInc: opcAddInt else: opcSubInt
|
||||
let d = c.genx(n.sons[1])
|
||||
if n.sons[2].isInt8Lit:
|
||||
@@ -832,10 +832,10 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
c.freeTemp(d)
|
||||
of mOrd, mChr, mArrToSeq: c.gen(n.sons[1], dest)
|
||||
of mNew, mNewFinalize:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
c.genNew(n)
|
||||
of mNewSeq:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
c.genNewSeq(n)
|
||||
of mNewSeqOfCap: c.genNewSeqOfCap(n, dest)
|
||||
of mNewString:
|
||||
@@ -855,7 +855,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
of mLengthStr, mXLenStr:
|
||||
genUnaryABI(c, n, dest, opcLenStr)
|
||||
of mIncl, mExcl:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
var d = c.genx(n.sons[1])
|
||||
var tmp = c.genx(n.sons[2])
|
||||
c.genSetType(n.sons[1], d)
|
||||
@@ -952,19 +952,19 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
of mInSet: genBinarySet(c, n, dest, opcContainsSet)
|
||||
of mRepr: genUnaryABC(c, n, dest, opcRepr)
|
||||
of mExit:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
var tmp = c.genx(n.sons[1])
|
||||
c.gABC(n, opcQuit, tmp)
|
||||
c.freeTemp(tmp)
|
||||
of mSetLengthStr, mSetLengthSeq:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
var d = c.genx(n.sons[1])
|
||||
var tmp = c.genx(n.sons[2])
|
||||
c.gABC(n, if m == mSetLengthStr: opcSetLenStr else: opcSetLenSeq, d, tmp)
|
||||
c.genAsgnPatch(n.sons[1], d)
|
||||
c.freeTemp(tmp)
|
||||
of mSwap:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
c.gen(lowerSwap(n, if c.prc == nil: c.module else: c.prc.sym))
|
||||
of mIsNil: genUnaryABC(c, n, dest, opcIsNil)
|
||||
of mCopyStr:
|
||||
@@ -996,7 +996,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
# skip 'nkHiddenAddr':
|
||||
let d2AsNode = n.sons[2].sons[0]
|
||||
if needsAsgnPatch(d2AsNode):
|
||||
d2 = c.getTemp(getSysType(tyFloat))
|
||||
d2 = c.getTemp(getSysType(c.graph, n.info, tyFloat))
|
||||
else:
|
||||
d2 = c.genx(d2AsNode)
|
||||
var
|
||||
@@ -1009,13 +1009,13 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
c.genAsgnPatch(d2AsNode, d2)
|
||||
c.freeTemp(d2)
|
||||
of mReset:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
var d = c.genx(n.sons[1])
|
||||
c.gABC(n, opcReset, d)
|
||||
of mOf, mIs:
|
||||
if dest < 0: dest = c.getTemp(n.typ)
|
||||
var tmp = c.genx(n.sons[1])
|
||||
var idx = c.getTemp(getSysType(tyInt))
|
||||
var idx = c.getTemp(getSysType(c.graph, n.info, tyInt))
|
||||
var typ = n.sons[2].typ
|
||||
if m == mOf: typ = typ.skipTypes(abstractPtrs-{tyTypeDesc})
|
||||
c.gABx(n, opcLdImmInt, idx, c.genType(typ))
|
||||
@@ -1023,7 +1023,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
c.freeTemp(tmp)
|
||||
c.freeTemp(idx)
|
||||
of mSizeOf:
|
||||
globalError(n.info, errCannotInterpretNodeX, renderTree(n))
|
||||
globalError(c.config, n.info, "cannot run in the VM: " & renderTree(n))
|
||||
of mHigh:
|
||||
if dest < 0: dest = c.getTemp(n.typ)
|
||||
let tmp = c.genx(n.sons[1])
|
||||
@@ -1034,23 +1034,23 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
c.gABI(n, opcLenSeq, dest, tmp, 1)
|
||||
c.freeTemp(tmp)
|
||||
of mEcho:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
let n = n[1].skipConv
|
||||
let x = c.getTempRange(n.len, slotTempUnknown)
|
||||
internalAssert n.kind == nkBracket
|
||||
internalAssert c.config, n.kind == nkBracket
|
||||
for i in 0..<n.len:
|
||||
var r: TRegister = x+i
|
||||
c.gen(n.sons[i], r)
|
||||
c.gABC(n, opcEcho, x, n.len)
|
||||
c.freeTempRange(x, n.len)
|
||||
of mAppendStrCh:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
genBinaryStmtVar(c, n, opcAddStrCh)
|
||||
of mAppendStrStr:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
genBinaryStmtVar(c, n, opcAddStrStr)
|
||||
of mAppendSeqElem:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
genBinaryStmtVar(c, n, opcAddSeqElem)
|
||||
of mParseExprToAst:
|
||||
genUnaryABC(c, n, dest, opcParseExprToAst)
|
||||
@@ -1068,7 +1068,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
of mGetImpl: genUnaryABC(c, n, dest, opcGetImpl)
|
||||
of mNChild: genBinaryABC(c, n, dest, opcNChild)
|
||||
of mNSetChild, mNDel:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
var
|
||||
tmp1 = c.genx(n.sons[1])
|
||||
tmp2 = c.genx(n.sons[2])
|
||||
@@ -1098,22 +1098,22 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
#genUnaryABC(c, n, dest, opcNGetType)
|
||||
of mNStrVal: genUnaryABC(c, n, dest, opcNStrVal)
|
||||
of mNSetIntVal:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
genBinaryStmt(c, n, opcNSetIntVal)
|
||||
of mNSetFloatVal:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
genBinaryStmt(c, n, opcNSetFloatVal)
|
||||
of mNSetSymbol:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
genBinaryStmt(c, n, opcNSetSymbol)
|
||||
of mNSetIdent:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
genBinaryStmt(c, n, opcNSetIdent)
|
||||
of mNSetType:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
genBinaryStmt(c, n, opcNSetType)
|
||||
of mNSetStrVal:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
genBinaryStmt(c, n, opcNSetStrVal)
|
||||
of mNNewNimNode: genBinaryABC(c, n, dest, opcNNewNimNode)
|
||||
of mNCopyNimNode: genUnaryABC(c, n, dest, opcNCopyNimNode)
|
||||
@@ -1124,7 +1124,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
if dest < 0: dest = c.getTemp(n.typ)
|
||||
c.gABx(n, opcNBindSym, dest, idx)
|
||||
else:
|
||||
localError(n.info, "invalid bindSym usage")
|
||||
localError(c.config, n.info, "invalid bindSym usage")
|
||||
of mStrToIdent: genUnaryABC(c, n, dest, opcStrToIdent)
|
||||
of mEqIdent: genBinaryABC(c, n, dest, opcEqIdent)
|
||||
of mEqNimrodNode: genBinaryABC(c, n, dest, opcEqNimrodNode)
|
||||
@@ -1138,12 +1138,12 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
of "getColumn":
|
||||
genUnaryABC(c, n, dest, opcNGetColumn)
|
||||
else:
|
||||
internalAssert false
|
||||
internalAssert c.config, false
|
||||
of mNHint:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
genUnaryStmt(c, n, opcNHint)
|
||||
of mNWarning:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
genUnaryStmt(c, n, opcNWarning)
|
||||
of mNError:
|
||||
if n.len <= 1:
|
||||
@@ -1151,7 +1151,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
c.gABC(n, opcQueryErrorFlag, dest)
|
||||
else:
|
||||
# setter
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
genBinaryStmt(c, n, opcNError)
|
||||
of mNCallSite:
|
||||
if dest < 0: dest = c.getTemp(n.typ)
|
||||
@@ -1162,7 +1162,7 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
c.genCall(n, dest)
|
||||
of mExpandToAst:
|
||||
if n.len != 2:
|
||||
globalError(n.info, errGenerated, "expandToAst requires 1 argument")
|
||||
globalError(c.config, n.info, "expandToAst requires 1 argument")
|
||||
let arg = n.sons[1]
|
||||
if arg.kind in nkCallKinds:
|
||||
#if arg[0].kind != nkSym or arg[0].sym.kind notin {skTemplate, skMacro}:
|
||||
@@ -1172,12 +1172,12 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||
# do not call clearDest(n, dest) here as getAst has a meta-type as such
|
||||
# produces a value
|
||||
else:
|
||||
globalError(n.info, "expandToAst requires a call expression")
|
||||
globalError(c.config, n.info, "expandToAst requires a call expression")
|
||||
of mRunnableExamples:
|
||||
discard "just ignore any call to runnableExamples"
|
||||
else:
|
||||
# mGCref, mGCunref,
|
||||
globalError(n.info, "cannot generate code for: " & $m)
|
||||
globalError(c.config, n.info, "cannot generate code for: " & $m)
|
||||
|
||||
proc genMarshalLoad(c: PCtx, n: PNode, dest: var TDest) =
|
||||
## Signature: proc to*[T](data: string): T
|
||||
@@ -1306,14 +1306,14 @@ proc setSlot(c: PCtx; v: PSym) =
|
||||
if v.position == 0:
|
||||
if c.prc.maxSlots == 0: c.prc.maxSlots = 1
|
||||
if c.prc.maxSlots >= high(TRegister):
|
||||
globalError(v.info, "cannot generate code; too many registers required")
|
||||
globalError(c.config, v.info, "cannot generate code; too many registers required")
|
||||
v.position = c.prc.maxSlots
|
||||
c.prc.slots[v.position] = (inUse: true,
|
||||
kind: if v.kind == skLet: slotFixedLet else: slotFixedVar)
|
||||
inc c.prc.maxSlots
|
||||
|
||||
proc cannotEval(n: PNode) {.noinline.} =
|
||||
globalError(n.info, errGenerated, "cannot evaluate at compile time: " &
|
||||
proc cannotEval(c: PCtx; n: PNode) {.noinline.} =
|
||||
globalError(c.config, n.info, "cannot evaluate at compile time: " &
|
||||
n.renderTree)
|
||||
|
||||
proc isOwnedBy(a, b: PSym): bool =
|
||||
@@ -1333,10 +1333,10 @@ proc checkCanEval(c: PCtx; n: PNode) =
|
||||
if {sfCompileTime, sfGlobal} <= s.flags: return
|
||||
if s.kind in {skVar, skTemp, skLet, skParam, skResult} and
|
||||
not s.isOwnedBy(c.prc.sym) and s.owner != c.module and c.mode != emRepl:
|
||||
cannotEval(n)
|
||||
cannotEval(c, n)
|
||||
elif s.kind in {skProc, skFunc, skConverter, skMethod,
|
||||
skIterator} and sfForward in s.flags:
|
||||
cannotEval(n)
|
||||
cannotEval(c, n)
|
||||
|
||||
proc isTemp(c: PCtx; dest: TDest): bool =
|
||||
result = dest >= 0 and c.prc.slots[dest].kind >= slotTempUnknown
|
||||
@@ -1378,7 +1378,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||
# XXX field checks here
|
||||
let left = if le.kind == nkDotExpr: le else: le.sons[0]
|
||||
let dest = c.genx(left.sons[0], {gfAddrOf, gfFieldAccess})
|
||||
let idx = genField(left.sons[1])
|
||||
let idx = genField(c, left.sons[1])
|
||||
let tmp = c.genx(ri)
|
||||
c.preventFalseAlias(left, opcWrObj, dest, idx, tmp)
|
||||
c.freeTemp(tmp)
|
||||
@@ -1398,7 +1398,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||
c.freeTemp(val)
|
||||
else:
|
||||
if s.kind == skForVar: c.setSlot s
|
||||
internalAssert s.position > 0 or (s.position == 0 and
|
||||
internalAssert c.config, s.position > 0 or (s.position == 0 and
|
||||
s.kind in {skParam,skResult})
|
||||
var dest: TRegister = s.position + ord(s.kind == skParam)
|
||||
assert le.typ != nil
|
||||
@@ -1424,15 +1424,15 @@ proc importcSym(c: PCtx; info: TLineInfo; s: PSym) =
|
||||
c.globals.add(importcSymbol(s))
|
||||
s.position = c.globals.len
|
||||
else:
|
||||
localError(info, errGenerated, "VM is not allowed to 'importc'")
|
||||
localError(c.config, info, "VM is not allowed to 'importc'")
|
||||
else:
|
||||
localError(info, errGenerated,
|
||||
localError(c.config, info,
|
||||
"cannot 'importc' variable at compile time")
|
||||
|
||||
proc getNullValue*(typ: PType, info: TLineInfo): PNode
|
||||
proc getNullValue*(typ: PType, info: TLineInfo; conf: ConfigRef): PNode
|
||||
|
||||
proc genGlobalInit(c: PCtx; n: PNode; s: PSym) =
|
||||
c.globals.add(getNullValue(s.typ, n.info))
|
||||
c.globals.add(getNullValue(s.typ, n.info, c.config))
|
||||
s.position = c.globals.len
|
||||
# This is rather hard to support, due to the laziness of the VM code
|
||||
# generator. See tests/compile/tmacro2 for why this is necessary:
|
||||
@@ -1451,7 +1451,7 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
||||
if sfCompileTime in s.flags or c.mode == emRepl:
|
||||
discard
|
||||
elif s.position == 0:
|
||||
cannotEval(n)
|
||||
cannotEval(c, n)
|
||||
if s.position == 0:
|
||||
if sfImportc in s.flags: c.importcSym(n.info, s)
|
||||
else: genGlobalInit(c, n, s)
|
||||
@@ -1472,13 +1472,13 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
||||
s.kind in {skParam,skResult}):
|
||||
if dest < 0:
|
||||
dest = s.position + ord(s.kind == skParam)
|
||||
internalAssert(c.prc.slots[dest].kind < slotSomeTemp)
|
||||
internalAssert(c.config, c.prc.slots[dest].kind < slotSomeTemp)
|
||||
else:
|
||||
# we need to generate an assignment:
|
||||
genAsgn(c, dest, n, c.prc.slots[dest].kind >= slotSomeTemp)
|
||||
else:
|
||||
# see tests/t99bott for an example that triggers it:
|
||||
cannotEval(n)
|
||||
cannotEval(c, n)
|
||||
|
||||
template needsRegLoad(): untyped =
|
||||
gfAddrOf notin flags and fitsRegister(n.typ.skipTypes({tyVar, tyLent}))
|
||||
@@ -1502,7 +1502,7 @@ proc genArrAccess2(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
|
||||
|
||||
proc genObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
||||
let a = c.genx(n.sons[0], flags)
|
||||
let b = genField(n.sons[1])
|
||||
let b = genField(c, n.sons[1])
|
||||
if dest < 0: dest = c.getTemp(n.typ)
|
||||
if needsRegLoad():
|
||||
var cc = c.getTemp(n.typ)
|
||||
@@ -1526,22 +1526,22 @@ proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
||||
else:
|
||||
genArrAccess2(c, n, dest, opcLdArr, flags)
|
||||
|
||||
proc getNullValueAux(obj: PNode, result: PNode) =
|
||||
proc getNullValueAux(obj: PNode, result: PNode; conf: ConfigRef) =
|
||||
case obj.kind
|
||||
of nkRecList:
|
||||
for i in countup(0, sonsLen(obj) - 1): getNullValueAux(obj.sons[i], result)
|
||||
for i in countup(0, sonsLen(obj) - 1): getNullValueAux(obj.sons[i], result, conf)
|
||||
of nkRecCase:
|
||||
getNullValueAux(obj.sons[0], result)
|
||||
getNullValueAux(obj.sons[0], result, conf)
|
||||
for i in countup(1, sonsLen(obj) - 1):
|
||||
getNullValueAux(lastSon(obj.sons[i]), result)
|
||||
getNullValueAux(lastSon(obj.sons[i]), result, conf)
|
||||
of nkSym:
|
||||
let field = newNodeI(nkExprColonExpr, result.info)
|
||||
field.add(obj)
|
||||
field.add(getNullValue(obj.sym.typ, result.info))
|
||||
field.add(getNullValue(obj.sym.typ, result.info, conf))
|
||||
addSon(result, field)
|
||||
else: globalError(result.info, "cannot create null element for: " & $obj)
|
||||
else: globalError(conf, result.info, "cannot create null element for: " & $obj)
|
||||
|
||||
proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||
proc getNullValue(typ: PType, info: TLineInfo; conf: ConfigRef): PNode =
|
||||
var t = skipTypes(typ, abstractRange-{tyTypeDesc})
|
||||
result = emptyNode
|
||||
case t.kind
|
||||
@@ -1570,17 +1570,17 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||
# initialize inherited fields:
|
||||
var base = t.sons[0]
|
||||
while base != nil:
|
||||
getNullValueAux(skipTypes(base, skipPtrs).n, result)
|
||||
getNullValueAux(skipTypes(base, skipPtrs).n, result, conf)
|
||||
base = base.sons[0]
|
||||
getNullValueAux(t.n, result)
|
||||
getNullValueAux(t.n, result, conf)
|
||||
of tyArray:
|
||||
result = newNodeIT(nkBracket, info, t)
|
||||
for i in countup(0, int(lengthOrd(t)) - 1):
|
||||
addSon(result, getNullValue(elemType(t), info))
|
||||
addSon(result, getNullValue(elemType(t), info, conf))
|
||||
of tyTuple:
|
||||
result = newNodeIT(nkTupleConstr, info, t)
|
||||
for i in countup(0, sonsLen(t) - 1):
|
||||
addSon(result, getNullValue(t.sons[i], info))
|
||||
addSon(result, getNullValue(t.sons[i], info, conf))
|
||||
of tySet:
|
||||
result = newNodeIT(nkCurly, info, t)
|
||||
of tyOpt:
|
||||
@@ -1588,7 +1588,7 @@ proc getNullValue(typ: PType, info: TLineInfo): PNode =
|
||||
of tySequence:
|
||||
result = newNodeIT(nkBracket, info, t)
|
||||
else:
|
||||
globalError(info, "cannot create null element for: " & $t.kind)
|
||||
globalError(conf, info, "cannot create null element for: " & $t.kind)
|
||||
|
||||
proc ldNullOpcode(t: PType): TOpcode =
|
||||
assert t != nil
|
||||
@@ -1602,7 +1602,7 @@ proc genVarSection(c: PCtx; n: PNode) =
|
||||
for i in 0 .. a.len-3:
|
||||
if not a[i].sym.isGlobal: setSlot(c, a[i].sym)
|
||||
checkCanEval(c, a[i])
|
||||
c.gen(lowerTupleUnpacking(a, c.getOwner))
|
||||
c.gen(lowerTupleUnpacking(c.graph, a, c.getOwner))
|
||||
elif a.sons[0].kind == nkSym:
|
||||
let s = a.sons[0].sym
|
||||
checkCanEval(c, a.sons[0])
|
||||
@@ -1610,7 +1610,7 @@ proc genVarSection(c: PCtx; n: PNode) =
|
||||
if s.position == 0:
|
||||
if sfImportc in s.flags: c.importcSym(a.info, s)
|
||||
else:
|
||||
let sa = getNullValue(s.typ, a.info)
|
||||
let sa = getNullValue(s.typ, a.info, c.config)
|
||||
#if s.ast.isNil: getNullValue(s.typ, a.info)
|
||||
#else: canonValue(s.ast)
|
||||
assert sa.kind != nkCall
|
||||
@@ -1652,7 +1652,7 @@ proc genArrayConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||
if dest < 0: dest = c.getTemp(n.typ)
|
||||
c.gABx(n, opcLdNull, dest, c.genType(n.typ))
|
||||
|
||||
let intType = getSysType(tyInt)
|
||||
let intType = getSysType(c.graph, n.info, tyInt)
|
||||
let seqType = n.typ.skipTypes(abstractVar-{tyTypeDesc})
|
||||
if seqType.kind == tySequence:
|
||||
var tmp = c.getTemp(intType)
|
||||
@@ -1696,13 +1696,13 @@ proc genObjConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||
for i in 1..<n.len:
|
||||
let it = n.sons[i]
|
||||
if it.kind == nkExprColonExpr and it.sons[0].kind == nkSym:
|
||||
let idx = genField(it.sons[0])
|
||||
let idx = genField(c, it.sons[0])
|
||||
let tmp = c.genx(it.sons[1])
|
||||
c.preventFalseAlias(it.sons[1], whichAsgnOpc(it.sons[1], opcWrObj),
|
||||
dest, idx, tmp)
|
||||
c.freeTemp(tmp)
|
||||
else:
|
||||
globalError(n.info, "invalid object constructor")
|
||||
globalError(c.config, n.info, "invalid object constructor")
|
||||
|
||||
proc genTupleConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||
if dest < 0: dest = c.getTemp(n.typ)
|
||||
@@ -1711,7 +1711,7 @@ proc genTupleConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||
for i in 0..<n.len:
|
||||
let it = n.sons[i]
|
||||
if it.kind == nkExprColonExpr:
|
||||
let idx = genField(it.sons[0])
|
||||
let idx = genField(c, it.sons[0])
|
||||
let tmp = c.genx(it.sons[1])
|
||||
c.preventFalseAlias(it.sons[1], whichAsgnOpc(it.sons[1], opcWrObj),
|
||||
dest, idx, tmp)
|
||||
@@ -1786,9 +1786,9 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
if c.prc.sym != nil and c.prc.sym.kind == skMacro:
|
||||
genRdVar(c, n, dest, flags)
|
||||
else:
|
||||
globalError(n.info, errGenerated, "cannot generate code for: " & s.name.s)
|
||||
globalError(c.config, n.info, "cannot generate code for: " & s.name.s)
|
||||
else:
|
||||
globalError(n.info, errGenerated, "cannot generate code for: " & s.name.s)
|
||||
globalError(c.config, n.info, "cannot generate code for: " & s.name.s)
|
||||
of nkCallKinds:
|
||||
if n.sons[0].kind == nkSym:
|
||||
let s = n.sons[0].sym
|
||||
@@ -1812,10 +1812,10 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
genLit(c, n, dest)
|
||||
of nkUIntLit..pred(nkNilLit): genLit(c, n, dest)
|
||||
of nkNilLit:
|
||||
if not n.typ.isEmptyType: genLit(c, getNullValue(n.typ, n.info), dest)
|
||||
else: unused(n, dest)
|
||||
if not n.typ.isEmptyType: genLit(c, getNullValue(n.typ, n.info, c.config), dest)
|
||||
else: unused(c, n, dest)
|
||||
of nkAsgn, nkFastAsgn:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
genAsgn(c, n.sons[0], n.sons[1], n.kind == nkAsgn)
|
||||
of nkDotExpr: genObjAccess(c, n, dest, flags)
|
||||
of nkCheckedFieldExpr: genCheckedObjAccess(c, n, dest, flags)
|
||||
@@ -1828,20 +1828,20 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
gen(c, n.sons[0].sons[1], dest)
|
||||
of nkCaseStmt: genCase(c, n, dest)
|
||||
of nkWhileStmt:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
genWhile(c, n)
|
||||
of nkBlockExpr, nkBlockStmt: genBlock(c, n, dest)
|
||||
of nkReturnStmt:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
genReturn(c, n)
|
||||
of nkRaiseStmt:
|
||||
genRaise(c, n)
|
||||
of nkBreakStmt:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
genBreak(c, n)
|
||||
of nkTryStmt: genTry(c, n, dest)
|
||||
of nkStmtList:
|
||||
#unused(n, dest)
|
||||
#unused(c, n, dest)
|
||||
# XXX Fix this bug properly, lexim triggers it
|
||||
for x in n: gen(c, x)
|
||||
of nkStmtListExpr:
|
||||
@@ -1851,17 +1851,17 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
of nkPragmaBlock:
|
||||
gen(c, n.lastSon, dest, flags)
|
||||
of nkDiscardStmt:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
gen(c, n.sons[0])
|
||||
of nkHiddenStdConv, nkHiddenSubConv, nkConv:
|
||||
genConv(c, n, n.sons[1], dest)
|
||||
of nkObjDownConv:
|
||||
genConv(c, n, n.sons[0], dest)
|
||||
of nkVarSection, nkLetSection:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
genVarSection(c, n)
|
||||
of declarativeDefs, nkMacroDef:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
of nkLambdaKinds:
|
||||
#let s = n.sons[namePos].sym
|
||||
#discard genProc(c, s)
|
||||
@@ -1881,7 +1881,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
dest = tmp0
|
||||
of nkEmpty, nkCommentStmt, nkTypeSection, nkConstSection, nkPragma,
|
||||
nkTemplateDef, nkIncludeStmt, nkImportStmt, nkFromStmt:
|
||||
unused(n, dest)
|
||||
unused(c, n, dest)
|
||||
of nkStringToCString, nkCStringToString:
|
||||
gen(c, n.sons[0], dest)
|
||||
of nkBracket: genArrayConstr(c, n, dest)
|
||||
@@ -1898,7 +1898,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
of nkComesFrom:
|
||||
discard "XXX to implement for better stack traces"
|
||||
else:
|
||||
globalError(n.info, errGenerated, "cannot generate VM code for " & $n)
|
||||
globalError(c.config, n.info, "cannot generate VM code for " & $n)
|
||||
|
||||
proc removeLastEof(c: PCtx) =
|
||||
let last = c.code.len-1
|
||||
@@ -1915,7 +1915,7 @@ proc genStmt*(c: PCtx; n: PNode): int =
|
||||
c.gen(n, d)
|
||||
c.gABC(n, opcEof)
|
||||
if d >= 0:
|
||||
globalError(n.info, errGenerated, "VM problem: dest register is set")
|
||||
globalError(c.config, n.info, "VM problem: dest register is set")
|
||||
|
||||
proc genExpr*(c: PCtx; n: PNode, requiresValue = true): int =
|
||||
c.removeLastEof
|
||||
@@ -1924,7 +1924,7 @@ proc genExpr*(c: PCtx; n: PNode, requiresValue = true): int =
|
||||
c.gen(n, d)
|
||||
if d < 0:
|
||||
if requiresValue:
|
||||
globalError(n.info, errGenerated, "VM problem: dest register is not set")
|
||||
globalError(c.config, n.info, "VM problem: dest register is not set")
|
||||
d = 0
|
||||
c.gABC(n, opcEof, d)
|
||||
|
||||
@@ -1939,7 +1939,7 @@ proc genParams(c: PCtx; params: PNode) =
|
||||
c.prc.maxSlots = max(params.len, 1)
|
||||
|
||||
proc finalJumpTarget(c: PCtx; pc, diff: int) =
|
||||
internalAssert(-0x7fff < diff and diff < 0x7fff)
|
||||
internalAssert(c.config, -0x7fff < diff and diff < 0x7fff)
|
||||
let oldInstr = c.code[pc]
|
||||
# opcode and regA stay the same:
|
||||
c.code[pc] = ((oldInstr.uint32 and 0xffff'u32).uint32 or
|
||||
|
||||
@@ -9,7 +9,8 @@
|
||||
|
||||
## Implements marshaling for the VM.
|
||||
|
||||
import streams, json, intsets, tables, ast, astalgo, idents, types, msgs
|
||||
import streams, json, intsets, tables, ast, astalgo, idents, types, msgs,
|
||||
options
|
||||
|
||||
proc ptrToInt(x: PNode): int {.inline.} =
|
||||
result = cast[int](x) # don't skip alignment
|
||||
@@ -28,37 +29,38 @@ proc getField(n: PNode; position: int): PSym =
|
||||
of nkOfBranch, nkElse:
|
||||
result = getField(lastSon(n.sons[i]), position)
|
||||
if result != nil: return
|
||||
else: internalError(n.info, "getField(record case branch)")
|
||||
else: discard
|
||||
of nkSym:
|
||||
if n.sym.position == position: result = n.sym
|
||||
else: discard
|
||||
|
||||
proc storeAny(s: var string; t: PType; a: PNode; stored: var IntSet)
|
||||
proc storeAny(s: var string; t: PType; a: PNode; stored: var IntSet; conf: ConfigRef)
|
||||
|
||||
proc storeObj(s: var string; typ: PType; x: PNode; stored: var IntSet) =
|
||||
internalAssert x.kind == nkObjConstr
|
||||
proc storeObj(s: var string; typ: PType; x: PNode; stored: var IntSet; conf: ConfigRef) =
|
||||
assert x.kind == nkObjConstr
|
||||
let start = 1
|
||||
for i in countup(start, sonsLen(x) - 1):
|
||||
if i > start: s.add(", ")
|
||||
var it = x.sons[i]
|
||||
if it.kind == nkExprColonExpr:
|
||||
internalAssert it.sons[0].kind == nkSym
|
||||
let field = it.sons[0].sym
|
||||
s.add(escapeJson(field.name.s))
|
||||
s.add(": ")
|
||||
storeAny(s, field.typ, it.sons[1], stored)
|
||||
if it.sons[0].kind == nkSym:
|
||||
let field = it.sons[0].sym
|
||||
s.add(escapeJson(field.name.s))
|
||||
s.add(": ")
|
||||
storeAny(s, field.typ, it.sons[1], stored, conf)
|
||||
elif typ.n != nil:
|
||||
let field = getField(typ.n, i)
|
||||
s.add(escapeJson(field.name.s))
|
||||
s.add(": ")
|
||||
storeAny(s, field.typ, it, stored)
|
||||
storeAny(s, field.typ, it, stored, conf)
|
||||
|
||||
proc skipColon*(n: PNode): PNode =
|
||||
result = n
|
||||
if n.kind == nkExprColonExpr:
|
||||
result = n.sons[1]
|
||||
|
||||
proc storeAny(s: var string; t: PType; a: PNode; stored: var IntSet) =
|
||||
proc storeAny(s: var string; t: PType; a: PNode; stored: var IntSet;
|
||||
conf: ConfigRef) =
|
||||
case t.kind
|
||||
of tyNone: assert false
|
||||
of tyBool: s.add($(a.intVal != 0))
|
||||
@@ -74,7 +76,7 @@ proc storeAny(s: var string; t: PType; a: PNode; stored: var IntSet) =
|
||||
s.add("[")
|
||||
for i in 0 .. a.len-1:
|
||||
if i > 0: s.add(", ")
|
||||
storeAny(s, t.elemType, a[i], stored)
|
||||
storeAny(s, t.elemType, a[i], stored, conf)
|
||||
s.add("]")
|
||||
of tyTuple:
|
||||
s.add("{")
|
||||
@@ -82,11 +84,11 @@ proc storeAny(s: var string; t: PType; a: PNode; stored: var IntSet) =
|
||||
if i > 0: s.add(", ")
|
||||
s.add("\"Field" & $i)
|
||||
s.add("\": ")
|
||||
storeAny(s, t.sons[i], a[i].skipColon, stored)
|
||||
storeAny(s, t.sons[i], a[i].skipColon, stored, conf)
|
||||
s.add("}")
|
||||
of tyObject:
|
||||
s.add("{")
|
||||
storeObj(s, t, a, stored)
|
||||
storeObj(s, t, a, stored, conf)
|
||||
s.add("}")
|
||||
of tySet:
|
||||
s.add("[")
|
||||
@@ -94,15 +96,16 @@ proc storeAny(s: var string; t: PType; a: PNode; stored: var IntSet) =
|
||||
if i > 0: s.add(", ")
|
||||
if a[i].kind == nkRange:
|
||||
var x = copyNode(a[i][0])
|
||||
storeAny(s, t.lastSon, x, stored)
|
||||
storeAny(s, t.lastSon, x, stored, conf)
|
||||
while x.intVal+1 <= a[i][1].intVal:
|
||||
s.add(", ")
|
||||
storeAny(s, t.lastSon, x, stored)
|
||||
storeAny(s, t.lastSon, x, stored, conf)
|
||||
inc x.intVal
|
||||
else:
|
||||
storeAny(s, t.lastSon, a[i], stored)
|
||||
storeAny(s, t.lastSon, a[i], stored, conf)
|
||||
s.add("]")
|
||||
of tyRange, tyGenericInst, tyAlias, tySink: storeAny(s, t.lastSon, a, stored)
|
||||
of tyRange, tyGenericInst, tyAlias, tySink:
|
||||
storeAny(s, t.lastSon, a, stored, conf)
|
||||
of tyEnum:
|
||||
# we need a slow linear search because of enums with holes:
|
||||
for e in items(t.n):
|
||||
@@ -121,7 +124,7 @@ proc storeAny(s: var string; t: PType; a: PNode; stored: var IntSet) =
|
||||
s.add("[")
|
||||
s.add($x.ptrToInt)
|
||||
s.add(", ")
|
||||
storeAny(s, t.lastSon, a, stored)
|
||||
storeAny(s, t.lastSon, a, stored, conf)
|
||||
s.add("]")
|
||||
of tyString, tyCString:
|
||||
if a.kind == nkNilLit or a.strVal.isNil: s.add("null")
|
||||
@@ -129,14 +132,15 @@ proc storeAny(s: var string; t: PType; a: PNode; stored: var IntSet) =
|
||||
of tyInt..tyInt64, tyUInt..tyUInt64: s.add($a.intVal)
|
||||
of tyFloat..tyFloat128: s.add($a.floatVal)
|
||||
else:
|
||||
internalError a.info, "cannot marshal at compile-time " & t.typeToString
|
||||
internalError conf, a.info, "cannot marshal at compile-time " & t.typeToString
|
||||
|
||||
proc storeAny*(s: var string; t: PType; a: PNode) =
|
||||
proc storeAny*(s: var string; t: PType; a: PNode; conf: ConfigRef) =
|
||||
var stored = initIntSet()
|
||||
storeAny(s, t, a, stored)
|
||||
storeAny(s, t, a, stored, conf)
|
||||
|
||||
proc loadAny(p: var JsonParser, t: PType,
|
||||
tab: var Table[BiggestInt, PNode]): PNode =
|
||||
tab: var Table[BiggestInt, PNode];
|
||||
conf: ConfigRef): PNode =
|
||||
case t.kind
|
||||
of tyNone: assert false
|
||||
of tyBool:
|
||||
@@ -170,7 +174,7 @@ proc loadAny(p: var JsonParser, t: PType,
|
||||
next(p)
|
||||
result = newNode(nkBracket)
|
||||
while p.kind != jsonArrayEnd and p.kind != jsonEof:
|
||||
result.add loadAny(p, t.elemType, tab)
|
||||
result.add loadAny(p, t.elemType, tab, conf)
|
||||
if p.kind == jsonArrayEnd: next(p)
|
||||
else: raiseParseErr(p, "']' end of array expected")
|
||||
of tySequence:
|
||||
@@ -182,7 +186,7 @@ proc loadAny(p: var JsonParser, t: PType,
|
||||
next(p)
|
||||
result = newNode(nkBracket)
|
||||
while p.kind != jsonArrayEnd and p.kind != jsonEof:
|
||||
result.add loadAny(p, t.elemType, tab)
|
||||
result.add loadAny(p, t.elemType, tab, conf)
|
||||
if p.kind == jsonArrayEnd: next(p)
|
||||
else: raiseParseErr(p, "")
|
||||
else:
|
||||
@@ -198,7 +202,7 @@ proc loadAny(p: var JsonParser, t: PType,
|
||||
next(p)
|
||||
if i >= t.len:
|
||||
raiseParseErr(p, "too many fields to tuple type " & typeToString(t))
|
||||
result.add loadAny(p, t.sons[i], tab)
|
||||
result.add loadAny(p, t.sons[i], tab, conf)
|
||||
inc i
|
||||
if p.kind == jsonObjectEnd: next(p)
|
||||
else: raiseParseErr(p, "'}' end of object expected")
|
||||
@@ -220,7 +224,7 @@ proc loadAny(p: var JsonParser, t: PType,
|
||||
setLen(result.sons, pos + 1)
|
||||
let fieldNode = newNode(nkExprColonExpr)
|
||||
fieldNode.addSon(newSymNode(newSym(skField, ident, nil, unknownLineInfo())))
|
||||
fieldNode.addSon(loadAny(p, field.typ, tab))
|
||||
fieldNode.addSon(loadAny(p, field.typ, tab, conf))
|
||||
result.sons[pos] = fieldNode
|
||||
if p.kind == jsonObjectEnd: next(p)
|
||||
else: raiseParseErr(p, "'}' end of object expected")
|
||||
@@ -229,7 +233,7 @@ proc loadAny(p: var JsonParser, t: PType,
|
||||
next(p)
|
||||
result = newNode(nkCurly)
|
||||
while p.kind != jsonArrayEnd and p.kind != jsonEof:
|
||||
result.add loadAny(p, t.lastSon, tab)
|
||||
result.add loadAny(p, t.lastSon, tab, conf)
|
||||
next(p)
|
||||
if p.kind == jsonArrayEnd: next(p)
|
||||
else: raiseParseErr(p, "']' end of array expected")
|
||||
@@ -248,7 +252,7 @@ proc loadAny(p: var JsonParser, t: PType,
|
||||
if p.kind == jsonInt:
|
||||
let idx = p.getInt
|
||||
next(p)
|
||||
result = loadAny(p, t.lastSon, tab)
|
||||
result = loadAny(p, t.lastSon, tab, conf)
|
||||
tab[idx] = result
|
||||
else: raiseParseErr(p, "index for ref type expected")
|
||||
if p.kind == jsonArrayEnd: next(p)
|
||||
@@ -275,14 +279,15 @@ proc loadAny(p: var JsonParser, t: PType,
|
||||
next(p)
|
||||
return
|
||||
raiseParseErr(p, "float expected")
|
||||
of tyRange, tyGenericInst, tyAlias, tySink: result = loadAny(p, t.lastSon, tab)
|
||||
of tyRange, tyGenericInst, tyAlias, tySink:
|
||||
result = loadAny(p, t.lastSon, tab, conf)
|
||||
else:
|
||||
internalError "cannot marshal at compile-time " & t.typeToString
|
||||
internalError conf, "cannot marshal at compile-time " & t.typeToString
|
||||
|
||||
proc loadAny*(s: string; t: PType): PNode =
|
||||
proc loadAny*(s: string; t: PType; conf: ConfigRef): PNode =
|
||||
var tab = initTable[BiggestInt, PNode]()
|
||||
var p: JsonParser
|
||||
open(p, newStringStream(s), "unknown file")
|
||||
next(p)
|
||||
result = loadAny(p, t, tab)
|
||||
result = loadAny(p, t, tab, conf)
|
||||
close(p)
|
||||
|
||||
Reference in New Issue
Block a user