add support cast[integer] in VM
This commit is contained in:
parent
3073f08e48
commit
41472f0e28
1 changed files with 45 additions and 2 deletions
|
|
@ -30,7 +30,7 @@
|
||||||
import
|
import
|
||||||
strutils, ast, astalgo, types, msgs, renderer, vmdef,
|
strutils, ast, astalgo, types, msgs, renderer, vmdef,
|
||||||
trees, intsets, rodread, magicsys, options, lowerings
|
trees, intsets, rodread, magicsys, options, lowerings
|
||||||
|
import platform
|
||||||
from os import splitFile
|
from os import splitFile
|
||||||
|
|
||||||
when hasFFI:
|
when hasFFI:
|
||||||
|
|
@ -761,6 +761,49 @@ proc genCard(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
c.gABC(n, opcCard, dest, tmp)
|
c.gABC(n, opcCard, dest, tmp)
|
||||||
c.freeTemp(tmp)
|
c.freeTemp(tmp)
|
||||||
|
|
||||||
|
proc genIntCast(c: PCtx; n: PNode; dest: var TDest) =
|
||||||
|
const allowedIntegers = {tyInt..tyInt64, tyUInt..tyUInt64, tyChar}
|
||||||
|
var signedIntegers = {tyInt8..tyInt32}
|
||||||
|
var unsignedIntegers = {tyUInt8..tyUInt32, tyChar}
|
||||||
|
let src = n.sons[1].typ.skipTypes(abstractRange)#.kind
|
||||||
|
let dst = n.sons[0].typ.skipTypes(abstractRange)#.kind
|
||||||
|
let src_size = src.getSize
|
||||||
|
|
||||||
|
if platform.intSize < 8:
|
||||||
|
signedIntegers.incl(tyInt)
|
||||||
|
unsignedIntegers.incl(tyUInt)
|
||||||
|
if src_size == dst.getSize and src.kind in allowedIntegers and
|
||||||
|
dst.kind in allowedIntegers:
|
||||||
|
let tmp = c.genx(n.sons[1])
|
||||||
|
var tmp2 = c.getTemp(n.sons[1].typ)
|
||||||
|
let tmp3 = c.getTemp(n.sons[1].typ)
|
||||||
|
if dest < 0: dest = c.getTemp(n[0].typ)
|
||||||
|
proc mkIntLit(ival: int): int =
|
||||||
|
result = genLiteral(c, newIntTypeNode(nkIntLit, ival, getSysType(tyInt)))
|
||||||
|
if src.kind in unsignedIntegers and dst.kind in signedIntegers:
|
||||||
|
# cast unsigned to signed integer of same size
|
||||||
|
# signedVal = (unsignedVal xor offset) -% offset
|
||||||
|
let offset = 1 shl (src_size * 8 - 1)
|
||||||
|
c.gABx(n, opcLdConst, tmp2, mkIntLit(offset))
|
||||||
|
c.gABC(n, opcBitxorInt, tmp3, tmp, tmp2)
|
||||||
|
c.gABC(n, opcSubInt, dest, tmp3, tmp2)
|
||||||
|
elif src.kind in signedIntegers and dst.kind in unsignedIntegers:
|
||||||
|
# cast signed to unsigned integer of same size
|
||||||
|
# unsignedVal = (offset +% signedVal +% 1) and offset
|
||||||
|
let offset = (1 shl (src_size * 8)) - 1
|
||||||
|
c.gABx(n, opcLdConst, tmp2, mkIntLit(offset))
|
||||||
|
c.gABx(n, opcLdConst, dest, mkIntLit(offset+1))
|
||||||
|
c.gABC(n, opcAddu, tmp3, tmp, dest)
|
||||||
|
c.gABC(n, opcNarrowU, tmp3, TRegister(src_size*8))
|
||||||
|
c.gABC(n, opcBitandInt, dest, tmp3, tmp2)
|
||||||
|
else:
|
||||||
|
c.gABC(n, opcAsgnInt, dest, tmp)
|
||||||
|
c.freeTemp(tmp)
|
||||||
|
c.freeTemp(tmp2)
|
||||||
|
c.freeTemp(tmp3)
|
||||||
|
else:
|
||||||
|
globalError(n.info, errGenerated, "VM is only allowed to 'cast' between integers of same size")
|
||||||
|
|
||||||
proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
|
||||||
case m
|
case m
|
||||||
of mAnd: c.genAndOr(n, opcFJmp, dest)
|
of mAnd: c.genAndOr(n, opcFJmp, dest)
|
||||||
|
|
@ -1844,7 +1887,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) =
|
||||||
if allowCast in c.features:
|
if allowCast in c.features:
|
||||||
genConv(c, n, n.sons[1], dest, opcCast)
|
genConv(c, n, n.sons[1], dest, opcCast)
|
||||||
else:
|
else:
|
||||||
globalError(n.info, errGenerated, "VM is not allowed to 'cast'")
|
genIntCast(c, n, dest)
|
||||||
of nkTypeOfExpr:
|
of nkTypeOfExpr:
|
||||||
genTypeLit(c, n.typ, dest)
|
genTypeLit(c, n.typ, dest)
|
||||||
of nkComesFrom:
|
of nkComesFrom:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue