codegen produces better code for complex assignments
This commit is contained in:
parent
180ab350dc
commit
9fc2bfa799
4 changed files with 68 additions and 10 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# c2nim - C to Nimrod source converter
|
# c2nim - C to Nimrod source converter
|
||||||
# (c) Copyright 2012 Andreas Rumpf
|
# (c) Copyright 2013 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
@ -15,7 +15,7 @@ const
|
||||||
Version = NimrodVersion
|
Version = NimrodVersion
|
||||||
Usage = """
|
Usage = """
|
||||||
c2nim - C to Nimrod source converter
|
c2nim - C to Nimrod source converter
|
||||||
(c) 2012 Andreas Rumpf
|
(c) 2013 Andreas Rumpf
|
||||||
Usage: c2nim [options] inputfile [options]
|
Usage: c2nim [options] inputfile [options]
|
||||||
Options:
|
Options:
|
||||||
-o, --out:FILE set output filename
|
-o, --out:FILE set output filename
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
# The Nimrod Compiler
|
# The Nimrod Compiler
|
||||||
# (c) Copyright 2012 Andreas Rumpf
|
# (c) Copyright 2013 Andreas Rumpf
|
||||||
#
|
#
|
||||||
# See the file "copying.txt", included in this
|
# See the file "copying.txt", included in this
|
||||||
# distribution, for details about the copyright.
|
# distribution, for details about the copyright.
|
||||||
|
|
|
||||||
|
|
@ -195,6 +195,46 @@ proc genRefAssign(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
addrLoc(dest), rdLoc(src))
|
addrLoc(dest), rdLoc(src))
|
||||||
if needToKeepAlive in flags: keepAlive(p, dest)
|
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) =
|
proc genGenericAsgn(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
|
||||||
# Consider:
|
# Consider:
|
||||||
# type TMyFastString {.shallow.} = string
|
# 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",
|
linefmt(p, cpsStmts, "#unsureAsgnRef((void**) $1, #copyString($2));$n",
|
||||||
addrLoc(dest), rdLoc(src))
|
addrLoc(dest), rdLoc(src))
|
||||||
if needToKeepAlive in flags: keepAlive(p, dest)
|
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?
|
# XXX: check for subtyping?
|
||||||
if needsComplexAssignment(dest.t):
|
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:
|
else:
|
||||||
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
linefmt(p, cpsStmts, "$1 = $2;$n", rdLoc(dest), rdLoc(src))
|
||||||
of tyArray, tyArrayConstr:
|
of tyArray, tyArrayConstr:
|
||||||
|
|
|
||||||
9
todo.txt
9
todo.txt
|
|
@ -4,16 +4,11 @@ version 0.9.2
|
||||||
- FFI:
|
- FFI:
|
||||||
* test libffi on windows
|
* test libffi on windows
|
||||||
* test: times.format with the FFI
|
* 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
|
- acyclic vs prunable; introduce GC hints
|
||||||
- implement constructors + full 'not nil' checking
|
- implement constructors + full 'not nil' checking
|
||||||
- CGEN: ``restrict`` pragma + backend support; computed goto support
|
- CGEN: ``restrict`` pragma + backend support; computed goto support
|
||||||
- fix:
|
- fix:
|
||||||
- 'result' is not properly cleaned for NRVO
|
- 'result' is not properly cleaned for NRVO
|
||||||
- optimize genericAssign in the code generator
|
|
||||||
- document NimMain and check whether it works for threading
|
- 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
|
- implement marker procs for message passing
|
||||||
- activate more thread tests
|
- activate more thread tests
|
||||||
- implement closures that support nesting of *procs* > 1
|
- 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
|
GC
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue