summary refs log tree commit diff stats
path: root/compiler/ccgexprs.nim
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/ccgexprs.nim')
-rw-r--r--compiler/ccgexprs.nim233
1 files changed, 123 insertions, 110 deletions
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 6a2ffe752..2f7804384 100644
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -9,9 +9,6 @@
 
 # included from cgen.nim
 
-proc lenField: PRope {.inline.} = 
-  result = toRope(if gCmd != cmdCompileToCpp: "Sup.len" else: "len")
-
 # -------------------------- constant expressions ------------------------
 
 proc intLiteral(i: biggestInt): PRope =
@@ -207,8 +204,6 @@ proc asgnComplexity(n: PNode): int =
         result += asgnComplexity(t)
     else: nil
 
-proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags)
-
 proc optAsgnLoc(a: TLoc, t: PType, field: PRope): TLoc =
   result.k = locField
   result.s = a.s
@@ -345,11 +340,6 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
     linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
   else: InternalError("genAssignment(" & $ty.kind & ')')
 
-proc expr(p: BProc, e: PNode, d: var TLoc)
-proc initLocExpr(p: BProc, e: PNode, result: var TLoc) =
-  initLoc(result, locNone, e.typ, OnUnknown)
-  expr(p, e, result)
-
 proc getDestLoc(p: BProc, d: var TLoc, typ: PType) =
   if d.k == locNone: getTemp(p, typ, d)
 
@@ -377,15 +367,15 @@ proc putIntoDest(p: BProc, d: var TLoc, t: PType, r: PRope) =
     d.a = -1
 
 proc binaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
-  var b: TLoc
+  var a, b: TLoc
   if d.k != locNone: InternalError(e.info, "binaryStmt")
-  InitLocExpr(p, e.sons[1], d)
+  InitLocExpr(p, e.sons[1], a)
   InitLocExpr(p, e.sons[2], b)
-  lineCg(p, cpsStmts, frmt, rdLoc(d), rdLoc(b))
+  lineCg(p, cpsStmts, frmt, rdLoc(a), rdLoc(b))
 
 proc unaryStmt(p: BProc, e: PNode, d: var TLoc, frmt: string) =
   var a: TLoc
-  if (d.k != locNone): InternalError(e.info, "unaryStmt")
+  if d.k != locNone: InternalError(e.info, "unaryStmt")
   InitLocExpr(p, e.sons[1], a)
   lineCg(p, cpsStmts, frmt, [rdLoc(a)])
 
@@ -840,44 +830,6 @@ proc genAndOr(p: BProc, e: PNode, d: var TLoc, m: TMagic) =
   else:
     genAssignment(p, d, tmp, {}) # no need for deep copying
 
-proc genIfExpr(p: BProc, n: PNode, d: var TLoc) =
-  #
-  #  if (!expr1) goto L1;
-  #  thenPart
-  #  goto LEnd
-  #  L1:
-  #  if (!expr2) goto L2;
-  #  thenPart2
-  #  goto LEnd
-  #  L2:
-  #  elsePart
-  #  Lend:
-  #
-  var
-    it: PNode
-    a, tmp: TLoc
-    Lend, Lelse: TLabel
-  getTemp(p, n.typ, tmp)      # force it into a temp!
-  Lend = getLabel(p)
-  for i in countup(0, sonsLen(n) - 1):
-    it = n.sons[i]
-    case it.kind
-    of nkElifExpr:
-      initLocExpr(p, it.sons[0], a)
-      Lelse = getLabel(p)
-      lineF(p, cpsStmts, "if (!$1) goto $2;$n", [rdLoc(a), Lelse])
-      expr(p, it.sons[1], tmp)
-      lineF(p, cpsStmts, "goto $1;$n", [Lend])
-      fixLabel(p, Lelse)
-    of nkElseExpr:
-      expr(p, it.sons[0], tmp)
-    else: internalError(n.info, "genIfExpr()")
-  fixLabel(p, Lend)
-  if d.k == locNone:
-    d = tmp
-  else:
-    genAssignment(p, d, tmp, {}) # no need for deep copying
-
 proc genEcho(p: BProc, n: PNode) =
   # this unusal way of implementing it ensures that e.g. ``echo("hallo", 45)``
   # is threadsafe.
@@ -889,8 +841,6 @@ proc genEcho(p: BProc, n: PNode) =
   linefmt(p, cpsStmts, "printf($1$2);$n",
           makeCString(repeatStr(n.len-1, "%s") & tnl), args)
 
-include ccgcalls
-
 proc genStrConcat(p: BProc, e: PNode, d: var TLoc) =
   #   <Nimrod code>
   #   s = 'Hello ' & name & ', how do you feel?' & 'z'
@@ -1791,11 +1741,10 @@ proc exprComplexConst(p: BProc, n: PNode, d: var TLoc) =
   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
+proc expr(p: BProc, n: PNode, d: var TLoc) =
+  case n.kind
   of nkSym:
-    var sym = e.sym
+    var sym = n.sym
     case sym.Kind
     of skMethod:
       if sym.getBody.kind == nkEmpty or sfDispatcher in sym.flags:
@@ -1808,22 +1757,22 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
     of skProc, skConverter, skIterator:
       genProc(p.module, sym)
       if sym.loc.r == nil or sym.loc.t == nil:
-        InternalError(e.info, "expr: proc not init " & sym.name.s)
+        InternalError(n.info, "expr: proc not init " & sym.name.s)
       putLocIntoDest(p, d, sym.loc)
     of skConst:
       if sfFakeConst in sym.flags:
         if sfGlobal in sym.flags: genVarPrototype(p.module, sym)
         putLocIntoDest(p, d, sym.loc)
       elif isSimpleConst(sym.typ):
-        putIntoDest(p, d, e.typ, genLiteral(p, sym.ast, sym.typ))
+        putIntoDest(p, d, n.typ, genLiteral(p, sym.ast, sym.typ))
       else:
         genComplexConst(p, sym, d)
     of skEnumField:
-      putIntoDest(p, d, e.typ, toRope(sym.position))
+      putIntoDest(p, d, n.typ, toRope(sym.position))
     of skVar, skForVar, skResult, skLet:
       if sfGlobal in sym.flags: genVarPrototype(p.module, sym)
       if sym.loc.r == nil or sym.loc.t == nil:
-        InternalError(e.info, "expr: var not init " & sym.name.s)
+        InternalError(n.info, "expr: var not init " & sym.name.s)
       if sfThread in sym.flags:
         AccessThreadLocalVar(p, sym)
         if emulatedThreadVars(): 
@@ -1834,75 +1783,139 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
         putLocIntoDest(p, d, sym.loc)
     of skTemp:
       if sym.loc.r == nil or sym.loc.t == nil:
-        InternalError(e.info, "expr: temp not init " & sym.name.s)
+        InternalError(n.info, "expr: temp not init " & sym.name.s)
       putLocIntoDest(p, d, sym.loc)
     of skParam:
       if sym.loc.r == nil or sym.loc.t == nil:
-        InternalError(e.info, "expr: param not init " & sym.name.s)
+        InternalError(n.info, "expr: param not init " & sym.name.s)
       putLocIntoDest(p, d, sym.loc)
-    else: InternalError(e.info, "expr(" & $sym.kind & "); unknown symbol")
+    else: InternalError(n.info, "expr(" & $sym.kind & "); unknown symbol")
+  of nkNilLit:
+    if not isEmptyType(n.typ):
+      putIntoDest(p, d, n.typ, genLiteral(p, n))
   of nkStrLit..nkTripleStrLit, nkIntLit..nkUInt64Lit,
-     nkFloatLit..nkFloat128Lit, nkNilLit, nkCharLit:
-    putIntoDest(p, d, e.typ, genLiteral(p, e))
+     nkFloatLit..nkFloat128Lit, nkCharLit:
+    putIntoDest(p, d, n.typ, genLiteral(p, n))
   of nkCall, nkHiddenCallConv, nkInfix, nkPrefix, nkPostfix, nkCommand,
      nkCallStrLit:
-    if e.sons[0].kind == nkSym and e.sons[0].sym.magic != mNone:
-      genMagicExpr(p, e, d, e.sons[0].sym.magic)
+    genLineDir(p, n)
+    let op = n.sons[0]
+    if n.typ.isNil:
+      # discard the value:
+      var a: TLoc
+      if op.kind == nkSym and op.sym.magic != mNone:
+        genMagicExpr(p, n, a, op.sym.magic)
+      else:
+        genCall(p, n, a)
     else:
-      genCall(p, e, d)
+      # load it into 'd':
+      if op.kind == nkSym and op.sym.magic != mNone:
+        genMagicExpr(p, n, d, op.sym.magic)
+      else:
+        genCall(p, n, d)
   of nkCurly:
-    if isDeepConstExpr(e) and e.len != 0:
-      putIntoDest(p, d, e.typ, genSetNode(p, e))
+    if isDeepConstExpr(n) and n.len != 0:
+      putIntoDest(p, d, n.typ, genSetNode(p, n))
     else:
-      genSetConstr(p, e, d)
+      genSetConstr(p, n, d)
   of nkBracket:
-    if isDeepConstExpr(e) and e.len != 0:
-      exprComplexConst(p, e, d)
-    elif skipTypes(e.typ, abstractVarRange).kind == tySequence:
-      genSeqConstr(p, e, d)
+    if isDeepConstExpr(n) and n.len != 0:
+      exprComplexConst(p, n, d)
+    elif skipTypes(n.typ, abstractVarRange).kind == tySequence:
+      genSeqConstr(p, n, d)
     else:
-      genArrayConstr(p, e, d)
+      genArrayConstr(p, n, d)
   of nkPar:
-    if isDeepConstExpr(e) and e.len != 0:
-      exprComplexConst(p, e, d)
+    if isDeepConstExpr(n) and n.len != 0:
+      exprComplexConst(p, n, d)
     else:
-      genTupleConstr(p, e, d)
-  of nkObjConstr: genObjConstr(p, e, d)
-  of nkCast: genCast(p, e, d)
-  of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, e, d)
-  of nkHiddenAddr, nkAddr: genAddr(p, e, d)
+      genTupleConstr(p, n, d)
+  of nkObjConstr: genObjConstr(p, n, d)
+  of nkCast: genCast(p, n, d)
+  of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, d)
+  of nkHiddenAddr, nkAddr: genAddr(p, n, d)
   of nkBracketExpr:
-    var ty = skipTypes(e.sons[0].typ, abstractVarRange)
+    var ty = skipTypes(n.sons[0].typ, abstractVarRange)
     if ty.kind in {tyRef, tyPtr}: ty = skipTypes(ty.sons[0], abstractVarRange)
     case ty.kind
-    of tyArray, tyArrayConstr: genArrayElem(p, e, d)
-    of tyOpenArray, tyVarargs: genOpenArrayElem(p, e, d)
-    of tySequence, tyString: genSeqElem(p, e, d)
-    of tyCString: genCStringElem(p, e, d)
-    of tyTuple: genTupleElem(p, e, d)
-    else: InternalError(e.info, "expr(nkBracketExpr, " & $ty.kind & ')')
-  of nkDerefExpr, nkHiddenDeref: genDeref(p, e, d)
-  of nkDotExpr: genRecordField(p, e, d)
-  of nkCheckedFieldExpr: genCheckedRecordField(p, e, d)
-  of nkBlockExpr: genBlock(p, e, d)
-  of nkStmtListExpr: genStmtListExpr(p, e, d)
-  of nkIfExpr: genIfExpr(p, e, d)
-  of nkObjDownConv: downConv(p, e, d)
-  of nkObjUpConv: upConv(p, e, d)
-  of nkChckRangeF: genRangeChck(p, e, d, "chckRangeF")
-  of nkChckRange64: genRangeChck(p, e, d, "chckRange64")
-  of nkChckRange: genRangeChck(p, e, d, "chckRange")
-  of nkStringToCString: convStrToCStr(p, e, d)
-  of nkCStringToString: convCStrToStr(p, e, d)
+    of tyArray, tyArrayConstr: genArrayElem(p, n, d)
+    of tyOpenArray, tyVarargs: genOpenArrayElem(p, n, d)
+    of tySequence, tyString: genSeqElem(p, n, d)
+    of tyCString: genCStringElem(p, n, d)
+    of tyTuple: genTupleElem(p, n, d)
+    else: InternalError(n.info, "expr(nkBracketExpr, " & $ty.kind & ')')
+  of nkDerefExpr, nkHiddenDeref: genDeref(p, n, d)
+  of nkDotExpr: genRecordField(p, n, d)
+  of nkCheckedFieldExpr: genCheckedRecordField(p, n, d)
+  of nkBlockExpr, nkBlockStmt: genBlock(p, n, d)
+  of nkStmtListExpr: genStmtListExpr(p, n, d)
+  of nkStmtList:
+    for i in countup(0, sonsLen(n) - 1): genStmts(p, n.sons[i])
+  of nkIfExpr, nkIfStmt: genIf(p, n, d)
+  of nkObjDownConv: downConv(p, n, d)
+  of nkObjUpConv: upConv(p, n, d)
+  of nkChckRangeF: genRangeChck(p, n, d, "chckRangeF")
+  of nkChckRange64: genRangeChck(p, n, d, "chckRange64")
+  of nkChckRange: genRangeChck(p, n, d, "chckRange")
+  of nkStringToCString: convStrToCStr(p, n, d)
+  of nkCStringToString: convCStrToStr(p, n, d)
   of nkLambdaKinds:
