diff options
author | Araq <rumpf_a@web.de> | 2011-11-02 00:55:29 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2011-11-02 00:55:29 +0100 |
commit | 351e89e705c05bd9968010ab1af1674e7eda0d59 (patch) | |
tree | ebdbb14eba617b56c0a65df891889ca165c0576f /compiler | |
parent | 47f523cfb8b5d430d1105c608440200950183bb1 (diff) | |
download | Nim-351e89e705c05bd9968010ab1af1674e7eda0d59.tar.gz |
better code generation for constant aggregates
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/ccgexprs.nim | 38 | ||||
-rwxr-xr-x | compiler/ccgstmts.nim | 2 | ||||
-rwxr-xr-x | compiler/options.nim | 3 | ||||
-rwxr-xr-x | compiler/parser.nim | 3 | ||||
-rwxr-xr-x | compiler/semexprs.nim | 22 | ||||
-rwxr-xr-x | compiler/transf.nim | 9 | ||||
-rwxr-xr-x | compiler/trees.nim | 13 |
7 files changed, 67 insertions, 23 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index c957e0aaa..c9be31830 100755 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -1727,6 +1727,23 @@ proc downConv(p: BProc, n: PNode, d: var TLoc) = for i in countup(1, abs(inheritanceDiff(dest, src))): app(r, ".Sup") putIntoDest(p, d, n.typ, r) +proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) = + var t = getUniqueType(n.typ) + discard getTypeDesc(p.module, t) # so that any fields are initialized + var id = NodeTableTestOrSet(p.module.dataCache, n, gBackendId) + var tmp = con("TMP", toRope(id)) + + if id == gBackendId: + # expression not found in the cache: + inc(gBackendId) + appf(p.module.s[cfsData], "NIM_CONST $1 $2 = $3;$n", + [getTypeDesc(p.module, t), tmp, genConstExpr(p, n)]) + + if d.k == locNone: + fillLoc(d, locData, t, tmp, OnHeap) + else: + putIntoDest(p, d, t, tmp) + proc genBlock(p: BProc, t: PNode, d: var TLoc) proc expr(p: BProc, e: PNode, d: var TLoc) = case e.kind @@ -1791,13 +1808,23 @@ proc expr(p: BProc, e: PNode, d: var TLoc) = genNamedParamCall(p, e, d) else: genCall(p, e, d) - of nkCurly: genSetConstr(p, e, d) + of nkCurly: + if isDeepConstExpr(e) and e.len != 0: + putIntoDest(p, d, e.typ, genSetNode(p, e)) + else: + genSetConstr(p, e, d) of nkBracket: - if skipTypes(e.typ, abstractVarRange).kind == tySequence: + if isDeepConstExpr(e) and e.len != 0: + exprComplexConst(p, e, d) + elif skipTypes(e.typ, abstractVarRange).kind == tySequence: genSeqConstr(p, e, d) else: genArrayConstr(p, e, d) - of nkPar: genTupleConstr(p, e, d) + of nkPar: + if isDeepConstExpr(e) and e.len != 0: + exprComplexConst(p, e, d) + else: + genTupleConstr(p, e, d) of nkCast: genCast(p, e, d) of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, e, d) of nkHiddenAddr, nkAddr: genAddr(p, e, d) @@ -1851,8 +1878,8 @@ proc genConstSeq(p: BProc, n: PNode, t: PType): PRope = appf(data, ",$1$n", [genConstExpr(p, n.sons[i])]) data.app("}") - inc(p.labels) - result = con("CNSTSEQ", p.labels.toRope) + inc(gBackendId) + result = con("CNSTSEQ", gBackendId.toRope) appcg(p.module, cfsData, "NIM_CONST struct {$n" & @@ -1872,7 +1899,6 @@ proc genConstExpr(p: BProc, n: PNode): PRope = toBitSet(n, cs) result = genRawSetData(cs, int(getSize(n.typ))) of nkBracket, nkPar: - # XXX: tySequence! var t = skipTypes(n.typ, abstractInst) if t.kind == tySequence: result = genConstSeq(p, n, t) diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 567240302..a7a474197 100755 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -67,7 +67,7 @@ proc genConstStmt(p: BProc, t: PNode) = var c = it.sons[0].sym if sfFakeConst in c.flags: genSingleVar(p, it) - elif c.typ.kind in ConstantDataTypes and not (lfNoDecl in c.loc.flags) and + elif c.typ.kind in ConstantDataTypes and lfNoDecl notin c.loc.flags and c.ast.len != 0: # generate the data: fillLoc(c.loc, locData, c.typ, mangleName(c), OnUnknown) diff --git a/compiler/options.nim b/compiler/options.nim index a4188d81d..640daf808 100755 --- a/compiler/options.nim +++ b/compiler/options.nim @@ -147,7 +147,8 @@ proc removeTrailingDirSep*(path: string): string = result = path proc getGeneratedPath: string = - result = if nimcacheDir.len > 0: nimcacheDir else: projectPath / genSubDir + result = if nimcacheDir.len > 0: nimcacheDir else: projectPath.shortenDir / + genSubDir proc toGeneratedFile*(path, ext: string): string = ## converts "/home/a/mymodule.nim", "rod" to "/home/a/nimcache/mymodule.rod" diff --git a/compiler/parser.nim b/compiler/parser.nim index d1798efa4..2a136b631 100755 --- a/compiler/parser.nim +++ b/compiler/parser.nim @@ -474,7 +474,8 @@ proc lowestExprAux(p: var TParser, limit: int): PNode = var a = newNodeP(nkInfix, p) var opNode = newIdentNodeP(p.tok.ident, p) # skip operator: getTok(p) - optInd(p, opNode) # read sub-expression with higher priority + optInd(p, opNode) + # read sub-expression with higher priority: var b = lowestExprAux(p, opPrec + leftAssoc) addSon(a, opNode) addSon(a, result) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index b16c1ade6..d8e90a589 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -261,7 +261,7 @@ proc changeType(n: PNode, newType: PType) = if newType.kind != tyTuple: InternalError(n.info, "changeType: no tuple type for constructor") if newType.n == nil: nil - elif (sonsLen(n) > 0) and (n.sons[0].kind == nkExprColonExpr): + elif sonsLen(n) > 0 and n.sons[0].kind == nkExprColonExpr: for i in countup(0, sonsLen(n) - 1): var m = n.sons[i].sons[0] if m.kind != nkSym: @@ -269,8 +269,8 @@ proc changeType(n: PNode, newType: PType) = var f = getSymFromList(newType.n, m.sym.name) if f == nil: internalError(m.info, "changeType(): invalid identifier") changeType(n.sons[i].sons[1], f.typ) - else: - for i in countup(0, sonsLen(n) - 1): + else: + for i in countup(0, sonsLen(n) - 1): var m = n.sons[i] var a = newNodeIT(nkExprColonExpr, m.info, newType.sons[i]) addSon(a, newSymNode(newType.n.sons[i].sym)) @@ -314,6 +314,7 @@ proc semArrayConstr(c: PContext, n: PNode): PNode = result.typ.sons[0] = makeRangeType(c, 0, sonsLen(result) - 1, n.info) proc fixAbstractType(c: PContext, n: PNode) = + # XXX finally rewrite that crap! for i in countup(1, sonsLen(n) - 1): var it = n.sons[i] case it.kind @@ -909,10 +910,8 @@ proc expectStringArg(c: PContext, n: PNode, i: int): PNode = if result.kind notin {nkStrLit, nkRStrLit, nkTripleStrLit}: GlobalError(result.info, errStringLiteralExpected) -proc isAstValue(n: PNode): bool = - result = n.typ.sym.name.s in [ "expr", "stmt", "PNimrodNode" ] - -proc semExpandToAst(c: PContext, n: PNode, magicSym: PSym, flags: TExprFlags): PNode = +proc semExpandToAst(c: PContext, n: PNode, magicSym: PSym, + flags: TExprFlags): PNode = if sonsLen(n) == 2: if not isCallExpr(n.sons[1]): GlobalError(n.info, errXisNoMacroOrTemplate, n.renderTree) @@ -921,24 +920,23 @@ proc semExpandToAst(c: PContext, n: PNode, magicSym: PSym, flags: TExprFlags): P var expandedSym = qualifiedLookup(c, macroCall.sons[0], {checkUndeclared}) if expandedSym == nil: - GlobalError(n.info, errUndeclaredIdentifier, macroCall.sons[0].renderTree) + GlobalError(n.info, errUndeclaredIdentifier, macroCall[0].renderTree) - if not (expandedSym.kind in { skMacro, skTemplate }): + if expandedSym.kind notin {skMacro, skTemplate}: GlobalError(n.info, errXisNoMacroOrTemplate, expandedSym.name.s) macroCall.sons[0] = newNodeI(nkSym, macroCall.info) macroCall.sons[0].sym = expandedSym markUsed(n, expandedSym) - for i in countup(1, macroCall.sonsLen - 1): + for i in countup(1, macroCall.len-1): macroCall.sons[i] = semExprWithType(c, macroCall.sons[i], {efAllowType}) # Preserve the magic symbol in order to handled in evals.nim n.sons[0] = newNodeI(nkSym, n.info) n.sons[0].sym = magicSym - + n.typ = expandedSym.getReturnType - result = n else: result = semDirectOp(c, n, flags) diff --git a/compiler/transf.nim b/compiler/transf.nim index c6b48454c..78ca50e3b 100755 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -657,6 +657,12 @@ proc transformCall(c: PTransf, n: PNode): PTransNode = else: result = transformSons(c, n) +proc dontInlineConstant(orig, cnst: PNode): bool {.inline.} = + # symbols that expand to a complex constant (array, etc.) should not be + # inlined, unless it's the empty array: + result = orig.kind == nkSym and cnst.kind in {nkCurly, nkPar, nkBracket} and + cnst.len != 0 + proc transform(c: PTransf, n: PNode): PTransNode = case n.kind of nkSym: @@ -723,8 +729,7 @@ proc transform(c: PTransf, n: PNode): PTransNode = result = transformSons(c, n) var cnst = getConstExpr(c.module, PNode(result)) # we inline constants if they are not complex constants: - if cnst != nil and (cnst.kind notin {nkCurly, nkPar, nkBracket} or - cnst.len == 0): + if cnst != nil and not dontInlineConstant(n, cnst): result = PTransNode(cnst) # do not miss an optimization proc processTransf(context: PPassContext, n: PNode): PNode = diff --git a/compiler/trees.nim b/compiler/trees.nim index 7b90296ad..9ef61f80e 100755 --- a/compiler/trees.nim +++ b/compiler/trees.nim @@ -108,6 +108,19 @@ proc isConstExpr*(n: PNode): bool = {nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit, nkFloatLit..nkFloat64Lit, nkNilLit}) or (nfAllConst in n.flags) +proc isDeepConstExpr*(n: PNode): bool = + case n.kind + of nkCharLit..nkInt64Lit, nkStrLit..nkTripleStrLit, + nkFloatLit..nkFloat64Lit, nkNilLit: + result = true + of nkExprEqExpr, nkExprColonExpr, nkHiddenStdConv, nkHiddenSubConv: + result = isDeepConstExpr(n.sons[1]) + of nkCurly, nkBracket, nkPar: + for i in 0 .. <n.len: + if not isDeepConstExpr(n.sons[i]): return false + result = true + else: nil + proc flattenTreeAux(d, a: PNode, op: TMagic) = if (getMagic(a) == op): # a is a "leaf", so add it: for i in countup(1, sonsLen(a) - 1): # BUGFIX |