summary refs log tree commit diff stats
path: root/rod/cgen.nim
diff options
context:
space:
mode:
Diffstat (limited to 'rod/cgen.nim')
-rwxr-xr-xrod/cgen.nim110
1 files changed, 72 insertions, 38 deletions
diff --git a/rod/cgen.nim b/rod/cgen.nim
index f13f5991a..503cb8586 100755
--- a/rod/cgen.nim
+++ b/rod/cgen.nim
@@ -256,35 +256,75 @@ proc rdCharLoc(a: TLoc): PRope =
   if skipTypes(a.t, abstractRange).kind == tyChar:
     result = ropef("((NU8)($1))", [result])
 
-proc zeroLoc(p: BProc, loc: TLoc) = 
-  if not (skipTypes(loc.t, abstractVarRange).Kind in
-      {tyArray, tyArrayConstr, tySet, tyTuple, tyObject}): 
-    if gCmd == cmdCompileToLLVM: 
-      appf(p.s[cpsStmts], "store $2 0, $2* $1$n", 
-           [addrLoc(loc), getTypeDesc(p.module, loc.t)])
-    else: 
+proc genObjectInit(p: BProc, section: TCProcSection, t: PType, a: TLoc, 
+                   takeAddr: bool) =
+  case analyseObjectWithTypeField(t)
+  of frNone:
+    nil
+  of frHeader:
+    var r = rdLoc(a)
+    if not takeAddr: r = ropef("(*$1)", [r])
+    var s = t
+    while (s.kind == tyObject) and (s.sons[0] != nil):
+      app(r, ".Sup")
+      s = skipTypes(s.sons[0], abstractInst)
+    appcg(p, section, "$1.m_type = $2;$n", [r, genTypeInfo(p.module, t)])
+  of frEmbedded:
+    # worst case for performance:
+    var r = if takeAddr: addrLoc(a) else: rdLoc(a)
+    appcg(p, section, "#objectInit($1, $2);$n", [r, genTypeInfo(p.module, t)])
+
+type
+  TAssignmentFlag = enum
+    needToCopy, needForSubtypeCheck, afDestIsNil, afDestIsNotNil, afSrcIsNil,
+    afSrcIsNotNil
+  TAssignmentFlags = set[TAssignmentFlag]
+
+proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags)
+
+proc zeroVar(p: BProc, loc: TLoc, containsGCref: bool) = 
+  if skipTypes(loc.t, abstractVarRange).Kind notin
+      {tyArray, tyArrayConstr, tySet, tyTuple, tyObject}: 
+    if containsGcref:
+      appf(p.s[cpsInit], "$1 = 0;$n", [rdLoc(loc)])
+      var nilLoc: TLoc
+      initLoc(nilLoc, locTemp, loc.t, onStack)
+      nilLoc.r = toRope("NIM_NIL")
+      # puts ``unsureAsgnRef`` etc to ``p.s[cpsStmts]``:
+      genRefAssign(p, loc, nilLoc, {afSrcIsNil})
+    else:
       appf(p.s[cpsStmts], "$1 = 0;$n", [rdLoc(loc)])
   else: 
-    if gCmd == cmdCompileToLLVM: 
-      app(p.module.s[cfsProcHeaders], 
-          "declare void @llvm.memset.i32(i8*, i8, i32, i32)" & tnl)
-      inc(p.labels, 2)
-      appf(p.s[cpsStmts], "%LOC$3 = getelementptr $2* null, %NI 1$n" &
-          "%LOC$4 = cast $2* %LOC$3 to i32$n" &
-          "call void @llvm.memset.i32(i8* $1, i8 0, i32 %LOC$4, i32 0)$n", [
-          addrLoc(loc), getTypeDesc(p.module, loc.t), toRope(p.labels), 
-          toRope(p.labels - 1)])
-    else: 
+    if containsGcref:
+      appf(p.s[cpsInit], "memset((void*)$1, 0, sizeof($2));$n", 
+           [addrLoc(loc), rdLoc(loc)])
+      appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n", 
+           [addrLoc(loc), genTypeInfo(p.module, loc.t)])
+    else:
       appf(p.s[cpsStmts], "memset((void*)$1, 0, sizeof($2));$n", 
            [addrLoc(loc), rdLoc(loc)])
+    genObjectInit(p, cpsInit, loc.t, loc, true)
+
+proc zeroTemp(p: BProc, loc: TLoc) = 
+  if skipTypes(loc.t, abstractVarRange).Kind notin
+      {tyArray, tyArrayConstr, tySet, tyTuple, tyObject}: 
+    var nilLoc: TLoc
+    initLoc(nilLoc, locTemp, loc.t, onStack)
+    nilLoc.r = toRope("NIM_NIL")
+    # puts ``unsureAsgnRef`` etc to ``p.s[cpsStmts]``:
+    genRefAssign(p, loc, nilLoc, {afSrcIsNil})
+  else: 
+    appcg(p, cpsStmts, "#genericReset((void*)$1, $2);$n", 
+         [addrLoc(loc), genTypeInfo(p.module, loc.t)])
 
 proc initVariable(p: BProc, v: PSym) = 