-    var sym = e.sons[namePos].sym
+    var sym = n.sons[namePos].sym
     genProc(p.module, sym)
     if sym.loc.r == nil or sym.loc.t == nil:
-      InternalError(e.info, "expr: proc not init " & sym.name.s)
+      InternalError(n.info, "expr: proc not init " & sym.name.s)
     putLocIntoDest(p, d, sym.loc)
-  of nkClosure: genClosure(p, e, d)
-  of nkMetaNode: expr(p, e.sons[0], d)
-  else: InternalError(e.info, "expr(" & $e.kind & "); unknown node kind")
+  of nkClosure: genClosure(p, n, d)
+  of nkMetaNode: expr(p, n.sons[0], d)
+
+  of nkEmpty:  nil
+  of nkWhileStmt: genWhileStmt(p, n)
+  of nkVarSection, nkLetSection: genVarStmt(p, n)
+  of nkConstSection: genConstStmt(p, n)
+  of nkForStmt: internalError(n.info, "for statement not eliminated")
+  of nkCaseStmt: genCase(p, n, d)
+  of nkReturnStmt: genReturnStmt(p, n)
+  of nkBreakStmt: genBreakStmt(p, n)
+  of nkAsgn: genAsgn(p, n, fastAsgn=false)
+  of nkFastAsgn:
+    # transf is overly aggressive with 'nkFastAsgn', so we work around here.
+    # See tests/run/tcnstseq3 for an example that would fail otherwise.
+    genAsgn(p, n, fastAsgn=p.prc != nil)
+  of nkDiscardStmt:
+    if n.sons[0].kind != nkEmpty:
+      var a: TLoc
+      genLineDir(p, n)
+      initLocExpr(p, n.sons[0], a)
+  of nkAsmStmt: genAsmStmt(p, n)
+  of nkTryStmt:
+    if gCmd == cmdCompileToCpp: genTryCpp(p, n, d)
+    else: genTry(p, n, d)
+  of nkRaiseStmt: genRaiseStmt(p, n)
+  of nkTypeSection:
+    # we have to emit the type information for object types here to support
+    # separate compilation:
+    genTypeSection(p.module, n)
+  of nkCommentStmt, nkIteratorDef, nkIncludeStmt, 
+     nkImportStmt, nkImportExceptStmt, nkExportStmt, nkExportExceptStmt, 
+     nkFromStmt, nkTemplateDef, nkMacroDef: 
+    nil
+  of nkPragma: genPragma(p, n)
+  of nkProcDef, nkMethodDef, nkConverterDef: 
+    if (n.sons[genericParamsPos].kind == nkEmpty): 
+      var prc = n.sons[namePos].sym
+      if (optDeadCodeElim notin gGlobalOptions and
+          sfDeadCodeElim notin getModule(prc).flags) or
+          ({sfExportc, sfCompilerProc} * prc.flags == {sfExportc}) or
+          (sfExportc in prc.flags and lfExportLib in prc.loc.flags) or
+          (prc.kind == skMethod): 
+        # we have not only the header: 
+        if prc.getBody.kind != nkEmpty or lfDynamicLib in prc.loc.flags: 
+          genProc(p.module, prc)
+  of nkParForStmt: genParForStmt(p, n)
+  of nkState: genState(p, n)
+  of nkGotoState: genGotoState(p, n)
+  of nkBreakState: genBreakState(p, n)
+  else: InternalError(n.info, "expr(" & $n.kind & "); unknown node kind")
 
 proc genNamedConstExpr(p: BProc, n: PNode): PRope =
   if n.kind == nkExprColonExpr: result = genConstExpr(p, n.sons[1])