diff options
author | Arne Döring <arne.doering@gmx.net> | 2018-10-28 11:56:30 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-10-28 11:56:30 +0100 |
commit | 2fa13040b99350c96e20550f4768043d708f0742 (patch) | |
tree | 3ab663ad9d4ce2efa993bedc6bacc24974e140fd /compiler | |
parent | f2cd8ed99a7caa00b20bae2443cacf2d97700d75 (diff) | |
parent | 2f781781d0e3a73d90f01b8056b8d50b65536eb9 (diff) | |
download | Nim-2fa13040b99350c96e20550f4768043d708f0742.tar.gz |
Merge pull request #9496 from cooldome/vm_float_casts
VM: add int <-> float casts of the same size
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/vm.nim | 16 | ||||
-rw-r--r-- | compiler/vmdef.nim | 4 | ||||
-rw-r--r-- | compiler/vmgen.nim | 30 |
3 files changed, 45 insertions, 5 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim index 420934470..05ee3b90e 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -488,6 +488,22 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of opcAsgnFloat: decodeB(rkFloat) regs[ra].floatVal = regs[rb].floatVal + of opcAsgnIntFromFloat32: + let rb = instr.regB + ensureKind(rkInt) + regs[ra].intVal = cast[int32](float32(regs[rb].floatVal)) + of opcAsgnIntFromFloat64: + let rb = instr.regB + ensureKind(rkInt) + regs[ra].intVal = cast[int64](regs[rb].floatVal) + of opcAsgnFloat32FromInt: + let rb = instr.regB + ensureKind(rkFloat) + regs[ra].floatVal = cast[float32](int32(regs[rb].intVal)) + of opcAsgnFloat64FromInt: + let rb = instr.regB + ensureKind(rkFloat) + regs[ra].floatVal = cast[float64](int64(regs[rb].intVal)) of opcAsgnComplex: asgnComplex(regs[ra], regs[instr.regB]) of opcAsgnRef: diff --git a/compiler/vmdef.nim b/compiler/vmdef.nim index 875ae5a52..25ace3cdd 100644 --- a/compiler/vmdef.nim +++ b/compiler/vmdef.nim @@ -35,6 +35,10 @@ type opcAsgnStr, opcAsgnFloat, opcAsgnRef, + opcAsgnIntFromFloat32, # int and float must be of the same byte size + opcAsgnIntFromFloat64, # int and float must be of the same byte size + opcAsgnFloat32FromInt, # int and float must be of the same byte size + opcAsgnFloat64FromInt, # int and float must be of the same byte size opcAsgnComplex, opcNodeToReg, diff --git a/compiler/vmgen.nim b/compiler/vmgen.nim index c59581aca..ea0fb35ff 100644 --- a/compiler/vmgen.nim +++ b/compiler/vmgen.nim @@ -769,18 +769,18 @@ proc genCard(c: PCtx; n: PNode; dest: var TDest) = c.gABC(n, opcCard, dest, tmp) c.freeTemp(tmp) -proc genIntCast(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} 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 == getSize(c.config, dst) and src.kind in allowedIntegers and + if src_size == dst_size 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) @@ -809,8 +809,28 @@ proc genIntCast(c: PCtx; n: PNode; dest: var TDest) = 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]) + if dest < 0: dest = c.getTemp(n[0].typ) + if dst.kind == tyFloat32: + c.gABC(n, opcAsgnFloat32FromInt, dest, tmp) + else: + c.gABC(n, opcAsgnFloat64FromInt, dest, tmp) + c.freeTemp(tmp) + + elif src_size == dst_size and src.kind in {tyFloat, tyFloat32, tyFloat64} and + dst.kind in allowedIntegers: + let tmp = c.genx(n[1]) + if dest < 0: dest = c.getTemp(n[0].typ) + if src.kind == tyFloat32: + c.gABC(n, opcAsgnIntFromFloat32, dest, tmp) + else: + c.gABC(n, opcAsgnIntFromFloat64, dest, tmp) + c.freeTemp(tmp) + else: - globalError(c.config, n.info, "VM is only allowed to 'cast' between integers of same size") + globalError(c.config, n.info, "VM is only allowed to 'cast' between integers and/or floats of same size") proc genVoidABC(c: PCtx, n: PNode, dest: TDest, opcode: TOpcode) = unused(c, n, dest) @@ -2008,7 +2028,7 @@ proc gen(c: PCtx; n: PNode; dest: var TDest; flags: TGenFlags = {}) = if allowCast in c.features: genConv(c, n, n.sons[1], dest, opcCast) else: - genIntCast(c, n, dest) + genCastIntFloat(c, n, dest) of nkTypeOfExpr: genTypeLit(c, n.typ, dest) of nkComesFrom: |