Less ropes (#10979)

* convert ropecg to a macro
* fewer intermediate ropes
This commit is contained in:
Arne Döring 2019-04-11 09:48:10 +02:00 • committed by Andreas Rumpf
commit 1da98b1636
7 changed files with 451 additions and 349 deletions

View file

@ -44,8 +44,19 @@ proc inExceptBlockLen(p: BProc): int =
for x in p.nestedTryStmts:
if x.inExcept: result.inc
proc startBlock(p: BProc, start: FormatStr = "{$n",
args: varargs[Rope]): int {.discardable.}
proc startBlockInternal(p: BProc): int {.discardable.} =
inc(p.labels)
result = len(p.blocks)
setLen(p.blocks, result + 1)
p.blocks[result].id = p.labels
p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16
p.blocks[result].nestedExceptStmts = p.inExceptBlockLen.int16
template startBlock(p: BProc, start: FormatStr = "{$n",
args: varargs[Rope]): int =
lineCg(p, cpsStmts, start, args)
startBlockInternal(p)
proc endBlock(p: BProc)
proc genVarTuple(p: BProc, n: PNode) =
@ -70,7 +81,7 @@ proc genVarTuple(p: BProc, n: PNode) =
if forHcr:
# check with the boolean if the initializing code for the tuple should be ran
lineCg(p, cpsStmts, "if ($1)$n", hcrCond)
lineCg(p, cpsStmts, "if ($1)$n", [hcrCond])
startBlock(p)
defer:
if forHcr:
@ -80,10 +91,10 @@ proc genVarTuple(p: BProc, n: PNode) =
# insert the registration of the globals for the different parts of the tuple at the
# start of the current scope (after they have been iterated) and init a boolean to
# check if any of them is newly introduced and the initializing code has to be ran
lineCg(p, cpsLocals, "NIM_BOOL $1 = NIM_FALSE;$n", hcrCond)
lineCg(p, cpsLocals, "NIM_BOOL $1 = NIM_FALSE;$n", [hcrCond])
for curr in hcrGlobals:
lineCg(p, cpsLocals, "$1 |= hcrRegisterGlobal($4, \"$2\", sizeof($3), $5, (void**)&$2);$N",
hcrCond, curr.loc.r, rdLoc(curr.loc), getModuleDllPath(p.module, n.sons[0].sym), curr.tp)
[hcrCond, curr.loc.r, rdLoc(curr.loc), getModuleDllPath(p.module, n.sons[0].sym), curr.tp])
genLineDir(p, n)
initLocExpr(p, n.sons[L-1], tup)
@ -130,16 +141,6 @@ proc loadInto(p: BProc, le, ri: PNode, a: var TLoc) {.inline.} =
else:
expr(p, ri, a)
proc startBlock(p: BProc, start: FormatStr = "{$n",
args: varargs[Rope]): int {.discardable.} =
lineCg(p, cpsStmts, start, args)
inc(p.labels)
result = len(p.blocks)
setLen(p.blocks, result + 1)
p.blocks[result].id = p.labels
p.blocks[result].nestedTryStmts = p.nestedTryStmts.len.int16
p.blocks[result].nestedExceptStmts = p.inExceptBlockLen.int16
proc assignLabel(b: var TBlock): Rope {.inline.} =
b.label = "LA" & b.id.rope
result = b.label
@ -192,9 +193,9 @@ proc genState(p: BProc, n: PNode) =
let n0 = n[0]
if n0.kind == nkIntLit:
let idx = n.sons[0].intVal
linefmt(p, cpsStmts, "STATE$1: ;$n", idx.rope)
linefmt(p, cpsStmts, "STATE$1: ;$n", [idx])
elif n0.kind == nkStrLit:
linefmt(p, cpsStmts, "$1: ;$n", n0.strVal.rope)
linefmt(p, cpsStmts, "$1: ;$n", [n0.strVal])
proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
# Called by return and break stmts.
@ -207,7 +208,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
if not p.module.compileToCpp or optNoCppExceptions in p.config.globalOptions:
# Pop safe points generated by try
if not tryStmt.inExcept and not isDefined(p.config, "nimQuirky"):
linefmt(p, cpsStmts, "#popSafePoint();$n")
linefmt(p, cpsStmts, "#popSafePoint();$n", [])
# Pop this try-stmt of the list of nested trys
# so we don't infinite recurse on it in the next step.
@ -227,7 +228,7 @@ proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
# Pop exceptions that was handled by the
# except-blocks we are in
for i in countdown(howManyExcepts-1, 0):
linefmt(p, cpsStmts, "#popCurrentException();$n")
linefmt(p, cpsStmts, "#popCurrentException();$n", [])
proc genGotoState(p: BProc, n: PNode) =
# we resist the temptation to translate it into duff's device as it later
@ -352,7 +353,7 @@ proc genSingleVar(p: BProc, a: PNode) =
# put it in the locals section - mainly because of loops which
# use the var in a call to resetLoc() in the statements section
lineCg(targetProc, cpsLocals, "hcrRegisterGlobal($3, \"$1\", sizeof($2), $4, (void**)&$1);$n",
v.loc.r, rdLoc(v.loc), getModuleDllPath(p.module, v), traverseProc)
[v.loc.r, rdLoc(v.loc), getModuleDllPath(p.module, v), traverseProc])
# nothing special left to do later on - let's avoid closing and reopening blocks
forHcr = false
@ -361,7 +362,7 @@ proc genSingleVar(p: BProc, a: PNode) =
# be able to re-run it but without the top level code - just the init of globals
if forHcr:
lineCg(targetProc, cpsStmts, "if (hcrRegisterGlobal($3, \"$1\", sizeof($2), $4, (void**)&$1))$N",
v.loc.r, rdLoc(v.loc), getModuleDllPath(p.module, v), traverseProc)
[v.loc.r, rdLoc(v.loc), getModuleDllPath(p.module, v), traverseProc])
startBlock(targetProc)
defer:
if forHcr:
@ -452,7 +453,7 @@ proc genReturnStmt(p: BProc, t: PNode) =
# If we're in a finally block, and we came here by exception
# consume it before we return.
var safePoint = p.finallySafePoints[p.finallySafePoints.len-1]
linefmt(p, cpsStmts, "if ($1.status != 0) #popCurrentException();$n", safePoint)
linefmt(p, cpsStmts, "if ($1.status != 0) #popCurrentException();$n", [safePoint])
lineF(p, cpsStmts, "goto BeforeRet_;$n", [])
proc genGotoForCase(p: BProc; caseStmt: PNode) =
@ -589,7 +590,7 @@ proc genWhileStmt(p: BProc, t: PNode) =
if optProfiler in p.options:
# invoke at loop body exit:
linefmt(p, cpsStmts, "#nimProfile();$n")
linefmt(p, cpsStmts, "#nimProfile();$n", [])
endBlock(p)
dec(p.withinLoop)
@ -690,7 +691,7 @@ proc genRaiseStmt(p: BProc, t: PNode) =
lineCg(p, cpsStmts, "#raiseExceptionEx((#Exception*)$1, $2, $3, $4, $5);$n",
[e, makeCString(typ.sym.name.s),
makeCString(if p.prc != nil: p.prc.name.s else: p.module.module.name.s),
makeCString(toFileName(p.config, t.info)), rope(toLinenumber(t.info))])
makeCString(toFileName(p.config, t.info)), toLinenumber(t.info)])
if optNimV2 in p.config.globalOptions:
lineCg(p, cpsStmts, "$1 = NIM_NIL;$n", [e])
else:
@ -699,9 +700,9 @@ proc genRaiseStmt(p: BProc, t: PNode) =
if p.module.compileToCpp and optNoCppExceptions notin p.config.globalOptions:
line(p, cpsStmts, ~"throw;$n")
else:
linefmt(p, cpsStmts, "#reraiseException();$n")
linefmt(p, cpsStmts, "#reraiseException();$n", [])
proc genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
template genCaseGenericBranch(p: BProc, b: PNode, e: TLoc,
rangeFormat, eqFormat: FormatStr, labl: TLabel) =
var
x, y: TLoc
@ -731,10 +732,11 @@ proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc,
exprBlock(p, t.sons[i].sons[0], d)
result = lend
proc genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc,
template genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc,
rangeFormat, eqFormat: FormatStr,
until: int, a: TLoc): TLabel =
# generate a C-if statement for a Nim case statement
var res: TLabel
var labId = p.labels
for i in 1..until:
inc(p.labels)
@ -747,12 +749,13 @@ proc genIfForCaseUntil(p: BProc, t: PNode, d: var TLoc,
inc(p.labels)
var gotoTarget = p.labels
lineF(p, cpsStmts, "goto LA$1_;$n", [rope(gotoTarget)])
result = genCaseSecondPass(p, t, d, labId, until)
res = genCaseSecondPass(p, t, d, labId, until)
lineF(p, cpsStmts, "LA$1_: ;$n", [rope(gotoTarget)])
else:
result = genCaseSecondPass(p, t, d, labId, until)
res = genCaseSecondPass(p, t, d, labId, until)
res
proc genCaseGeneric(p: BProc, t: PNode, d: var TLoc,
template genCaseGeneric(p: BProc, t: PNode, d: var TLoc,
rangeFormat, eqFormat: FormatStr) =
var a: TLoc
initLocExpr(p, t.sons[0], a)
@ -793,7 +796,7 @@ proc genStringCase(p: BProc, t: PNode, d: var TLoc) =
# but we reserved a label, which we use later
discard
linefmt(p, cpsStmts, "switch (#hashString($1) & $2) {$n",
rdLoc(a), rope(bitMask))
[rdLoc(a), bitMask])
for j in countup(0, high(branches)):
if branches[j] != nil:
lineF(p, cpsStmts, "case $1: $n$2break;$n",
@ -895,7 +898,7 @@ proc genRestoreFrameAfterException(p: BProc) =
p.hasCurFramePointer = true
p.procSec(cpsLocals).add(ropecg(p.module, "\tTFrame* _nimCurFrame;$n", []))
p.procSec(cpsInit).add(ropecg(p.module, "\t_nimCurFrame = #getFrame();$n", []))
linefmt(p, cpsStmts, "#setFrame(_nimCurFrame);$n")
linefmt(p, cpsStmts, "#setFrame(_nimCurFrame);$n", [])
proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
# code to generate:
@ -1006,25 +1009,25 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
var safePoint: Rope
if not quirkyExceptions:
safePoint = getTempName(p.module)
linefmt(p, cpsLocals, "#TSafePoint $1;$n", safePoint)
linefmt(p, cpsStmts, "#pushSafePoint(&$1);$n", safePoint)
linefmt(p, cpsLocals, "#TSafePoint $1;$n", [safePoint])
linefmt(p, cpsStmts, "#pushSafePoint(&$1);$n", [safePoint])
if isDefined(p.config, "nimStdSetjmp"):
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint])
elif isDefined(p.config, "nimSigSetjmp"):
linefmt(p, cpsStmts, "$1.status = sigsetjmp($1.context, 0);$n", safePoint)
linefmt(p, cpsStmts, "$1.status = sigsetjmp($1.context, 0);$n", [safePoint])
elif isDefined(p.config, "nimRawSetjmp"):
linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", safePoint)
linefmt(p, cpsStmts, "$1.status = _setjmp($1.context);$n", [safePoint])
else:
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", safePoint)
linefmt(p, cpsStmts, "$1.status = setjmp($1.context);$n", [safePoint])
startBlock(p, "if ($1.status == 0) {$n", [safePoint])
var length = sonsLen(t)
add(p.nestedTryStmts, (t, false))
expr(p, t.sons[0], d)
if not quirkyExceptions:
linefmt(p, cpsStmts, "#popSafePoint();$n")
linefmt(p, cpsStmts, "#popSafePoint();$n", [])
endBlock(p)
startBlock(p, "else {$n")
linefmt(p, cpsStmts, "#popSafePoint();$n")
linefmt(p, cpsStmts, "#popSafePoint();$n", [])
genRestoreFrameAfterException(p)
elif 1 < length and t.sons[1].kind == nkExceptBranch:
startBlock(p, "if (#getCurrentException()) {$n")
@ -1041,30 +1044,28 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
if i > 1: lineF(p, cpsStmts, "else", [])
startBlock(p)
if not quirkyExceptions:
linefmt(p, cpsStmts, "$1.status = 0;$n", safePoint)
linefmt(p, cpsStmts, "$1.status = 0;$n", [safePoint])
expr(p, t.sons[i].sons[0], d)
linefmt(p, cpsStmts, "#popCurrentException();$n")
linefmt(p, cpsStmts, "#popCurrentException();$n", [])
endBlock(p)
else:
var orExpr: Rope = nil
for j in countup(0, blen - 2):
assert(t.sons[i].sons[j].kind == nkType)
if orExpr != nil: add(orExpr, "||")
let isObjFormat = if not p.module.compileToCpp:
"#isObj(#getCurrentException()->Sup.m_type, $1)"
else: "#isObj(#getCurrentException()->m_type, $1)"
let checkFor = if optNimV2 in p.config.globalOptions:
genTypeInfo2Name(p.module, t[i][j].typ)
else:
genTypeInfo(p.module, t[i][j].typ, t[i][j].info)
appcg(p.module, orExpr, isObjFormat, [checkFor])
let memberName = if p.module.compileToCpp: "m_type" else: "Sup.m_type"
appcg(p.module, orExpr, "#isObj(#getCurrentException()->$1, $2)", [memberName, checkFor])
if i > 1: line(p, cpsStmts, "else ")
startBlock(p, "if ($1) {$n", [orExpr])
if not quirkyExceptions:
linefmt(p, cpsStmts, "$1.status = 0;$n", safePoint)
linefmt(p, cpsStmts, "$1.status = 0;$n", [safePoint])
expr(p, t.sons[i].sons[blen-1], d)
linefmt(p, cpsStmts, "#popCurrentException();$n")
linefmt(p, cpsStmts, "#popCurrentException();$n", [])
endBlock(p)
inc(i)
discard pop(p.nestedTryStmts)
@ -1074,7 +1075,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
genSimpleBlock(p, t.sons[i].sons[0])
discard pop(p.finallySafePoints)
if not quirkyExceptions:
linefmt(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", safePoint)
linefmt(p, cpsStmts, "if ($1.status != 0) #reraiseException();$n", [safePoint])
proc genAsmOrEmitStmt(p: BProc, t: PNode, isAsmStmt=false): Rope =
var res = ""
@ -1169,7 +1170,7 @@ proc genBreakPoint(p: BProc, t: PNode) =
genLineDir(p, t) # BUGFIX
appcg(p.module, p.module.g.breakpoints,
"#dbgRegisterBreakpoint($1, (NCSTRING)$2, (NCSTRING)$3);$n", [
rope(toLinenumber(t.info)), makeCString(toFilename(p.config, t.info)),
toLinenumber(t.info), makeCString(toFilename(p.config, t.info)),
makeCString(name)])
proc genWatchpoint(p: BProc, n: PNode) =
@ -1212,7 +1213,7 @@ proc genDiscriminantCheck(p: BProc, a, tmp: TLoc, objtype: PType,
var L = lengthOrd(p.config, field.typ)
if not containsOrIncl(p.module.declaredThings, field.id):
appcg(p.module, cfsVars, "extern $1",
discriminatorTableDecl(p.module, t, field))
[discriminatorTableDecl(p.module, t, field)])
lineCg(p, cpsStmts,
"#FieldDiscriminantCheck((NI)(NU)($1), (NI)(NU)($2), $3, $4);$n",
[rdLoc(a), rdLoc(tmp), discriminatorTableName(p.module, t, field),