fixes #1023
This commit is contained in:
parent
5f478e5aa1
commit
5f64d7a353
3 changed files with 50 additions and 21 deletions
|
|
@ -465,6 +465,15 @@ proc needsAsgnPatch(n: PNode): bool =
|
||||||
n.kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr,
|
n.kind in {nkBracketExpr, nkDotExpr, nkCheckedFieldExpr,
|
||||||
nkDerefExpr, nkHiddenDeref} or (n.kind == nkSym and n.sym.isGlobal)
|
nkDerefExpr, nkHiddenDeref} or (n.kind == nkSym and n.sym.isGlobal)
|
||||||
|
|
||||||
|
proc genField(n: PNode): TRegister =
|
||||||
|
if n.kind != nkSym or n.sym.kind != skField:
|
||||||
|
internalError(n.info, "no field symbol")
|
||||||
|
let s = n.sym
|
||||||
|
if s.position > high(result):
|
||||||
|
internalError(n.info,
|
||||||
|
"too large offset! cannot generate code for: " & s.name.s)
|
||||||
|
result = s.position
|
||||||
|
|
||||||
proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
|
proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
|
||||||
case le.kind
|
case le.kind
|
||||||
of nkBracketExpr:
|
of nkBracketExpr:
|
||||||
|
|
@ -477,10 +486,9 @@ proc genAsgnPatch(c: PCtx; le: PNode, value: TRegister) =
|
||||||
# XXX field checks here
|
# XXX field checks here
|
||||||
let left = if le.kind == nkDotExpr: le else: le.sons[0]
|
let left = if le.kind == nkDotExpr: le else: le.sons[0]
|
||||||
let dest = c.genx(left.sons[0], {gfAddrOf})
|
let dest = c.genx(left.sons[0], {gfAddrOf})
|
||||||
let idx = c.genx(left.sons[1])
|
let idx = genField(left.sons[1])
|
||||||
c.gABC(left, opcWrObj, dest, idx, value)
|
c.gABC(left, opcWrObj, dest, idx, value)
|
||||||
c.freeTemp(dest)
|
c.freeTemp(dest)
|
||||||
c.freeTemp(idx)
|
|
||||||
of nkDerefExpr, nkHiddenDeref:
|
of nkDerefExpr, nkHiddenDeref:
|
||||||
let dest = c.genx(le.sons[0], {gfAddrOf})
|
let dest = c.genx(le.sons[0], {gfAddrOf})
|
||||||
c.gABC(le, opcWrDeref, dest, value)
|
c.gABC(le, opcWrDeref, dest, value)
|
||||||
|
|
@ -1023,7 +1031,7 @@ proc genAsgn(c: PCtx; le, ri: PNode; requiresCopy: bool) =
|
||||||
# XXX field checks here
|
# XXX field checks here
|
||||||
let left = if le.kind == nkDotExpr: le else: le.sons[0]
|
let left = if le.kind == nkDotExpr: le else: le.sons[0]
|
||||||
let dest = c.genx(left.sons[0], {gfAddrOf})
|
let dest = c.genx(left.sons[0], {gfAddrOf})
|
||||||
let idx = c.genx(left.sons[1])
|
let idx = genField(left.sons[1])
|
||||||
let tmp = c.genx(ri)
|
let tmp = c.genx(ri)
|
||||||
c.gABC(left, opcWrObj, dest, idx, tmp)
|
c.gABC(left, opcWrObj, dest, idx, tmp)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
|
|
@ -1108,11 +1116,12 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
||||||
else:
|
else:
|
||||||
c.gABx(n, opcLdGlobal, dest, s.position)
|
c.gABx(n, opcLdGlobal, dest, s.position)
|
||||||
else:
|
else:
|
||||||
if s.kind == skForVar and c.mode == emRepl: c.setSlot s
|
if s.kind == skForVar and c.mode == emRepl: c.setSlot(s)
|
||||||
if s.position > 0 or (s.position == 0 and
|
if s.position > 0 or (s.position == 0 and
|
||||||
s.kind in {skParam,skResult}):
|
s.kind in {skParam,skResult}):
|
||||||
if dest < 0:
|
if dest < 0:
|
||||||
dest = s.position + ord(s.kind == skParam)
|
dest = s.position + ord(s.kind == skParam)
|
||||||
|
internalAssert(c.prc.slots[dest].kind < slotSomeTemp)
|
||||||
else:
|
else:
|
||||||
# we need to generate an assignment:
|
# we need to generate an assignment:
|
||||||
genAsgn(c, dest, n, c.prc.slots[dest].kind >= slotSomeTemp)
|
genAsgn(c, dest, n, c.prc.slots[dest].kind >= slotSomeTemp)
|
||||||
|
|
@ -1120,8 +1129,8 @@ proc genRdVar(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
||||||
# see tests/t99bott for an example that triggers it:
|
# see tests/t99bott for an example that triggers it:
|
||||||
cannotEval(n)
|
cannotEval(n)
|
||||||
|
|
||||||
proc genAccess(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
|
proc genArrAccess2(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
|
||||||
flags: TGenFlags) =
|
flags: TGenFlags) =
|
||||||
let a = c.genx(n.sons[0], flags)
|
let a = c.genx(n.sons[0], flags)
|
||||||
let b = c.genx(n.sons[1], {})
|
let b = c.genx(n.sons[1], {})
|
||||||
if dest < 0: dest = c.getTemp(n.typ)
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
|
|
@ -1136,18 +1145,28 @@ proc genAccess(c: PCtx; n: PNode; dest: var TDest; opc: TOpcode;
|
||||||
c.freeTemp(b)
|
c.freeTemp(b)
|
||||||
|
|
||||||
proc genObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
proc genObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
||||||
genAccess(c, n, dest, opcLdObj, flags)
|
let a = c.genx(n.sons[0], flags)
|
||||||
|
let b = genField(n.sons[1])
|
||||||
|
if dest < 0: dest = c.getTemp(n.typ)
|
||||||
|
if gfAddrOf notin flags and fitsRegister(n.typ):
|
||||||
|
var cc = c.getTemp(n.typ)
|
||||||
|
c.gABC(n, opcLdObj, cc, a, b)
|
||||||
|
c.gABC(n, opcNodeToReg, dest, cc)
|
||||||
|
c.freeTemp(cc)
|
||||||
|
else:
|
||||||
|
c.gABC(n, opcLdObj, dest, a, b)
|
||||||
|
c.freeTemp(a)
|
||||||
|
|
||||||
proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
proc genCheckedObjAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
||||||
# XXX implement field checks!
|
# XXX implement field checks!
|
||||||
genAccess(c, n.sons[0], dest, opcLdObj, flags)
|
genObjAccess(c, n.sons[0], dest, flags)
|
||||||
|
|
||||||
proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
proc genArrAccess(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags) =
|
||||||
if n.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
|
if n.sons[0].typ.skipTypes(abstractVarRange-{tyTypeDesc}).kind in {
|
||||||
tyString, tyCString}:
|
tyString, tyCString}:
|
||||||
genAccess(c, n, dest, opcLdStrIdx, {})
|
genArrAccess2(c, n, dest, opcLdStrIdx, {})
|
||||||
else:
|
else:
|
||||||
genAccess(c, n, dest, opcLdArr, flags)
|
genArrAccess2(c, n, dest, opcLdArr, flags)
|
||||||
|
|
||||||
proc getNullValueAux(obj: PNode, result: PNode) =
|
proc getNullValueAux(obj: PNode, result: PNode) =
|
||||||
case obj.kind
|
case obj.kind
|
||||||
|
|
@ -1304,11 +1323,10 @@ proc genObjConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||||
for i in 1.. <n.len:
|
for i in 1.. <n.len:
|
||||||
let it = n.sons[i]
|
let it = n.sons[i]
|
||||||
if it.kind == nkExprColonExpr and it.sons[0].kind == nkSym:
|
if it.kind == nkExprColonExpr and it.sons[0].kind == nkSym:
|
||||||
let idx = c.genx(it.sons[0])
|
let idx = genField(it.sons[0])
|
||||||
let tmp = c.genx(it.sons[1])
|
let tmp = c.genx(it.sons[1])
|
||||||
c.gABC(it, whichAsgnOpc(it.sons[1], opcWrObj), dest, idx, tmp)
|
c.gABC(it, whichAsgnOpc(it.sons[1], opcWrObj), dest, idx, tmp)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
c.freeTemp(idx)
|
|
||||||
else:
|
else:
|
||||||
internalError(n.info, "invalid object constructor")
|
internalError(n.info, "invalid object constructor")
|
||||||
|
|
||||||
|
|
@ -1319,11 +1337,10 @@ proc genTupleConstr(c: PCtx, n: PNode, dest: var TDest) =
|
||||||
for i in 0.. <n.len:
|
for i in 0.. <n.len:
|
||||||
let it = n.sons[i]
|
let it = n.sons[i]
|
||||||
if it.kind == nkExprColonExpr:
|
if it.kind == nkExprColonExpr:
|
||||||
let idx = c.genx(it.sons[0])
|
let idx = genField(it.sons[0])
|
||||||
let tmp = c.genx(it.sons[1])
|
let tmp = c.genx(it.sons[1])
|
||||||
c.gABC(it, whichAsgnOpc(it.sons[1], opcWrObj), dest, idx, tmp)
|
c.gABC(it, whichAsgnOpc(it.sons[1], opcWrObj), dest, idx, tmp)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
c.freeTemp(idx)
|
|
||||||
else:
|
else:
|
||||||
let tmp = c.genx(it)
|
let tmp = c.genx(it)
|
||||||
c.gABC(it, whichAsgnOpc(it, opcWrObj), dest, i.TRegister, tmp)
|
c.gABC(it, whichAsgnOpc(it, opcWrObj), dest, i.TRegister, tmp)
|
||||||
|
|
@ -1352,12 +1369,6 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||||
else:
|
else:
|
||||||
var lit = genLiteral(c, newIntNode(nkIntLit, s.position))
|
var lit = genLiteral(c, newIntNode(nkIntLit, s.position))
|
||||||
c.gABx(n, opcLdConst, dest, lit)
|
c.gABx(n, opcLdConst, dest, lit)
|
||||||
of skField:
|
|
||||||
internalAssert dest < 0
|
|
||||||
if s.position > high(dest):
|
|
||||||
internalError(n.info,
|
|
||||||
"too large offset! cannot generate code for: " & s.name.s)
|
|
||||||
dest = s.position
|
|
||||||
of skType:
|
of skType:
|
||||||
genTypeLit(c, s.typ, dest)
|
genTypeLit(c, s.typ, dest)
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
17
tests/vm/tquadplus.nim
Normal file
17
tests/vm/tquadplus.nim
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
# bug #1023
|
||||||
|
|
||||||
|
discard """
|
||||||
|
output: "1 == 1"
|
||||||
|
"""
|
||||||
|
|
||||||
|
type Quadruple = tuple[a, b, c, d: int]
|
||||||
|
|
||||||
|
proc `+`(s, t: Quadruple): Quadruple =
|
||||||
|
(a: s.a + t.a, b: s.b + t.b, c: s.c + t.c, d: s.d + t.d)
|
||||||
|
|
||||||
|
const
|
||||||
|
A = (a: 0, b: -1, c: 0, d: 1)
|
||||||
|
B = (a: 0, b: -2, c: 1, d: 0)
|
||||||
|
C = A + B
|
||||||
|
|
||||||
|
echo C.d, " == ", (A+B).d
|
||||||
3
todo.txt
3
todo.txt
|
|
@ -6,7 +6,6 @@ version 0.9.4
|
||||||
- at least try to get the basic type zoo ops right
|
- at least try to get the basic type zoo ops right
|
||||||
- optimize opcAsgnStr
|
- optimize opcAsgnStr
|
||||||
- fix GC issues
|
- fix GC issues
|
||||||
- test and fix showoff
|
|
||||||
|
|
||||||
|
|
||||||
Bugs
|
Bugs
|
||||||
|
|
@ -27,6 +26,8 @@ version 0.9.x
|
||||||
|
|
||||||
- memory manager: add a measure of fragmentation
|
- memory manager: add a measure of fragmentation
|
||||||
- implement 'bits' pragmas
|
- implement 'bits' pragmas
|
||||||
|
- we need a magic thisModule symbol
|
||||||
|
- provide --nilChecks:on|off
|
||||||
- fix closures/lambdalifting
|
- fix closures/lambdalifting
|
||||||
- ensure (ref T)(a, b) works as a type conversion and type constructor
|
- ensure (ref T)(a, b) works as a type conversion and type constructor
|
||||||
- optimize 'genericReset'; 'newException' leads to code bloat
|
- optimize 'genericReset'; 'newException' leads to code bloat
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue