summary refs log tree commit diff stats
path: root/compiler/cgen.nim
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2019-12-19 11:35:15 +0100
committerAndreas Rumpf <rumpf_a@web.de>2019-12-24 17:33:27 +0100
commitd1d017ae859181106c835413c48c46dc036d4c49 (patch)
tree92e2929e5531d1162dd107f3495e04379698bb4d /compiler/cgen.nim
parenta7b4b2ed5401325a3a0612e7afd4ecff83d8778f (diff)
downloadNim-d1d017ae859181106c835413c48c46dc036d4c49.tar.gz
fixes #12826
Diffstat (limited to 'compiler/cgen.nim')
-rw-r--r--compiler/cgen.nim53
1 files changed, 34 insertions, 19 deletions
diff --git a/compiler/cgen.nim b/compiler/cgen.nim
index 5b336e78d..8a7b79d76 100644
--- a/compiler/cgen.nim
+++ b/compiler/cgen.nim
@@ -326,8 +326,22 @@ proc rdCharLoc(a: TLoc): Rope =
   if skipTypes(a.t, abstractRange).kind == tyChar:
     result = "((NU8)($1))" % [result]
 
-proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
-                   takeAddr: bool) =
+type
+  TAssignmentFlag = enum
+    needToCopy
+  TAssignmentFlags = set[TAssignmentFlag]
+
+proc genObjConstr(p: BProc, e: PNode, d: var TLoc)
+proc rawConstExpr(p: BProc, n: PNode; d: var TLoc)
+proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags)
+
+type
+  ObjConstrMode = enum
+    constructObj,
+    constructRefObj
+
+proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: var TLoc,
+                   mode: ObjConstrMode) =
   if p.module.compileToCpp and t.isException and not isDefined(p.config, "noCppExceptions"):
     # init vtable in Exception object for polymorphic exceptions
     includeHeader(p.module, "<new>")
@@ -339,7 +353,7 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
     discard
   of frHeader:
     var r = rdLoc(a)
-    if not takeAddr: r = "(*$1)" % [r]
+    if mode == constructRefObj: r = "(*$1)" % [r]
     var s = skipTypes(t, abstractInst)
     if not p.module.compileToCpp:
       while s.kind == tyObject and s[0] != nil:
@@ -348,15 +362,22 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
     linefmt(p, section, "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t, a.lode.info)])
   of frEmbedded:
     if optTinyRtti in p.config.globalOptions:
-      localError(p.config, p.prc.info,
-        "complex object initialization is not supported with --newruntime")
-    # worst case for performance:
-    var r = if takeAddr: addrLoc(p.config, a) else: rdLoc(a)
-    linefmt(p, section, "#objectInit($1, $2);$n", [r, genTypeInfo(p.module, t, a.lode.info)])
+      var n = newNodeIT(nkObjConstr, a.lode.info, t)
+      n.add newNodeIT(nkType, a.lode.info, t)
+      if mode == constructRefObj:
+        genObjConstr(p, n, a)
+      else:
+        var tmp: TLoc
+        rawConstExpr(p, n, tmp)
+        genAssignment(p, a, tmp, {})
+    else:
+      # worst case for performance:
+      var r = if mode == constructObj: addrLoc(p.config, a) else: rdLoc(a)
+      linefmt(p, section, "#objectInit($1, $2);$n", [r, genTypeInfo(p.module, t, a.lode.info)])
 
   if isException(t):
     var r = rdLoc(a)
-    if not takeAddr: r = "(*$1)" % [r]
+    if mode == constructRefObj: r = "(*$1)" % [r]
     var s = skipTypes(t, abstractInst)
     if not p.module.compileToCpp:
       while s.kind == tyObject and s[0] != nil and s.sym.magic != mException:
@@ -364,11 +385,6 @@ proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc,
         s = skipTypes(s[0], skipPtrs)
     linefmt(p, section, "$1.name = $2;$n", [r, makeCString(t.skipTypes(abstractInst).sym.name.s)])
 
-type
-  TAssignmentFlag = enum
-    needToCopy
-  TAssignmentFlags = set[TAssignmentFlag]
-
 proc genRefAssign(p: BProc, dest, src: TLoc)
 
 proc isComplexValueType(t: PType): bool {.inline.} =
@@ -399,7 +415,7 @@ proc resetLoc(p: BProc, loc: var TLoc) =
               [addrLoc(p.config, loc), genTypeInfo(p.module, loc.t, loc.lode.info)])
       # XXX: generated reset procs should not touch the m_type
       # field, so disabling this should be safe:
-      genObjectInit(p, cpsStmts, loc.t, loc, true)
+      genObjectInit(p, cpsStmts, loc.t, loc, constructObj)
     else:
       # array passed as argument decayed into pointer, bug #7332
       # so we use getTypeDesc here rather than rdLoc(loc)
@@ -407,9 +423,9 @@ proc resetLoc(p: BProc, loc: var TLoc) =
               [addrLoc(p.config, loc), getTypeDesc(p.module, loc.t)])
       # XXX: We can be extra clever here and call memset only
       # on the bytes following the m_type field?
-      genObjectInit(p, cpsStmts, loc.t, loc, true)
+      genObjectInit(p, cpsStmts, loc.t, loc, constructObj)
 
-proc constructLoc(p: BProc, loc: TLoc, isTemp = false) =
+proc constructLoc(p: BProc, loc: var TLoc, isTemp = false) =
   let typ = loc.t
   if optSeqDestructors in p.config.globalOptions and skipTypes(typ, abstractInst).kind in {tyString, tySequence}:
     linefmt(p, cpsStmts, "$1.len = 0; $1.p = NIM_NIL;$n", [rdLoc(loc)])
@@ -423,7 +439,7 @@ proc constructLoc(p: BProc, loc: TLoc, isTemp = false) =
       if not isImportedCppType(typ):
         linefmt(p, cpsStmts, "#nimZeroMem((void*)$1, sizeof($2));$n",
                 [addrLoc(p.config, loc), getTypeDesc(p.module, typ)])
-    genObjectInit(p, cpsStmts, loc.t, loc, true)
+    genObjectInit(p, cpsStmts, loc.t, loc, constructObj)
 
 proc initLocalVar(p: BProc, v: PSym, immediateAsgn: bool) =
   if sfNoInit notin v.flags:
@@ -580,7 +596,6 @@ proc genStmts(p: BProc, t: PNode)
 proc expr(p: BProc, n: PNode, d: var TLoc)
 proc genProcPrototype(m: BModule, sym: PSym)
 proc putLocIntoDest(p: BProc, d: var TLoc, s: TLoc)
-proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags)
 proc intLiteral(i: BiggestInt): Rope
 proc genLiteral(p: BProc, n: PNode): Rope
 proc genOtherArg(p: BProc; ri: PNode; i: int; typ: PType): Rope