-  if containsGarbageCollectedRef(v.typ) or (v.ast == nil): 
-    zeroLoc(p, v.loc)
+  var b = containsGarbageCollectedRef(v.typ)
+  if b or v.ast == nil: 
+    zeroVar(p, v.loc, b)
     
 proc initTemp(p: BProc, tmp: var TLoc) = 
   if containsGarbageCollectedRef(tmp.t):
-    zeroLoc(p, tmp)
+    zeroTemp(p, tmp)
 
 proc getTemp(p: BProc, t: PType, result: var TLoc) = 
   inc(p.labels)
@@ -324,11 +364,10 @@ proc cstringLit(m: BModule, r: var PRope, s: string): PRope =
     result = makeCString(s)
   
 proc allocParam(p: BProc, s: PSym) = 
-  var tmp: PRope
   assert(s.kind == skParam)
   if not (lfParamCopy in s.loc.flags): 
     inc(p.labels)
-    tmp = con("%LOC", toRope(p.labels))
+    var tmp = con("%LOC", toRope(p.labels))
     incl(s.loc.flags, lfParamCopy)
     incl(s.loc.flags, lfIndirect)
     appf(p.s[cpsInit], "$1 = alloca $3$n" & "store $3 $2, $3* $1$n", 
@@ -520,11 +559,7 @@ proc cgsym(m: BModule, name: string): PRope =
     # 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:
-    when false:
-      if not (sfSystemModule in m.module.flags): 
-        rawMessage(errSystemNeeds, name) 
-    else:
-      rawMessage(errSystemNeeds, name)
+    rawMessage(errSystemNeeds, name)
   result = sym.loc.r
   
 proc generateHeaders(m: BModule) = 
@@ -593,14 +628,13 @@ proc genProcAux(m: BModule, prc: PSym) =
       assignLocalVar(p, res)
       assert(res.loc.r != nil)
       returnStmt = ropeff("return $1;$n", "ret $1$n", [rdLoc(res.loc)])
+      initVariable(p, res)
     else: 
       fillResult(res)
       assignParam(p, res)
       if skipTypes(res.typ, abstractInst).kind == tyArray: 
         incl(res.loc.flags, lfIndirect)
         res.loc.s = OnUnknown
-    initVariable(p, res)
-    genObjectInit(p, res.typ, res.loc, true)
   for i in countup(1, sonsLen(prc.typ.n) - 1): 
     param = prc.typ.n.sons[i].sym
     assignParam(p, param)
@@ -644,23 +678,22 @@ proc genProcAux(m: BModule, prc: PSym) =
   
 proc genProcPrototype(m: BModule, sym: PSym) = 
   useHeader(m, sym)
-  if (lfNoDecl in sym.loc.Flags): return 
+  if lfNoDecl in sym.loc.Flags: return 
   if lfDynamicLib in sym.loc.Flags: 
-    if (sym.owner.id != m.module.id) and
+    if sym.owner.id != m.module.id and
         not intSetContainsOrIncl(m.declaredThings, sym.id): 
       appff(m.s[cfsVars], "extern $1 $2;$n", 
             "@$2 = linkonce global $1 zeroinitializer$n", 
             [getTypeDesc(m, sym.loc.t), mangleDynLibProc(sym)])
       if gCmd == cmdCompileToLLVM: incl(sym.loc.flags, lfIndirect)
-  else: 
-    if not IntSetContainsOrIncl(m.declaredProtos, sym.id): 
-      appf(m.s[cfsProcHeaders], "$1;$n", [genProcHeader(m, sym)])
+  elif not IntSetContainsOrIncl(m.declaredProtos, sym.id): 
+    appf(m.s[cfsProcHeaders], "$1;$n", [genProcHeader(m, sym)])
 
 proc genProcNoForward(m: BModule, prc: PSym) = 
   fillProcLoc(prc)
   useHeader(m, prc)
   genProcPrototype(m, prc)
-  if (lfNoDecl in prc.loc.Flags): return 
+  if lfNoDecl in prc.loc.Flags: return 
   if prc.typ.callConv == ccInline: 
     # We add inline procs to the calling module to enable C based inlining.
     # This also means that a check with ``gGeneratedSyms`` is wrong, we need
@@ -771,7 +804,8 @@ proc genMainProc(m: BModule) =
         "  NimMain();$n" & "  return 0;$n" & "}$n"
     WinNimDllMain = "N_LIB_EXPORT N_CDECL(void, NimMain)(void) {$n" &
         CommonMainBody & "}$n"
-    WinCDllMain = "BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, $n" &
+    WinCDllMain = 
+        "BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fwdreason, $n" &
         "                    LPVOID lpvReserved) {$n" & "  NimMain();$n" &
         "  return 1;$n" & "}$n"
     PosixNimDllMain = WinNimDllMain
@@ -779,8 +813,8 @@ proc genMainProc(m: BModule) =
         "void NIM_POSIX_INIT NimMainInit(void) {$n" &
         "  NimMain();$n}$n"
   var nimMain, otherMain: TFormatStr
-  if (platform.targetOS == osWindows) and
-      (gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}): 
+  if platform.targetOS == osWindows and
+      gGlobalOptions * {optGenGuiApp, optGenDynLib} != {}: 
     if optGenGuiApp in gGlobalOptions: 
       nimMain = WinNimMain
       otherMain = WinCMain