diff options
author | Araq <rumpf_a@web.de> | 2012-06-30 12:29:56 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-06-30 12:29:56 +0200 |
commit | ee1bcb6414a50642811632a92a803840c1c67036 (patch) | |
tree | 07e2be9d40db1a33cc29cf9d6f9f2dac9b9a5f38 /compiler | |
parent | 2900ceae3580a9f1e83b500cf1abcdfe77762cad (diff) | |
download | Nim-ee1bcb6414a50642811632a92a803840c1c67036.tar.gz |
dead code elimination for JS backend; JS improvements (but doesn't work yet)
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/ecmasgen.nim | 189 | ||||
-rw-r--r-- | compiler/lambdalifting.nim | 2 | ||||
-rwxr-xr-x | compiler/msgs.nim | 4 |
3 files changed, 126 insertions, 69 deletions
diff --git a/compiler/ecmasgen.nim b/compiler/ecmasgen.nim index 07754ee13..64ef75de5 100755 --- a/compiler/ecmasgen.nim +++ b/compiler/ecmasgen.nim @@ -26,7 +26,7 @@ type module*: PSym BModule = ref TEcmasGen - TEcmasTypeKind = enum + TEcmasTypeKind = enum # necessary JS "types" etyNone, # no type etyNull, # null type etyProc, # proc type @@ -50,25 +50,29 @@ type isLoop: bool # whether it's a 'block' or 'while' TGlobals{.final.} = object - typeInfo*, code*: PRope - typeInfoGenerated*: TIntSet + typeInfo, code: PRope + forwarded: seq[PSym] + generatedSyms: TIntSet + typeInfoGenerated: TIntSet PGlobals = ref TGlobals TProc{.final.} = object - procDef*: PNode - prc*: PSym - data*: PRope - options*: TOptions - module*: BModule - globals*: PGlobals - BeforeRetNeeded*: bool - nestedTryStmts*: int - unique*: int - blocks*: seq[TBlock] + procDef: PNode + prc: PSym + data: PRope + options: TOptions + module: BModule + g: PGlobals + BeforeRetNeeded: bool + nestedTryStmts: int + unique: int + blocks: seq[TBlock] proc newGlobals(): PGlobals = new(result) + result.forwarded = @[] + result.generatedSyms = initIntSet() result.typeInfoGenerated = initIntSet() proc initCompRes(r: var TCompRes) = @@ -82,7 +86,7 @@ proc initProc(p: var TProc, globals: PGlobals, module: BModule, procDef: PNode, p.options = options p.module = module p.procDef = procDef - p.globals = globals + p.g = globals if procDef != nil: p.prc = procDef.sons[namePos].sym const @@ -196,12 +200,12 @@ proc genObjectFields(p: var TProc, typ: PType, n: PNode): PRope = proc genObjectInfo(p: var TProc, typ: PType, name: PRope) = var s = ropef("var $1 = {size: 0, kind: $2, base: null, node: null, " & "finalizer: null};$n", [name, toRope(ord(typ.kind))]) - prepend(p.globals.typeInfo, s) - appf(p.globals.typeInfo, "var NNI$1 = $2;$n", + prepend(p.g.typeInfo, s) + appf(p.g.typeInfo, "var NNI$1 = $2;$n", [toRope(typ.id), genObjectFields(p, typ, typ.n)]) - appf(p.globals.typeInfo, "$1.node = NNI$2;$n", [name, toRope(typ.id)]) + appf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, toRope(typ.id)]) if (typ.kind == tyObject) and (typ.sons[0] != nil): - appf(p.globals.typeInfo, "$1.base = $2;$n", + appf(p.g.typeInfo, "$1.base = $2;$n", [name, genTypeInfo(p, typ.sons[0])]) proc genEnumInfo(p: var TProc, typ: PType, name: PRope) = @@ -221,18 +225,18 @@ proc genEnumInfo(p: var TProc, typ: PType, name: PRope) = "name: null, len: $2, sons: [$3]};$n", [toRope(typ.id), toRope(length), s]) s = ropef("var $1 = {size: 0, kind: $2, base: null, node: null, " & "finalizer: null};$n", [name, toRope(ord(typ.kind))]) - prepend(p.globals.typeInfo, s) - app(p.globals.typeInfo, n) - appf(p.globals.typeInfo, "$1.node = NNI$2;$n", [name, toRope(typ.id)]) + prepend(p.g.typeInfo, s) + app(p.g.typeInfo, n) + appf(p.g.typeInfo, "$1.node = NNI$2;$n", [name, toRope(typ.id)]) if typ.sons[0] != nil: - appf(p.globals.typeInfo, "$1.base = $2;$n", + appf(p.g.typeInfo, "$1.base = $2;$n", [name, genTypeInfo(p, typ.sons[0])]) proc genTypeInfo(p: var TProc, typ: PType): PRope = var t = typ if t.kind == tyGenericInst: t = lastSon(t) result = ropef("NTI$1", [toRope(t.id)]) - if ContainsOrIncl(p.globals.TypeInfoGenerated, t.id): return + if ContainsOrIncl(p.g.TypeInfoGenerated, t.id): return case t.kind of tyDistinct: result = genTypeInfo(p, typ.sons[0]) @@ -240,20 +244,20 @@ proc genTypeInfo(p: var TProc, typ: PType): PRope = var s = ropef( "var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n", [result, toRope(ord(t.kind))]) - prepend(p.globals.typeInfo, s) + prepend(p.g.typeInfo, s) of tyVar, tyRef, tyPtr, tySequence, tyRange, tySet: var s = ropef( "var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n", [result, toRope(ord(t.kind))]) - prepend(p.globals.typeInfo, s) - appf(p.globals.typeInfo, "$1.base = $2;$n", + prepend(p.g.typeInfo, s) + appf(p.g.typeInfo, "$1.base = $2;$n", [result, genTypeInfo(p, typ.sons[0])]) of tyArrayConstr, tyArray: var s = ropef( "var $1 = {size: 0,kind: $2,base: null,node: null,finalizer: null};$n", [result, toRope(ord(t.kind))]) - prepend(p.globals.typeInfo, s) - appf(p.globals.typeInfo, "$1.base = $2;$n", + prepend(p.g.typeInfo, s) + appf(p.g.typeInfo, "$1.base = $2;$n", [result, genTypeInfo(p, typ.sons[1])]) of tyEnum: genEnumInfo(p, t, result) of tyObject, tyTuple: genObjectInfo(p, t, result) @@ -261,10 +265,9 @@ proc genTypeInfo(p: var TProc, typ: PType): PRope = proc gen(p: var TProc, n: PNode, r: var TCompRes) proc genStmt(p: var TProc, n: PNode, r: var TCompRes) -proc useMagic(p: var TProc, ident: string) = - nil - # to implement - +proc genProc(oldProc: var TProc, prc: PSym, r: var TCompRes) +proc genConstant(p: var TProc, c: PSym, r: var TCompRes) + proc mergeExpr(a, b: PRope): PRope = if (a != nil): if b != nil: result = ropef("($1, $2)", [a, b]) @@ -280,6 +283,22 @@ proc mergeStmt(r: TCompRes): PRope = elif r.com == nil: result = r.res else: result = ropef("$1$2", [r.com, r.res]) +proc useMagic(p: var TProc, name: string) = + if name.len == 0: return + var s = magicsys.getCompilerProc(name) + if s != nil: + internalAssert s.kind in {skProc, skMethod, skConverter} + if not p.g.generatedSyms.containsOrIncl(s.id): + var r: TCompRes + genProc(p, s, r) + app(p.g.code, mergeStmt(r)) + else: + # we used to exclude the system module from this check, but for DLL + # generation support this sloppyness leads to hard to detect bugs, so + # we're picky here for the system module too: + if p.prc != nil: GlobalError(p.prc.info, errSystemNeeds, name) + else: rawMessage(errSystemNeeds, name) + proc genAnd(p: var TProc, a, b: PNode, r: var TCompRes) = var x, y: TCompRes gen(p, a, x) @@ -403,7 +422,7 @@ const # magic checked op; magic unchecked op; checked op; unchecked op proc binaryExpr(p: var TProc, n: PNode, r: var TCompRes, magic, frmt: string) = var x, y: TCompRes - if magic != "": useMagic(p, magic) + useMagic(p, magic) gen(p, n.sons[1], x) gen(p, n.sons[2], y) r.res = ropef(frmt, [x.res, y.res]) @@ -411,7 +430,7 @@ proc binaryExpr(p: var TProc, n: PNode, r: var TCompRes, magic, frmt: string) = proc binaryStmt(p: var TProc, n: PNode, r: var TCompRes, magic, frmt: string) = var x, y: TCompRes - if magic != "": useMagic(p, magic) + useMagic(p, magic) gen(p, n.sons[1], x) gen(p, n.sons[2], y) if x.com != nil: appf(r.com, "$1;$n", [x.com]) @@ -419,7 +438,7 @@ proc binaryStmt(p: var TProc, n: PNode, r: var TCompRes, magic, frmt: string) = appf(r.com, frmt, [x.res, y.res]) proc unaryExpr(p: var TProc, n: PNode, r: var TCompRes, magic, frmt: string) = - if magic != "": useMagic(p, magic) + useMagic(p, magic) gen(p, n.sons[1], r) r.res = ropef(frmt, [r.res]) @@ -821,7 +840,7 @@ proc genArrayAddr(p: var TProc, n: PNode, r: var TCompRes) = var typ = skipTypes(n.sons[0].typ, abstractPtrs) if typ.kind in {tyArray, tyArrayConstr}: first = FirstOrd(typ.sons[0]) else: first = 0 - if (optBoundsCheck in p.options) and not isConstExpr(n.sons[1]): + if optBoundsCheck in p.options and not isConstExpr(n.sons[1]): useMagic(p, "chckIndx") b.res = ropef("chckIndx($1, $2, $3.length)-$2", [b.res, toRope(first), a.res]) @@ -869,12 +888,13 @@ proc genAddr(p: var TProc, n: PNode, r: var TCompRes) = genArrayAddr(p, n, r) else: InternalError(n.info, "genAddr") + proc genSym(p: var TProc, n: PNode, r: var TCompRes) = var s = n.sym - if s.loc.r == nil: - InternalError(n.info, "symbol has no generated name: " & s.name.s) case s.kind of skVar, skLet, skParam, skTemp, skResult: + if s.loc.r == nil: + InternalError(n.info, "symbol has no generated name: " & s.name.s) var k = mapType(s.typ) if k == etyBaseIndex: r.kind = etyBaseIndex @@ -888,7 +908,25 @@ proc genSym(p: var TProc, n: PNode, r: var TCompRes) = r.res = ropef("$1[0]", [s.loc.r]) else: r.res = s.loc.r - else: r.res = s.loc.r + of skConst: + genConstant(p, s, r) + if s.loc.r == nil: + InternalError(n.info, "symbol has no generated name: " & s.name.s) + r.res = s.loc.r + of skProc, skConverter, skMethod: + discard mangleName(s) + r.res = s.loc.r + if lfNoDecl in s.loc.flags or s.magic != mNone or isGenericRoutine(s): nil + elif sfForward in s.flags: + p.g.forwarded.add(s) + elif not p.g.generatedSyms.containsOrIncl(s.id): + var r2: TCompRes + genProc(p, s, r2) + app(p.g.code, mergeStmt(r2)) + else: + if s.loc.r == nil: + InternalError(n.info, "symbol has no generated name: " & s.name.s) + r.res = s.loc.r proc genDeref(p: var TProc, n: PNode, r: var TCompRes) = var a: TCompRes @@ -1041,16 +1079,22 @@ proc genVarStmt(p: var TProc, n: PNode, r: var TCompRes) = genLineDir(p, a, r) genVarInit(p, v, a.sons[2], r) -proc genConstStmt(p: var TProc, n: PNode, r: var TCompRes) = - genLineDir(p, n, r) - for i in countup(0, sonsLen(n) - 1): - if n.sons[i].kind == nkCommentStmt: continue - assert(n.sons[i].kind == nkConstDef) - var c = n.sons[i].sons[0].sym - if (c.ast != nil) and (c.typ.kind in ConstantDataTypes) and - not (lfNoDecl in c.loc.flags): - genLineDir(p, n.sons[i], r) - genVarInit(p, c, c.ast, r) +proc genConstant(p: var TProc, c: PSym, r: var TCompRes) = + if lfNoDecl notin c.loc.flags and not p.g.generatedSyms.containsOrIncl(c.id): + genLineDir(p, c.ast, r) + genVarInit(p, c, c.ast, r) + +when false: + proc genConstStmt(p: var TProc, n: PNode, r: var TCompRes) = + genLineDir(p, n, r) + for i in countup(0, sonsLen(n) - 1): + if n.sons[i].kind == nkCommentStmt: continue + assert(n.sons[i].kind == nkConstDef) + var c = n.sons[i].sons[0].sym + if c.ast != nil and c.typ.kind in ConstantDataTypes and + lfNoDecl notin c.loc.flags: + genLineDir(p, n.sons[i], r) + genVarInit(p, c, c.ast, r) proc genNew(p: var TProc, n: PNode, r: var TCompRes) = var a: TCompRes @@ -1299,12 +1343,14 @@ proc genProc(oldProc: var TProc, prc: PSym, r: var TCompRes) = resultSym: PSym name, returnStmt, resultAsgn, header: PRope a: TCompRes - initProc(p, oldProc.globals, oldProc.module, prc.ast, prc.options) + #if gVerbosity >= 3: + # echo "BEGIN generating code for: " & prc.name.s + initProc(p, oldProc.g, oldProc.module, prc.ast, prc.options) returnStmt = nil resultAsgn = nil name = mangleName(prc) header = generateHeader(p, prc.typ) - if (prc.typ.sons[0] != nil) and not (sfPure in prc.flags): + if (prc.typ.sons[0] != nil) and sfPure notin prc.flags: resultSym = prc.ast.sons[resultPos].sym resultAsgn = ropef("var $1 = $2;$n", [mangleName(resultSym), createVar(p, resultSym.typ, isIndirect(resultSym))]) @@ -1315,6 +1361,8 @@ proc genProc(oldProc: var TProc, prc: PSym, r: var TCompRes) = r.com = ropef("function $1($2) {$n$3$4$5}$n", [name, header, resultAsgn, genProcBody(p, prc, r), returnStmt]) r.res = nil + #if gVerbosity >= 3: + # echo "END generated code for: " & prc.name.s proc genStmtListExpr(p: var TProc, n: PNode, r: var TCompRes) = var a: TCompRes @@ -1342,7 +1390,7 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) = of nkIfStmt: genIfStmt(p, n, r) of nkWhileStmt: genWhileStmt(p, n, r) of nkVarSection, nkLetSection: genVarStmt(p, n, r) - of nkConstSection: genConstStmt(p, n, r) + of nkConstSection: nil of nkForStmt, nkParForStmt: internalError(n.info, "for statement not eliminated") of nkCaseStmt: genCaseStmt(p, n, r) @@ -1358,16 +1406,13 @@ proc genStmt(p: var TProc, n: PNode, r: var TCompRes) = of nkTryStmt: genTryStmt(p, n, r) of nkRaiseStmt: genRaiseStmt(p, n, r) of nkTypeSection, nkCommentStmt, nkIteratorDef, nkIncludeStmt, nkImportStmt, - nkFromStmt, nkTemplateDef, nkMacroDef, nkPragma: - nil - of nkProcDef, nkMethodDef, nkConverterDef: - if (n.sons[genericParamsPos].kind == nkEmpty): - var prc = n.sons[namePos].sym - if lfNoDecl notin prc.loc.flags and prc.getBody.kind != nkEmpty: - genProc(p, prc, r) - else: - discard mangleName(prc) - else: + nkFromStmt, nkTemplateDef, nkMacroDef, nkPragma: nil + of nkProcDef, nkMethodDef, nkConverterDef: + var s = n.sons[namePos].sym + if {sfExportc, sfCompilerProc} * s.flags == {sfExportc}: + var r2: TCompRes + genSym(p, n.sons[namePos], r2) + else: genLineDir(p, n, r) if n.sons[0].kind == nkSym: if n.sons[0].sym.loc.r == nil: @@ -1431,6 +1476,9 @@ proc gen(p: var TProc, n: PNode, r: var TCompRes) = of nkCStringToString: convCStrToStr(p, n, r) of nkStmtListExpr: genStmtListExpr(p, n, r) of nkEmpty: nil + of nkLambdaKinds: + # XXX not correct, as we need to put it into the proper scope! + gen(p, n.sons[namePos], r) of nkMetaNode: gen(p, n.sons[0], r) of nkType: r.res = genTypeInfo(p, n.typ) else: InternalError(n.info, "gen: unknown node type: " & $n.kind) @@ -1467,14 +1515,23 @@ proc myProcess(b: PPassContext, n: PNode): PNode = if m.module == nil: InternalError(n.info, "myProcess") initProc(p, globals, m, nil, m.module.options) genModule(p, n, r) - app(p.globals.code, p.data) - app(p.globals.code, mergeStmt(r)) + app(p.g.code, p.data) + app(p.g.code, mergeStmt(r)) proc myClose(b: PPassContext, n: PNode): PNode = if passes.skipCodegen(n): return n result = myProcess(b, n) var m = BModule(b) - if sfMainModule in m.module.flags: + if sfMainModule in m.module.flags: + for prc in globals.forwarded: + if not globals.generatedSyms.containsOrIncl(prc.id): + var + p: TProc + r: TCompRes + initProc(p, globals, m, nil, m.module.options) + genProc(p, prc, r) + app(p.g.code, mergeStmt(r)) + var disp = generateMethodDispatchers() for i in 0..sonsLen(disp)-1: var @@ -1482,7 +1539,7 @@ proc myClose(b: PPassContext, n: PNode): PNode = r: TCompRes initProc(p, globals, m, nil, m.module.options) genProc(p, disp.sons[i].sym, r) - app(p.globals.code, mergeStmt(r)) + app(p.g.code, mergeStmt(r)) # write the file: var code = con(globals.typeInfo, globals.code) diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 5ab7c65ef..ab824b92a 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -510,6 +510,6 @@ proc liftLambdas(fn: PSym, body: PNode): PNode = proc liftLambdas*(n: PNode): PNode = assert n.kind in procDefs - if gCmd == cmdCompileToEcmaScript: return n var s = n.sons[namePos].sym + if gCmd == cmdCompileToEcmaScript: return s.getBody result = liftLambdas(s, s.getBody) diff --git a/compiler/msgs.nim b/compiler/msgs.nim index 53438c722..efd83cfd9 100755 --- a/compiler/msgs.nim +++ b/compiler/msgs.nim @@ -246,7 +246,7 @@ const errWrongNumberOfArguments: "wrong number of arguments", errXCannotBePassedToProcVar: "\'$1\' cannot be passed to a procvar", errXCannotBeInParamDecl: "$1 cannot be declared in parameter declaration", - errPragmaOnlyInHeaderOfProc: "pragmas are only in the header of a proc allowed", + errPragmaOnlyInHeaderOfProc: "pragmas are only allowed in the header of a proc", errImplOfXNotAllowed: "implementation of \'$1\' is not allowed", errImplOfXexpected: "implementation of \'$1\' expected", errNoSymbolToBorrowFromFound: "no symbol to borrow from found", @@ -270,7 +270,7 @@ const errInvalidParamKindX: "invalid param kind: \'$1\'", errDefaultArgumentInvalid: "default argument invalid", errNamedParamHasToBeIdent: "named parameter has to be an identifier", - errNoReturnTypeForX: "no return type for $1 allowed", + errNoReturnTypeForX: "no return type allowed for $1", errConvNeedsOneArg: "a type conversion needs exactly one argument", errInvalidPragmaX: "invalid pragma: $1", errXNotAllowedHere: "$1 not allowed here", |