codegen produces better code for complex assignments

This commit is contained in:
Araq
2013-02-24 03:51:45 +01:00
parent 180ab350dc
commit 9fc2bfa799
4 changed files with 68 additions and 10 deletions

View File

@@ -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

View File

@@ -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.

View File

@@ -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:

View File

@@ -4,16 +4,11 @@ version 0.9.2
- FFI:
* test libffi on windows
* test: times.format with the FFI
- GC: implement simple generational GC
* first version: mark black in write barrier
* second version: introduce fake roots instead of marking black
* third version: find some clever heuristic which is preferable
- acyclic vs prunable; introduce GC hints
- implement constructors + full 'not nil' checking
- CGEN: ``restrict`` pragma + backend support; computed goto support
- fix:
- 'result' is not properly cleaned for NRVO
- optimize genericAssign in the code generator
- document NimMain and check whether it works for threading
@@ -94,6 +89,10 @@ Not essential for 1.0.0
- implement marker procs for message passing
- activate more thread tests
- implement closures that support nesting of *procs* > 1
- GC: implement simple generational GC
* first version: mark black in write barrier
* second version: introduce fake roots instead of marking black
* third version: find some clever heuristic which is preferable
GC