better code generation for constant aggregates

This commit is contained in:
Araq 2011-11-02 00:55:29 +01:00
commit 351e89e705
10 changed files with 79 additions and 32 deletions

View file

@ -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)

View file

@ -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)

View file

@ -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"

View file

@ -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)

View file

@ -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)

View file

@ -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 =

View file

@ -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