diff options
-rw-r--r-- | compiler/ccgexprs.nim | 34 | ||||
-rw-r--r-- | compiler/trees.nim | 19 | ||||
-rw-r--r-- | tests/ccgbugs/tinefficient_const_table.nim | 27 |
3 files changed, 57 insertions, 23 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index 75a7cb3bb..a86409e50 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1151,7 +1151,25 @@ proc genNewSeqOfCap(p: BProc; e: PNode; d: var TLoc) = genTypeInfo(p.module, seqtype), a.rdLoc])) gcUsage(e) +proc genConstExpr(p: BProc, n: PNode): Rope +proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool = + if d.k == locNone and n.len > ord(n.kind == nkObjConstr) and n.isDeepConstExpr: + var t = getUniqueType(n.typ) + discard getTypeDesc(p.module, t) # so that any fields are initialized + let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels) + fillLoc(d, locData, t, p.module.tmpBase & rope(id), OnStatic) + if id == p.module.labels: + # expression not found in the cache: + inc(p.module.labels) + addf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n", + [getTypeDesc(p.module, t), d.r, genConstExpr(p, n)]) + result = true + else: + result = false + proc genObjConstr(p: BProc, e: PNode, d: var TLoc) = + if handleConstExpr(p, e, d): return + #echo rendertree e, " ", e.isDeepConstExpr var tmp: TLoc var t = e.typ.skipTypes(abstractInst) getTemp(p, t, tmp) @@ -1769,22 +1787,6 @@ proc genMagicExpr(p: BProc, e: PNode, d: var TLoc, op: TMagic) = of mDotDot, mEqCString: genCall(p, e, d) else: internalError(e.info, "genMagicExpr: " & $op) -proc genConstExpr(p: BProc, n: PNode): Rope -proc handleConstExpr(p: BProc, n: PNode, d: var TLoc): bool = - if nfAllConst in n.flags and d.k == locNone and n.len > 0 and n.isDeepConstExpr: - var t = getUniqueType(n.typ) - discard getTypeDesc(p.module, t) # so that any fields are initialized - let id = nodeTableTestOrSet(p.module.dataCache, n, p.module.labels) - fillLoc(d, locData, t, p.module.tmpBase & rope(id), OnStatic) - if id == p.module.labels: - # expression not found in the cache: - inc(p.module.labels) - addf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n", - [getTypeDesc(p.module, t), d.r, genConstExpr(p, n)]) - result = true - else: - result = false - proc genSetConstr(p: BProc, e: PNode, d: var TLoc) = # example: { a..b, c, d, e, f..g } # we have to emit an expression of the form: diff --git a/compiler/trees.nim b/compiler/trees.nim index 659df334b..fdd88c348 100644 --- a/compiler/trees.nim +++ b/compiler/trees.nim @@ -103,14 +103,16 @@ proc getMagic*(op: PNode): TMagic = else: result = mNone else: result = mNone -proc treeToSym*(t: PNode): PSym = - result = t.sym - proc isConstExpr*(n: PNode): bool = result = (n.kind in {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit, nkFloatLit..nkFloat64Lit, nkNilLit}) or (nfAllConst in n.flags) +proc isCaseObj*(n: PNode): bool = + if n.kind == nkRecCase: return true + for i in 0..<safeLen(n): + if n[i].isCaseObj: return true + proc isDeepConstExpr*(n: PNode): bool = case n.kind of nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit, @@ -119,11 +121,14 @@ proc isDeepConstExpr*(n: PNode): bool = of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv: result = isDeepConstExpr(n.sons[1]) of nkCurly, nkBracket, nkPar, nkObjConstr, nkClosure: - for i in 0 .. <n.len: + for i in ord(n.kind == nkObjConstr) .. <n.len: if not isDeepConstExpr(n.sons[i]): return false - # XXX once constant objects are supported by the codegen this needs to be - # weakened: - result = n.typ.isNil or n.typ.skipTypes({tyGenericInst, tyDistinct}).kind != tyObject + if n.typ.isNil: result = true + else: + let t = n.typ.skipTypes({tyGenericInst, tyDistinct}) + if t.kind in {tyRef, tyPtr}: return false + if t.kind != tyObject or not isCaseObj(t.n): + result = true else: discard proc flattenTreeAux(d, a: PNode, op: TMagic) = diff --git a/tests/ccgbugs/tinefficient_const_table.nim b/tests/ccgbugs/tinefficient_const_table.nim new file mode 100644 index 000000000..149b8bcff --- /dev/null +++ b/tests/ccgbugs/tinefficient_const_table.nim @@ -0,0 +1,27 @@ +discard """ + output: '''a +long +list +of +words''' + cmd: r"nim c --hints:on $options -d:release $file" + ccodecheck: "! @'genericSeqAssign'" +""" + + +# bug #4354 +import tables +import sets +import strutils + +#const FRUITS = ["banana", "apple", "grapes"] +#let FRUITS = ["banana", "apple", "grapes"].toSet +const FRUITS = {"banana":0, "apple":0, "grapes":0}.toTable + +proc main() = + let L = "a long list of words".split() + for word in L: + if word notin FRUITS: + echo(word) + +main() |