diff options
author | Araq <rumpf_a@web.de> | 2013-02-24 03:51:45 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2013-02-24 03:51:45 +0100 |
commit | 9fc2bfa799ef432c96853d13b4487e99d5028f83 (patch) | |
tree | 7cf5ace0baea98da02c9b0453afaf1be86c7bcd5 /compiler | |
parent | 180ab350dcad1b6755d15f671b9b74b56897d0c7 (diff) | |
download | Nim-9fc2bfa799ef432c96853d13b4487e99d5028f83.tar.gz |
codegen produces better code for complex assignments
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/c2nim/c2nim.nim | 4 | ||||
-rw-r--r-- | compiler/ccgcalls.nim | 2 | ||||
-rwxr-xr-x | compiler/ccgexprs.nim | 63 |
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: |