diff options
author | Araq <rumpf_a@web.de> | 2011-10-29 23:54:50 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2011-10-29 23:54:50 +0200 |
commit | 299390a585a1f626c51b932484fa3929102896d7 (patch) | |
tree | 8754d51a0970d22ebbe5a93905fc3a882995d349 /compiler | |
parent | 22115a2c6a43709aba02054b77ce2e641f280be1 (diff) | |
download | Nim-299390a585a1f626c51b932484fa3929102896d7.tar.gz |
constant folding for cnst[i] and cnst.attr
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/ast.nim | 4 | ||||
-rwxr-xr-x | compiler/cgen.nim | 2 | ||||
-rwxr-xr-x | compiler/semfold.nim | 73 | ||||
-rwxr-xr-x | compiler/transf.nim | 4 |
4 files changed, 71 insertions, 12 deletions
diff --git a/compiler/ast.nim b/compiler/ast.nim index 30989f392..550bda122 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -281,7 +281,9 @@ type nfBase2, # nfBase10 is default, so not needed nfBase8, nfBase16, - nfAllConst, # used to mark complex expressions constant + nfAllConst, # used to mark complex expressions constant; easy to get rid of + # but unfortunately it has measurable impact for compilation + # efficiency nfTransf, # node has been transformed nfSem # node has been checked for semantics diff --git a/compiler/cgen.nim b/compiler/cgen.nim index a5343e3f7..7e16042f8 100755 --- a/compiler/cgen.nim +++ b/compiler/cgen.nim @@ -14,7 +14,7 @@ import options, intsets, nversion, nimsets, msgs, crc, bitsets, idents, lists, types, ccgutils, os, times, ropes, math, passes, rodread, wordrecg, treetab, cgmeth, - rodutils, renderer, idgen, cgendata, ccgmerge + rodutils, renderer, idgen, cgendata, ccgmerge, semfold when options.hasTinyCBackend: import tccgen diff --git a/compiler/semfold.nim b/compiler/semfold.nim index d51f69bc1..f317340da 100755 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -155,9 +155,9 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode = result = newIntNodeT(ord(`<%`(getOrdValue(a), getOrdValue(b))), n) of mLeU, mLeU64: result = newIntNodeT(ord(`<=%`(getOrdValue(a), getOrdValue(b))), n) - of mBitandI, mBitandI64, mAnd: result = newIntNodeT(getInt(a) and getInt(b), n) + of mBitandI, mBitandI64, mAnd: result = newIntNodeT(a.getInt and b.getInt, n) of mBitorI, mBitorI64, mOr: result = newIntNodeT(getInt(a) or getInt(b), n) - of mBitxorI, mBitxorI64, mXor: result = newIntNodeT(getInt(a) xor getInt(b), n) + of mBitxorI, mBitxorI64, mXor: result = newIntNodeT(a.getInt xor b.getInt, n) of mAddU, mAddU64: result = newIntNodeT(`+%`(getInt(a), getInt(b)), n) of mSubU, mSubU64: result = newIntNodeT(`-%`(getInt(a), getInt(b)), n) of mMulU, mMulU64: result = newIntNodeT(`*%`(getInt(a), getInt(b)), n) @@ -199,7 +199,7 @@ proc evalOp(m: TMagic, n, a, b, c: PNode): PNode = result = copyTree(a) result.typ = n.typ of mCompileOption: - result = newIntNodeT(Ord(commands.testCompileOption(getStr(a), n.info)), n) + result = newIntNodeT(Ord(commands.testCompileOption(a.getStr, n.info)), n) of mCompileOptionArg: result = newIntNodeT(Ord( testCompileOptionArg(getStr(a), getStr(b), n.info)), n) @@ -315,6 +315,59 @@ proc foldConv*(n, a: PNode): PNode = result = a result.typ = n.typ +proc getArrayConstr(m: PSym, n: PNode): PNode = + if n.kind == nkBracket: + result = n + else: + result = getConstExpr(m, n) + if result == nil: result = n + +proc foldArrayAccess(m: PSym, n: PNode): PNode = + var x = getConstExpr(m, n.sons[0]) + if x == nil: return + + var y = getConstExpr(m, n.sons[1]) + if y == nil: return + + var idx = getOrdValue(y) + case x.kind + of nkPar: + if (idx >= 0) and (idx < sonsLen(x)): + result = x.sons[int(idx)] + if result.kind == nkExprColonExpr: result = result.sons[1] + else: + LocalError(n.info, errIndexOutOfBounds) + of nkBracket, nkMetaNode: + if (idx >= 0) and (idx < sonsLen(x)): result = x.sons[int(idx)] + else: LocalError(n.info, errIndexOutOfBounds) + of nkStrLit..nkTripleStrLit: + result = newNodeIT(nkCharLit, x.info, n.typ) + if (idx >= 0) and (idx < len(x.strVal)): + result.intVal = ord(x.strVal[int(idx)]) + elif idx == len(x.strVal): + nil + else: + LocalError(n.info, errIndexOutOfBounds) + else: nil + +proc foldFieldAccess(m: PSym, n: PNode): PNode = + # a real field access; proc calls have already been transformed + var x = getConstExpr(m, n.sons[0]) + if x == nil or x.kind != nkPar: return + + var field = n.sons[1].sym + for i in countup(0, sonsLen(x) - 1): + var it = x.sons[i] + if it.kind != nkExprColonExpr: + # lookup per index: + result = x.sons[field.position] + if result.kind == nkExprColonExpr: result = result.sons[1] + return + if it.sons[0].sym.name.id == field.name.id: + result = x.sons[i].sons[1] + return + localError(n.info, errFieldXNotFound, field.name.s) + proc getConstExpr(m: PSym, n: PNode): PNode = result = nil case n.kind @@ -333,7 +386,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode = of mNimrodPatch: result = newIntNodeT(VersionPatch, n) of mCpuEndian: result = newIntNodeT(ord(CPU[targetCPU].endian), n) of mHostOS: result = newStrNodeT(toLower(platform.OS[targetOS].name), n) - of mHostCPU: result = newStrNodeT(toLower(platform.CPU[targetCPU].name), n) + of mHostCPU: result = newStrNodeT(platform.CPU[targetCPU].name.toLower, n) of mAppType: result = getAppType(n) of mNaN: result = newFloatNodeT(NaN, n) of mInf: result = newFloatNodeT(Inf, n) @@ -346,7 +399,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode = result = copyNode(n) of nkIfExpr: result = getConstIfExpr(m, n) - of nkCall, nkCommand, nkCallStrLit: + of nkCall, nkCommand, nkCallStrLit, nkPrefix, nkInfix: if n.sons[0].kind != nkSym: return var s = n.sons[0].sym if s.kind != skProc: return @@ -372,13 +425,13 @@ proc getConstExpr(m: PSym, n: PNode): PNode = {tyOpenArray, tySequence, tyString}: result = newIntNodeT(lastOrd(skipTypes(n[1].typ, abstractVar)), n) else: - var a = n.sons[1] + var a = getArrayConstr(m, n.sons[1]) if a.kind == nkBracket: # we can optimize it away: result = newIntNodeT(sonsLen(a)-1, n) of mLengthOpenArray: - var a = n.sons[1] - if a.kind == nkBracket: + var a = getArrayConstr(m, n.sons[1]) + if a.kind == nkBracket: # we can optimize it away! This fixes the bug ``len(134)``. result = newIntNodeT(sonsLen(a), n) else: @@ -449,5 +502,7 @@ proc getConstExpr(m: PSym, n: PNode): PNode = var a = getConstExpr(m, n.sons[1]) if a == nil: return result = foldConv(n, a) - else: + of nkBracketExpr: result = foldArrayAccess(m, n) + of nkDotExpr: result = foldFieldAccess(m, n) + else: nil diff --git a/compiler/transf.nim b/compiler/transf.nim index f8475f853..81c25ecb2 100755 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -719,7 +719,9 @@ proc transform(c: PTransf, n: PNode): PTransNode = else: result = transformSons(c, n) var cnst = getConstExpr(c.module, PNode(result)) - if cnst != nil and (cnst.kind != nkBracket or cnst.len == 0): + # we inline constants if they are not complex constants: + if cnst != nil and (cnst.kind notin {nkCurly, nkPar, nkBracket} or + cnst.len == 0): result = PTransNode(cnst) # do not miss an optimization proc processTransf(context: PPassContext, n: PNode): PNode = |