From 08a6f3fc67f1bac78c47a241c94f936d7fbd5108 Mon Sep 17 00:00:00 2001 From: Andreas Rumpf Date: Wed, 7 Sep 2016 08:29:37 +0200 Subject: [PATCH] fixes #4721 --- compiler/ccgstmts.nim | 24 +++++++++++++++++++----- compiler/cgen.nim | 5 +++-- tests/ccgbugs/tescaping_temps.nim | 11 +++++++++++ todo.txt | 1 - 4 files changed, 33 insertions(+), 8 deletions(-) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 294235ae9..10b5641c5 100644 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -293,6 +293,8 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) = genLineDir(p, n) let lend = getLabel(p) for i in countup(0, sonsLen(n) - 1): + # bug #4230: avoid false sharing between branches: + if d.k == locTemp and isEmptyType(n.typ): d.k = locNone let it = n.sons[i] if it.len == 2: when newScopeForIf: startBlock(p) @@ -488,16 +490,20 @@ proc genWhileStmt(p: BProc, t: PNode) = dec(p.withinLoop) -proc genBlock(p: BProc, t: PNode, d: var TLoc) = +proc genBlock(p: BProc, n: PNode, d: var TLoc) = + # bug #4505: allocate the temp in the outer scope + # so that it can escape the generated {}: + if not isEmptyType(n.typ) and d.k == locNone: + getTemp(p, n.typ, d) preserveBreakIdx: p.breakIdx = startBlock(p) - if t.sons[0].kind != nkEmpty: + if n.sons[0].kind != nkEmpty: # named block? - assert(t.sons[0].kind == nkSym) - var sym = t.sons[0].sym + assert(n.sons[0].kind == nkSym) + var sym = n.sons[0].sym sym.loc.k = locOther sym.position = p.breakIdx+1 - expr(p, t.sons[1], d) + expr(p, n.sons[1], d) endBlock(p) proc genParForStmt(p: BProc, t: PNode) = @@ -592,6 +598,8 @@ proc genCaseSecondPass(p: BProc, t: PNode, d: var TLoc, labId, until: int): TLabel = var lend = getLabel(p) for i in 1..until: + # bug #4230: avoid false sharing between branches: + if d.k == locTemp and isEmptyType(t.typ): d.k = locNone lineF(p, cpsStmts, "LA$1: ;$n", [rope(labId + i)]) if t.sons[i].kind == nkOfBranch: var length = sonsLen(t.sons[i]) @@ -727,6 +735,8 @@ proc genOrdinalCase(p: BProc, n: PNode, d: var TLoc) = lineF(p, cpsStmts, "switch ($1) {$n", [rdCharLoc(a)]) var hasDefault = false for i in splitPoint+1 .. < n.len: + # bug #4230: avoid false sharing between branches: + if d.k == locTemp and isEmptyType(n.typ): d.k = locNone var branch = n[i] if branch.kind == nkOfBranch: genCaseRange(p, branch) @@ -797,6 +807,8 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) = var i = 1 var catchAllPresent = false while (i < length) and (t.sons[i].kind == nkExceptBranch): + # bug #4230: avoid false sharing between branches: + if d.k == locTemp and isEmptyType(t.typ): d.k = locNone let blen = sonsLen(t.sons[i]) if i > 1: addf(p.s(cpsStmts), "else ", []) if blen == 1: @@ -902,6 +914,8 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) = inc p.inExceptBlock var i = 1 while (i < length) and (t.sons[i].kind == nkExceptBranch): + # bug #4230: avoid false sharing between branches: + if d.k == locTemp and isEmptyType(t.typ): d.k = locNone var blen = sonsLen(t.sons[i]) if blen == 1: # general except section: diff --git a/compiler/cgen.nim b/compiler/cgen.nim index 7333c77c3..48b6e9633 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -323,8 +323,9 @@ proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) = proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) = inc(p.labels) result.r = "LOC" & rope(p.labels) - addf(p.blocks[0].sections[cpsLocals], - "$1 $2;$n", [getTypeDesc(p.module, t), result.r]) + #addf(p.blocks[0].sections[cpsLocals], + # "$1 $2;$n", [getTypeDesc(p.module, t), result.r]) + linefmt(p, cpsLocals, "$1 $2;$n", getTypeDesc(p.module, t), result.r) result.k = locTemp #result.a = - 1 result.t = t diff --git a/tests/ccgbugs/tescaping_temps.nim b/tests/ccgbugs/tescaping_temps.nim index ef078913b..ea09261ea 100644 --- a/tests/ccgbugs/tescaping_temps.nim +++ b/tests/ccgbugs/tescaping_temps.nim @@ -18,3 +18,14 @@ test proc() = test proc() = discard else: test proc() = discard + +# ensure 'case' does not trigger the same bug: +test proc() = + let f = 15 + case f + of 10: + test proc() = discard + of 3: + test proc() = discard + else: + test proc() = discard diff --git a/todo.txt b/todo.txt index 106f2bb34..21bec6e27 100644 --- a/todo.txt +++ b/todo.txt @@ -53,7 +53,6 @@ Bugs - VM: ptr/ref T cannot work in general - blocks can "export" an identifier but the CCG generates {} for them ... - ConcreteTypes in a 'case' means we don't check for duplicated case branches -- BUG: echo with template `$`*(info: TLineInfo): expr = toFileLineCol(info) GC