diff options
author | Arne Döring <arne.doering@gmx.net> | 2019-06-10 19:58:11 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2019-06-10 19:58:11 +0200 |
commit | 94177f7357c3f67ea77b8fcf8ba1dbc0eb3f0423 (patch) | |
tree | 69c299def13d7cd03e75f3d279b23a60fd1993be /compiler | |
parent | 7cf9b522b5d2735b5279e9c2bdcade5c177868f8 (diff) | |
download | Nim-94177f7357c3f67ea77b8fcf8ba1dbc0eb3f0423.tar.gz |
VM can now cast integer type arbitrarily. (#11459) [feature]
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/vmgen.nim | 46 |
1 files changed, 15 insertions, 31 deletions
diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index 035ab25cd..de314a552 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -813,44 +813,28 @@ proc genCard(c: PCtx; n: PNode; dest: var TDest) = proc genCastIntFloat(c: PCtx; n: PNode; dest: var TDest) = const allowedIntegers = {tyInt..tyInt64, tyUInt..tyUInt64, tyChar} - var signedIntegers = {tyInt8..tyInt32} - var unsignedIntegers = {tyUInt8..tyUInt32, tyChar} + var signedIntegers = {tyInt..tyInt64} + var unsignedIntegers = {tyUInt..tyUInt64, tyChar} let src = n.sons[1].typ.skipTypes(abstractRange)#.kind let dst = n.sons[0].typ.skipTypes(abstractRange)#.kind let src_size = getSize(c.config, src) let dst_size = getSize(c.config, dst) - if c.config.target.intSize < 8: - signedIntegers.incl(tyInt) - unsignedIntegers.incl(tyUInt) - if src_size == dst_size and src.kind in allowedIntegers and - dst.kind in allowedIntegers: + if 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(c.graph, n.info, 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.gABC(n, opcAsgnInt, dest, tmp) + if dst_size != sizeof(BiggestInt): # don't do anything on biggest int types + if dst.kind in signedIntegers: # we need to do sign extensions + if dst_size <= src_size: + # Sign extension can be omitted when the size increases. + c.gABC(n, opcSignExtend, dest, TRegister(dst_size*8)) + elif dst.kind in unsignedIntegers: + if src.kind in signedIntegers or dst_size < src_size: + # Cast from signed to unsigned always needs narrowing. Cast + # from unsigned to unsigned only needs narrowing when target + # is smaller than source. + c.gABC(n, opcNarrowU, dest, TRegister(dst_size*8)) c.freeTemp(tmp) - c.freeTemp(tmp2) - c.freeTemp(tmp3) elif src_size == dst_size and src.kind in allowedIntegers and dst.kind in {tyFloat, tyFloat32, tyFloat64}: let tmp = c.genx(n[1]) |