mirror of
https://github.com/nim-lang/Nim.git
synced 2025-12-28 17:04:41 +00:00
first steps in adding template/macro calls to stack traces
This commit is contained in:
@@ -62,8 +62,8 @@ type
|
||||
nkTripleStrLit, # a triple string literal """
|
||||
nkNilLit, # the nil literal
|
||||
# end of atoms
|
||||
nkMetaNode_Obsolete, # difficult to explain; represents itself
|
||||
# (used for macros)
|
||||
nkComesFrom, # "comes from" template/macro information for
|
||||
# better stack trace generation
|
||||
nkDotCall, # used to temporarily flag a nkCall node;
|
||||
# this is used
|
||||
# for transforming ``s.len`` to ``len(s)``
|
||||
|
||||
@@ -1982,10 +1982,35 @@ proc genComplexConst(p: BProc, sym: PSym, d: var TLoc) =
|
||||
assert((sym.loc.r != nil) and (sym.loc.t != nil))
|
||||
putLocIntoDest(p, d, sym.loc)
|
||||
|
||||
template genStmtListExprImpl(exprOrStmt) {.dirty.} =
|
||||
#let hasNimFrame = magicsys.getCompilerProc("nimFrame") != nil
|
||||
let hasNimFrame = p.prc != nil and
|
||||
sfSystemModule notin p.module.module.flags and
|
||||
optStackTrace in p.prc.options
|
||||
var frameName: Rope = nil
|
||||
for i in 0 .. n.len - 2:
|
||||
let it = n[i]
|
||||
if it.kind == nkComesFrom:
|
||||
if hasNimFrame and frameName == nil:
|
||||
inc p.labels
|
||||
frameName = "FR" & rope(p.labels) & "_"
|
||||
let theMacro = it[0].sym
|
||||
add p.s(cpsStmts), initFrameNoDebug(p, frameName,
|
||||
makeCString theMacro.name.s,
|
||||
theMacro.info.quotedFilename, it.info.line)
|
||||
else:
|
||||
genStmts(p, it)
|
||||
if n.len > 0: exprOrStmt
|
||||
if frameName != nil:
|
||||
add p.s(cpsStmts), deinitFrameNoDebug(p, frameName)
|
||||
|
||||
proc genStmtListExpr(p: BProc, n: PNode, d: var TLoc) =
|
||||
var length = sonsLen(n)
|
||||
for i in countup(0, length - 2): genStmts(p, n.sons[i])
|
||||
if length > 0: expr(p, n.sons[length - 1], d)
|
||||
genStmtListExprImpl:
|
||||
expr(p, n[n.len - 1], d)
|
||||
|
||||
proc genStmtList(p: BProc, n: PNode) =
|
||||
genStmtListExprImpl:
|
||||
genStmts(p, n[n.len - 1])
|
||||
|
||||
proc upConv(p: BProc, n: PNode, d: var TLoc) =
|
||||
var a: TLoc
|
||||
@@ -2184,8 +2209,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
|
||||
of nkCheckedFieldExpr: genCheckedRecordField(p, n, d)
|
||||
of nkBlockExpr, nkBlockStmt: genBlock(p, n, d)
|
||||
of nkStmtListExpr: genStmtListExpr(p, n, d)
|
||||
of nkStmtList:
|
||||
for i in countup(0, sonsLen(n) - 1): genStmts(p, n.sons[i])
|
||||
of nkStmtList: genStmtList(p, n)
|
||||
of nkIfExpr, nkIfStmt: genIf(p, n, d)
|
||||
of nkWhen:
|
||||
# This should be a "when nimvm" node.
|
||||
|
||||
@@ -564,9 +564,6 @@ proc genBreakStmt(p: BProc, t: PNode) =
|
||||
genLineDir(p, t)
|
||||
lineF(p, cpsStmts, "goto $1;$n", [label])
|
||||
|
||||
proc getRaiseFrmt(p: BProc): string =
|
||||
result = "#raiseException((#Exception*)$1, $2);$n"
|
||||
|
||||
proc genRaiseStmt(p: BProc, t: PNode) =
|
||||
if p.inExceptBlock > 0:
|
||||
# if the current try stmt have a finally block,
|
||||
@@ -580,7 +577,8 @@ proc genRaiseStmt(p: BProc, t: PNode) =
|
||||
var e = rdLoc(a)
|
||||
var typ = skipTypes(t.sons[0].typ, abstractPtrs)
|
||||
genLineDir(p, t)
|
||||
lineCg(p, cpsStmts, getRaiseFrmt(p), [e, makeCString(typ.sym.name.s)])
|
||||
lineCg(p, cpsStmts, "#raiseException((#Exception*)$1, $2);$n",
|
||||
[e, makeCString(typ.sym.name.s)])
|
||||
else:
|
||||
genLineDir(p, t)
|
||||
# reraise the last exception:
|
||||
|
||||
@@ -493,7 +493,32 @@ proc initLocExprSingleUse(p: BProc, e: PNode, result: var TLoc) =
|
||||
proc lenField(p: BProc): Rope =
|
||||
result = rope(if p.module.compileToCpp: "len" else: "Sup.len")
|
||||
|
||||
include ccgcalls, "ccgstmts.nim", "ccgexprs.nim"
|
||||
include ccgcalls, "ccgstmts.nim"
|
||||
|
||||
proc initFrame(p: BProc, procname, filename: Rope): Rope =
|
||||
discard cgsym(p.module, "nimFrame")
|
||||
if p.maxFrameLen > 0:
|
||||
discard cgsym(p.module, "VarSlot")
|
||||
result = rfmt(nil, "\tnimfrs_($1, $2, $3, $4);$n",
|
||||
procname, filename, p.maxFrameLen.rope,
|
||||
p.blocks[0].frameLen.rope)
|
||||
else:
|
||||
result = rfmt(nil, "\tnimfr_($1, $2);$n", procname, filename)
|
||||
|
||||
proc initFrameNoDebug(p: BProc; frame, procname, filename: Rope; line: int): Rope =
|
||||
discard cgsym(p.module, "nimFrame")
|
||||
addf(p.blocks[0].sections[cpsLocals], "TFrame $1;$n", [frame])
|
||||
result = rfmt(nil, "\t$1.procname = $2; $1.filename = $3; " &
|
||||
" $1.line = $4; $1.len = -1; nimFrame(&$1);$n",
|
||||
frame, procname, filename, rope(line))
|
||||
|
||||
proc deinitFrameNoDebug(p: BProc; frame: Rope): Rope =
|
||||
result = rfmt(p.module, "\t#popFrameOfAddr(&$1);$n", frame)
|
||||
|
||||
proc deinitFrame(p: BProc): Rope =
|
||||
result = rfmt(p.module, "\t#popFrame();$n")
|
||||
|
||||
include ccgexprs
|
||||
|
||||
# ----------------------------- dynamic library handling -----------------
|
||||
# We don't finalize dynamic libs as the OS does this for us.
|
||||
@@ -600,7 +625,7 @@ proc symInDynamicLibPartial(m: BModule, sym: PSym) =
|
||||
sym.typ.sym = nil # generate a new name
|
||||
|
||||
proc cgsym(m: BModule, name: string): Rope =
|
||||
var sym = magicsys.getCompilerProc(name)
|
||||
let sym = magicsys.getCompilerProc(name)
|
||||
if sym != nil:
|
||||
case sym.kind
|
||||
of skProc, skFunc, skMethod, skConverter, skIterator: genProc(m, sym)
|
||||
@@ -637,19 +662,6 @@ proc generateHeaders(m: BModule) =
|
||||
add(m.s[cfsHeaders], "#undef powerpc" & tnl)
|
||||
add(m.s[cfsHeaders], "#undef unix" & tnl)
|
||||
|
||||
proc initFrame(p: BProc, procname, filename: Rope): Rope =
|
||||
discard cgsym(p.module, "nimFrame")
|
||||
if p.maxFrameLen > 0:
|
||||
discard cgsym(p.module, "VarSlot")
|
||||
result = rfmt(nil, "\tnimfrs_($1, $2, $3, $4);$n",
|
||||
procname, filename, p.maxFrameLen.rope,
|
||||
p.blocks[0].frameLen.rope)
|
||||
else:
|
||||
result = rfmt(nil, "\tnimfr_($1, $2);$n", procname, filename)
|
||||
|
||||
proc deinitFrame(p: BProc): Rope =
|
||||
result = rfmt(p.module, "\t#popFrame();$n")
|
||||
|
||||
proc closureSetup(p: BProc, prc: PSym) =
|
||||
if tfCapturesEnv notin prc.typ.flags: return
|
||||
# prc.ast[paramsPos].last contains the type we're after:
|
||||
|
||||
@@ -109,7 +109,7 @@ proc evalTemplateArgs(n: PNode, s: PSym; fromHlo: bool): PNode =
|
||||
var evalTemplateCounter* = 0
|
||||
# to prevent endless recursion in templates instantiation
|
||||
|
||||
proc wrapInComesFrom*(info: TLineInfo; res: PNode): PNode =
|
||||
proc wrapInComesFrom*(info: TLineInfo; sym: PSym; res: PNode): PNode =
|
||||
when true:
|
||||
result = res
|
||||
result.info = info
|
||||
@@ -124,8 +124,12 @@ proc wrapInComesFrom*(info: TLineInfo; res: PNode): PNode =
|
||||
if x[i].kind in nkCallKinds:
|
||||
x.sons[i].info = info
|
||||
else:
|
||||
result = newNodeI(nkPar, info)
|
||||
result = newNodeI(nkStmtListExpr, info)
|
||||
var d = newNodeI(nkComesFrom, info)
|
||||
d.add newSymNode(sym, info)
|
||||
result.add d
|
||||
result.add res
|
||||
result.typ = res.typ
|
||||
|
||||
proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym; fromHlo=false): PNode =
|
||||
inc(evalTemplateCounter)
|
||||
@@ -156,6 +160,6 @@ proc evalTemplate*(n: PNode, tmpl, genSymOwner: PSym; fromHlo=false): PNode =
|
||||
for i in countup(0, safeLen(body) - 1):
|
||||
evalTemplateAux(body.sons[i], args, ctx, result)
|
||||
result.flags.incl nfFromTemplate
|
||||
result = wrapInComesFrom(n.info, result)
|
||||
result = wrapInComesFrom(n.info, tmpl, result)
|
||||
dec(evalTemplateCounter)
|
||||
|
||||
|
||||
@@ -2369,6 +2369,8 @@ proc gen(p: PProc, n: PNode, r: var TCompRes) =
|
||||
of nkGotoState, nkState:
|
||||
internalError(n.info, "first class iterators not implemented")
|
||||
of nkPragmaBlock: gen(p, n.lastSon, r)
|
||||
of nkComesFrom:
|
||||
discard "XXX to implement for better stack traces"
|
||||
else: internalError(n.info, "gen: unknown node type: " & $n.kind)
|
||||
|
||||
var globals: PGlobals
|
||||
|
||||
@@ -723,7 +723,7 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
|
||||
result = accessViaEnvParam(n, owner)
|
||||
else:
|
||||
result = accessViaEnvVar(n, owner, d, c)
|
||||
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit,
|
||||
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkComesFrom,
|
||||
nkTemplateDef, nkTypeSection:
|
||||
discard
|
||||
of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef:
|
||||
|
||||
@@ -1397,8 +1397,8 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
|
||||
put(g, tkBracketRi, "]")
|
||||
of nkTupleClassTy:
|
||||
put(g, tkTuple, "tuple")
|
||||
of nkMetaNode_Obsolete:
|
||||
put(g, tkParLe, "(META|")
|
||||
of nkComesFrom:
|
||||
put(g, tkParLe, "(ComesFrom|")
|
||||
gsub(g, n, 0)
|
||||
put(g, tkParRi, ")")
|
||||
of nkGotoState, nkState:
|
||||
|
||||
@@ -423,7 +423,7 @@ proc semMacroExpr(c: PContext, n, nOrig: PNode, sym: PSym,
|
||||
result = evalMacroCall(c.module, c.cache, n, nOrig, sym)
|
||||
if efNoSemCheck notin flags:
|
||||
result = semAfterMacroCall(c, n, result, sym, flags)
|
||||
result = wrapInComesFrom(nOrig.info, result)
|
||||
result = wrapInComesFrom(nOrig.info, sym, result)
|
||||
popInfoContext()
|
||||
|
||||
proc forceBool(c: PContext, n: PNode): PNode =
|
||||
|
||||
@@ -2380,6 +2380,7 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode =
|
||||
if n.len != 1 and n.len != 2: illFormedAst(n)
|
||||
for i in 0 ..< n.len:
|
||||
n.sons[i] = semExpr(c, n.sons[i])
|
||||
of nkComesFrom: discard "ignore the comes from information for now"
|
||||
else:
|
||||
localError(n.info, errInvalidExpressionX,
|
||||
renderTree(n, {renderNoComments}))
|
||||
|
||||
@@ -655,5 +655,8 @@ proc getConstExpr(m: PSym, n: PNode): PNode =
|
||||
result.typ = n.typ
|
||||
of nkBracketExpr: result = foldArrayAccess(m, n)
|
||||
of nkDotExpr: result = foldFieldAccess(m, n)
|
||||
of nkStmtListExpr:
|
||||
if n.len == 2 and n[0].kind == nkComesFrom:
|
||||
result = getConstExpr(m, n[1])
|
||||
else:
|
||||
discard
|
||||
|
||||
@@ -186,7 +186,7 @@ proc semGenericStmt(c: PContext, n: PNode,
|
||||
let a = n.sym
|
||||
let b = getGenSym(c, a)
|
||||
if b != a: n.sym = b
|
||||
of nkEmpty, succ(nkSym)..nkNilLit:
|
||||
of nkEmpty, succ(nkSym)..nkNilLit, nkComesFrom:
|
||||
# see tests/compile/tgensymgeneric.nim:
|
||||
# We need to open the gensym'ed symbol again so that the instantiation
|
||||
# creates a fresh copy; but this is wrong the very first reason for gensym
|
||||
|
||||
@@ -331,7 +331,7 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode =
|
||||
of nkMixinStmt:
|
||||
if c.scopeN > 0: result = semTemplBodySons(c, n)
|
||||
else: result = semMixinStmt(c.c, n, c.toMixin)
|
||||
of nkEmpty, nkSym..nkNilLit:
|
||||
of nkEmpty, nkSym..nkNilLit, nkComesFrom:
|
||||
discard
|
||||
of nkIfStmt:
|
||||
for i in countup(0, sonsLen(n)-1):
|
||||
@@ -528,7 +528,7 @@ proc semTemplBodyDirty(c: var TemplCtx, n: PNode): PNode =
|
||||
result = semTemplBodyDirty(c, n.sons[0])
|
||||
of nkBindStmt:
|
||||
result = semBindStmt(c.c, n, c.toBind)
|
||||
of nkEmpty, nkSym..nkNilLit:
|
||||
of nkEmpty, nkSym..nkNilLit, nkComesFrom:
|
||||
discard
|
||||
else:
|
||||
# dotExpr is ambiguous: note that we explicitly allow 'x.TemplateParam',
|
||||
|
||||
@@ -791,7 +791,7 @@ proc transform(c: PTransf, n: PNode): PTransNode =
|
||||
case n.kind
|
||||
of nkSym:
|
||||
result = transformSym(c, n)
|
||||
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit:
|
||||
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit, nkComesFrom:
|
||||
# nothing to be done for leaves:
|
||||
result = PTransNode(n)
|
||||
of nkBracketExpr: result = transformArrayAccess(c, n)
|
||||
|
||||
@@ -1847,6 +1847,8 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||
globalError(n.info, errGenerated, "VM is not allowed to 'cast'")
|
||||
of nkTypeOfExpr:
|
||||
genTypeLit(c, n.typ, dest)
|
||||
of nkComesFrom:
|
||||
discard "XXX to implement for better stack traces"
|
||||
else:
|
||||
globalError(n.info, errGenerated, "cannot generate VM code for " & $n)
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ type
|
||||
nnkInt16Lit, nnkInt32Lit, nnkInt64Lit, nnkUIntLit, nnkUInt8Lit,
|
||||
nnkUInt16Lit, nnkUInt32Lit, nnkUInt64Lit, nnkFloatLit,
|
||||
nnkFloat32Lit, nnkFloat64Lit, nnkFloat128Lit, nnkStrLit, nnkRStrLit,
|
||||
nnkTripleStrLit, nnkNilLit, nnkMetaNode, nnkDotCall,
|
||||
nnkTripleStrLit, nnkNilLit, nnkComesFrom, nnkDotCall,
|
||||
nnkCommand, nnkCall, nnkCallStrLit, nnkInfix,
|
||||
nnkPrefix, nnkPostfix, nnkHiddenCallConv,
|
||||
nnkExprEqExpr,
|
||||
|
||||
@@ -70,6 +70,18 @@ proc getFrame*(): PFrame {.compilerRtl, inl.} = framePtr
|
||||
proc popFrame {.compilerRtl, inl.} =
|
||||
framePtr = framePtr.prev
|
||||
|
||||
when false:
|
||||
proc popFrameOfAddr(s: PFrame) {.compilerRtl.} =
|
||||
var it = framePtr
|
||||
if it == s:
|
||||
framePtr = framePtr.prev
|
||||
else:
|
||||
while it != nil:
|
||||
if it == s:
|
||||
framePtr = it.prev
|
||||
break
|
||||
it = it.prev
|
||||
|
||||
proc setFrame*(s: PFrame) {.compilerRtl, inl.} =
|
||||
framePtr = s
|
||||
|
||||
|
||||
Reference in New Issue
Block a user