summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-06-30 12:29:56 +0200
committerAraq <rumpf_a@web.de>2012-06-30 12:29:56 +0200
commitee1bcb6414a50642811632a92a803840c1c67036 (patch)
tree07e2be9d40db1a33cc29cf9d6f9f2dac9b9a5f38 /compiler
parent2900ceae3580a9f1e83b500cf1abcdfe77762cad (diff)
downloadNim-ee1bcb6414a50642811632a92a803840c1c67036.tar.gz
dead code elimination for JS backend; JS improvements (but doesn't work yet)
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/ecmasgen.nim189
-rw-r--r--compiler/lambdalifting.nim2
-rwxr-xr-xcompiler/msgs.nim4
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",