summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2013-02-24 03:51:45 +0100
committerAraq <rumpf_a@web.de>2013-02-24 03:51:45 +0100
commit9fc2bfa799ef432c96853d13b4487e99d5028f83 (patch)
tree7cf5ace0baea98da02c9b0453afaf1be86c7bcd5 /compiler
parent180ab350dcad1b6755d15f671b9b74b56897d0c7 (diff)
downloadNim-9fc2bfa799ef432c96853d13b4487e99d5028f83.tar.gz
codegen produces better code for complex assignments
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/c2nim/c2nim.nim4
-rw-r--r--compiler/ccgcalls.nim2
-rwxr-xr-xcompiler/ccgexprs.nim63
3 files changed, 64 insertions, 5 deletions
diff --git a/compiler/c2nim/c2nim.nim b/compiler/c2nim/c2nim.nim
index 40fb209c7..029f9ecda 100755
--- a/compiler/c2nim/c2nim.nim
+++ b/compiler/c2nim/c2nim.nim
@@ -1,7 +1,7 @@
 #
 #
 #      c2nim - C to Nimrod source converter
-#        (c) Copyright 2012 Andreas Rumpf
+#        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -15,7 +15,7 @@ const
   Version = NimrodVersion
   Usage = """
 c2nim - C to Nimrod source converter
-  (c) 2012 Andreas Rumpf
+  (c) 2013 Andreas Rumpf
 Usage: c2nim [options] inputfile [options]
 Options:
   -o, --out:FILE         set output filename
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim
index 71e4fe39b..b8b7f4c44 100644
--- a/compiler/ccgcalls.nim
+++ b/compiler/ccgcalls.nim
@@ -1,7 +1,7 @@
 #
 #
 #           The Nimrod Compiler
-#        (c) Copyright 2012 Andreas Rumpf
+#        (c) Copyright 2013 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index c6efaa7a0..cc97baaa4 100755
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -195,6 +195,46 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
             addrLoc(dest), rdLoc(src))
     if needToKeepAlive in flags: keepAlive(p, dest)
 
+proc asgnComplexity(n: PNode): int =
+  if n != nil:
+    case n.kind
+    of nkSym: result = 1
+    of nkRecCase:
+      # 'case objects' are too difficult to inline their assignment operation:
+      result = 100
+    of nkRecList:
+      for t in items(n):
+        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
+  result.t = t
+  result.r = rdLoc(a).con(".").con(field)
+  result.heapRoot = a.heapRoot
+
+proc genOptAsgnTuple(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
+  for i in 0 .. <dest.t.len:
+    let t = dest.t.sons[i]
+    let field = ropef("Field$1", i.toRope)
+    genAssignment(p, optAsgnLoc(dest, t, field), 
+                     optAsgnLoc(src, t, field), flags)
+
+proc genOptAsgnObject(p: BProc, dest, src: TLoc, flags: TAssignmentFlags,
+                      t: PNode) =
+  if t == nil: return
+  case t.kind
+  of nkSym:
+    let field = t.sym
+    genAssignment(p, optAsgnLoc(dest, field.typ, field.loc.r), 
+                     optAsgnLoc(src, field.typ, field.loc.r), flags)
+  of nkRecList:
+    for child in items(t): genOptAsgnObject(p, dest, src, flags, child)
+  else: nil
+
 proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
   # Consider: 
   # type TMyFastString {.shallow.} = string
@@ -251,10 +291,29 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
         linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
                addrLoc(dest), rdLoc(src))
         if needToKeepAlive in flags: keepAlive(p, dest)
-  of tyTuple, tyObject, tyProc:
+  of tyProc:
+    if needsComplexAssignment(dest.t):
+      # optimize closure assignment:
+      let a = optAsgnLoc(dest, dest.t, "ClEnv".toRope)
+      let b = optAsgnLoc(src, dest.t, "ClEnv".toRope)
+      genRefAssign(p, a, b, flags)
+      linefmt(p, cpsStmts, "$1.ClPrc = $2.ClPrc;$n", rdLoc(dest), rdLoc(src))
+    else:
+      linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
+  of tyTuple:
+    if needsComplexAssignment(dest.t):
+      if dest.t.len <= 4: genOptAsgnTuple(p, dest, src, flags)
+      else: genGenericAsgn(p, dest, src, flags)
+    else:
+      linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
+  of tyObject:
     # XXX: check for subtyping?
     if needsComplexAssignment(dest.t):
-      genGenericAsgn(p, dest, src, flags)
+      if asgnComplexity(dest.t.n) <= 4:
+        discard getTypeDesc(p.module, dest.t)
+        genOptAsgnObject(p, dest, src, flags, dest.t.n)
+      else:
+        genGenericAsgn(p, dest, src, flags)
     else:
       linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
   of tyArray, tyArrayConstr: