diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2019-04-21 09:57:53 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-21 09:57:53 +0200 |
commit | fabc2a7086bb83afc2abfd6d5841f25c8387609f (patch) | |
tree | 5e66aff72c698ba5dd4a2cda474e9f09bf513532 | |
parent | 88079a0dee3b6e7820811783ce0df0db8f97a8ad (diff) | |
download | Nim-fabc2a7086bb83afc2abfd6d5841f25c8387609f.tar.gz |
revert discardable transformation (#10905)
* Revert "Properly wrap discarded statements (#10322)" This reverts commit 15584879b91e14565156ca140eef1dc100cf34c4. * add test for implicit discard after defer * enable t10241 again * make C++ tests green again
-rw-r--r-- | compiler/ccgcalls.nim | 24 | ||||
-rw-r--r-- | compiler/ccgexprs.nim | 73 | ||||
-rw-r--r-- | compiler/cgen.nim | 9 | ||||
-rw-r--r-- | compiler/semexprs.nim | 4 | ||||
-rw-r--r-- | compiler/semstmts.nim | 24 | ||||
-rw-r--r-- | tests/discard/tdiscardable.nim | 20 |
6 files changed, 113 insertions, 41 deletions
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index fcdba2996..1e856ad73 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -46,13 +46,23 @@ proc fixupCall(p: BProc, le, ri: PNode, d: var TLoc, genAssignment(p, d, tmp, {}) # no need for deep copying else: add(pl, ~")") - if p.module.compileToCpp and lfSingleUse in d.flags: - # do not generate spurious temporaries for C++! For C we're better off - # with them to prevent undefined behaviour and because the codegen - # is free to emit expressions multiple times! - d.k = locCall - d.r = pl - excl d.flags, lfSingleUse + if p.module.compileToCpp: + if lfSingleUse in d.flags: + # do not generate spurious temporaries for C++! For C we're better off + # with them to prevent undefined behaviour and because the codegen + # is free to emit expressions multiple times! + d.k = locCall + d.r = pl + excl d.flags, lfSingleUse + else: + if d.k == locNone and p.splitDecls == 0: + getTempCpp(p, typ.sons[0], d, pl) + else: + if d.k == locNone: getTemp(p, typ.sons[0], d) + var list: TLoc + initLoc(list, locCall, d.lode, OnUnknown) + list.r = pl + genAssignment(p, d, list, {}) # no need for deep copying else: if d.k == locNone: getTemp(p, typ.sons[0], d) assert(d.t != nil) # generate an assignment to d: diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index e6d22379f..65cc6e42e 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -996,6 +996,23 @@ proc genBracketExpr(p: BProc; n: PNode; d: var TLoc) = of tyTuple: genTupleElem(p, n, d) else: internalError(p.config, n.info, "expr(nkBracketExpr, " & $ty.kind & ')') +proc isSimpleExpr(n: PNode): bool = + # calls all the way down --> can stay expression based + case n.kind + of nkCallKinds, nkDotExpr, nkPar, nkTupleConstr, + nkObjConstr, nkBracket, nkCurly, nkHiddenDeref, nkDerefExpr, nkHiddenAddr, + nkHiddenStdConv, nkHiddenSubConv, nkConv, nkAddr: + for c in n: + if not isSimpleExpr(c): return false + result = true + of nkStmtListExpr: + for i in 0..n.len-2: + if n[i].kind notin {nkCommentStmt, nkEmpty}: return false + result = isSimpleExpr(n.lastSon) + else: + if n.isAtom: + result = true + proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) = # how to generate code? # 'expr1 and expr2' becomes: @@ -1017,24 +1034,41 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) = # tmp = a # end: # a = tmp - var - L: TLabel - tmp: TLoc - getTemp(p, e.typ, tmp) # force it into a temp! - inc p.splitDecls - expr(p, e.sons[1], tmp) - L = getLabel(p) - if m == mOr: - lineF(p, cpsStmts, "if ($1) goto $2;$n", [rdLoc(tmp), L]) - else: - lineF(p, cpsStmts, "if (!($1)) goto $2;$n", [rdLoc(tmp), L]) - expr(p, e.sons[2], tmp) - fixLabel(p, L) - if d.k == locNone: - d = tmp + when false: + #if isSimpleExpr(e) and p.module.compileToCpp: + var tmpA, tmpB: TLoc + #getTemp(p, e.typ, tmpA) + #getTemp(p, e.typ, tmpB) + initLocExprSingleUse(p, e.sons[1], tmpA) + initLocExprSingleUse(p, e.sons[2], tmpB) + tmpB.k = locExpr + if m == mOr: + tmpB.r = "((" & rdLoc(tmpA) & ")||(" & rdLoc(tmpB) & "))" + else: + tmpB.r = "((" & rdLoc(tmpA) & ")&&(" & rdLoc(tmpB) & "))" + if d.k == locNone: + d = tmpB + else: + genAssignment(p, d, tmpB, {}) else: - genAssignment(p, d, tmp, {}) # no need for deep copying - dec p.splitDecls + var + L: TLabel + tmp: TLoc + getTemp(p, e.typ, tmp) # force it into a temp! + inc p.splitDecls + expr(p, e.sons[1], tmp) + L = getLabel(p) + if m == mOr: + lineF(p, cpsStmts, "if ($1) goto $2;$n", [rdLoc(tmp), L]) + else: + lineF(p, cpsStmts, "if (!($1)) goto $2;$n", [rdLoc(tmp), L]) + expr(p, e.sons[2], tmp) + fixLabel(p, L) + if d.k == locNone: + d = tmp + else: + genAssignment(p, d, tmp, {}) # no need for deep copying + dec p.splitDecls proc genEcho(p: BProc, n: PNode) = # this unusal way of implementing it ensures that e.g. ``echo("hallo", 45)`` @@ -2669,7 +2703,10 @@ proc expr(p: BProc, n: PNode, d: var TLoc) = genProc(p.module, prc) of nkParForStmt: genParForStmt(p, n) of nkState: genState(p, n) - of nkGotoState: genGotoState(p, n) + of nkGotoState: + # simply never set it back to 0 here from here on... + inc p.splitDecls + genGotoState(p, n) of nkBreakState: genBreakState(p, n, d) else: internalError(p.config, n.info, "expr(" & $n.kind & "); unknown node kind") diff --git a/compiler/cgen.nim b/compiler/cgen.nim index e87f512c8..9bc3353dc 100644 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -440,6 +440,15 @@ proc getTemp(p: BProc, t: PType, result: var TLoc; needsInit=false) = result.flags = {} constructLoc(p, result, not needsInit) +proc getTempCpp(p: BProc, t: PType, result: var TLoc; value: Rope) = + inc(p.labels) + result.r = "T" & rope(p.labels) & "_" + linefmt(p, cpsStmts, "$1 $2 = $3;$n", [getTypeDesc(p.module, t), result.r, value]) + result.k = locTemp + result.lode = lodeTyp t + result.storage = OnStack + result.flags = {} + proc getIntTemp(p: BProc, result: var TLoc) = inc(p.labels) result.r = "T" & rope(p.labels) & "_" diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index f39603c0e..10a058ff0 100644 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -937,7 +937,7 @@ proc semExprNoType(c: PContext, n: PNode): PNode = let isPush = hintExtendedContext in c.config.notes if isPush: pushInfoContext(c.config, n.info) result = semExpr(c, n, {efWantStmt}) - result = discardCheck(c, result, {}) + discardCheck(c, result, {}) if isPush: popInfoContext(c.config) proc isTypeExpr(n: PNode): bool = @@ -1673,7 +1673,7 @@ proc semProcBody(c: PContext, n: PNode): PNode = a.sons[1] = result result = semAsgn(c, a) else: - result = discardCheck(c, result, {}) + discardCheck(c, result, {}) if c.p.owner.kind notin {skMacro, skTemplate} and c.p.resultSym != nil and c.p.resultSym.typ.isMetaType: diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 4054fd71a..a71a57175 100644 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -130,13 +130,13 @@ proc fixNilType(c: PContext; n: PNode) = for it in n: fixNilType(c, it) n.typ = nil -proc discardCheck(c: PContext, expr: PNode, flags: TExprFlags): PNode = - result = expr +proc discardCheck(c: PContext, result: PNode, flags: TExprFlags) = if c.matchedConcept != nil or efInTypeof in flags: return if result.typ != nil and result.typ.kind notin {tyStmt, tyVoid}: if implicitlyDiscardable(result): - result = newNode(nkDiscardStmt, result.info, @[result]) + var n = newNodeI(nkDiscardStmt, result.info, 1) + n[0] = result elif result.typ.kind != tyError and c.config.cmd != cmdInteractive: var n = result while n.kind in skipForDiscardable: n = n.lastSon @@ -168,8 +168,7 @@ proc semIf(c: PContext, n: PNode; flags: TExprFlags): PNode = else: illFormedAst(it, c.config) if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or (not hasElse and efInTypeof notin flags): - for it in n: - it.sons[^1] = discardCheck(c, it.sons[^1], flags) + for it in n: discardCheck(c, it.lastSon, flags) result.kind = nkIfStmt # propagate any enforced VoidContext: if typ == c.enforceVoidContext: result.typ = c.enforceVoidContext @@ -267,14 +266,12 @@ proc semTry(c: PContext, n: PNode; flags: TExprFlags): PNode = dec c.p.inTryStmt if isEmptyType(typ) or typ.kind in {tyNil, tyExpr}: - n.sons[0] = discardCheck(c, n.sons[0], flags) - for i in 1..n.len-1: - n.sons[i].sons[^1] = discardCheck(c, n.sons[i].sons[^1], flags) + discardCheck(c, n.sons[0], flags) + for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon, flags) if typ == c.enforceVoidContext: result.typ = c.enforceVoidContext else: - if n.lastSon.kind == nkFinally: - n.sons[^1].sons[^1] = discardCheck(c, n.sons[^1].sons[^1], flags) + if n.lastSon.kind == nkFinally: discardCheck(c, n.lastSon.lastSon, flags) n.sons[0] = fitNode(c, typ, n.sons[0], n.sons[0].info) for i in 1..last: var it = n.sons[i] @@ -729,7 +726,7 @@ proc semForVars(c: PContext, n: PNode; flags: TExprFlags): PNode = openScope(c) n.sons[length-1] = semExprBranch(c, n.sons[length-1], flags) if efInTypeof notin flags: - n.sons[^1] = discardCheck(c, n.sons[^1], flags) + discardCheck(c, n.sons[length-1], flags) closeScope(c) dec(c.p.nestedLoopCounter) @@ -919,8 +916,7 @@ proc semCase(c: PContext, n: PNode; flags: TExprFlags): PNode = closeScope(c) if isEmptyType(typ) or typ.kind in {tyNil, tyExpr} or (not hasElse and efInTypeof notin flags): - for i in 1..n.len-1: - n.sons[i].sons[^1] = discardCheck(c, n.sons[i].sons[^1], flags) + for i in 1..n.len-1: discardCheck(c, n.sons[i].lastSon, flags) # propagate any enforced VoidContext: if typ == c.enforceVoidContext: result.typ = c.enforceVoidContext @@ -2124,7 +2120,7 @@ proc semStmtList(c: PContext, n: PNode, flags: TExprFlags): PNode = n.typ = n.sons[i].typ if not isEmptyType(n.typ): n.kind = nkStmtListExpr elif i != last or voidContext: - n.sons[i] = discardCheck(c, n.sons[i], flags) + discardCheck(c, n.sons[i], flags) else: n.typ = n.sons[i].typ if not isEmptyType(n.typ): n.kind = nkStmtListExpr diff --git a/tests/discard/tdiscardable.nim b/tests/discard/tdiscardable.nim index 81e17866a..032050139 100644 --- a/tests/discard/tdiscardable.nim +++ b/tests/discard/tdiscardable.nim @@ -3,6 +3,8 @@ output: ''' tdiscardable 1 1 +something defered +something defered ''' """ @@ -45,3 +47,21 @@ proc foo: (proc: int) = return bar discard foo() + +# bug #10842 + +proc myDiscardable(): int {.discardable.} = + discard + +proc main1() = + defer: + echo "something defered" + discard myDiscardable() + +proc main2() = + defer: + echo "something defered" + myDiscardable() + +main1() +main2() |