summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2011-11-02 00:55:29 +0100
committerAraq <rumpf_a@web.de>2011-11-02 00:55:29 +0100
commit351e89e705c05bd9968010ab1af1674e7eda0d59 (patch)
treeebdbb14eba617b56c0a65df891889ca165c0576f /compiler
parent47f523cfb8b5d430d1105c608440200950183bb1 (diff)
downloadNim-351e89e705c05bd9968010ab1af1674e7eda0d59.tar.gz
better code generation for constant aggregates
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/ccgexprs.nim38
-rwxr-xr-xcompiler/ccgstmts.nim2
-rwxr-xr-xcompiler/options.nim3
-rwxr-xr-xcompiler/parser.nim3
-rwxr-xr-xcompiler/semexprs.nim22
-rwxr-xr-xcompiler/transf.nim9
-rwxr-xr-xcompiler/trees.nim13
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