diff options
author | LemonBoy <LemonBoy@users.noreply.github.com> | 2018-08-31 13:45:42 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2018-08-31 13:45:42 +0200 |
commit | 2c8361bd39f98c869df7b23ee682c25a9929f64f (patch) | |
tree | 388cb124560c2af2e2b81e877a590f48cf2ee2f9 /compiler | |
parent | b74faf354e3d998156ab73bbc7367e359c16de41 (diff) | |
download | Nim-2c8361bd39f98c869df7b23ee682c25a9929f64f.tar.gz |
Constant folding for integer casts (#8095)
Diffstat (limited to 'compiler')
-rw-r--r-- | compiler/semfold.nim | 32 |
1 files changed, 25 insertions, 7 deletions
diff --git a/compiler/semfold.nim b/compiler/semfold.nim index 444940144..fe1871881 100644 --- a/compiler/semfold.nim +++ b/compiler/semfold.nim @@ -450,21 +450,38 @@ proc rangeCheck(n: PNode, value: BiggestInt; g: ModuleGraph) = localError(g.config, n.info, "cannot convert " & $value & " to " & typeToString(n.typ)) -proc foldConv*(n, a: PNode; g: ModuleGraph; check = false): PNode = +proc foldConv(n, a: PNode; g: ModuleGraph; check = false): PNode = + let dstTyp = skipTypes(n.typ, abstractRange) + let srcTyp = skipTypes(a.typ, abstractRange) + # XXX range checks? - case skipTypes(n.typ, abstractRange).kind - of tyInt..tyInt64, tyUInt..tyUInt64: - case skipTypes(a.typ, abstractRange).kind + case dstTyp.kind + of tyInt..tyInt64, tyUint..tyUInt64: + case srcTyp.kind of tyFloat..tyFloat64: result = newIntNodeT(int(getFloat(a)), n, g) - of tyChar: result = newIntNodeT(getOrdValue(a), n, g) + of tyChar: + result = newIntNodeT(getOrdValue(a), n, g) + of tyUInt8..tyUInt32, tyInt8..tyInt32: + let fromSigned = srcTyp.kind in tyInt..tyInt64 + let toSigned = dstTyp.kind in tyInt..tyInt64 + + let mask = lastOrd(g.config, dstTyp, fixedUnsigned=true) + + var val = + if toSigned: + a.getOrdValue mod mask + else: + a.getOrdValue and mask + + result = newIntNodeT(val, n, g) else: result = a result.typ = n.typ if check and result.kind in {nkCharLit..nkUInt64Lit}: rangeCheck(n, result.intVal, g) of tyFloat..tyFloat64: - case skipTypes(a.typ, abstractRange).kind + case srcTyp.kind of tyInt..tyInt64, tyEnum, tyBool, tyChar: result = newFloatNodeT(toBiggestFloat(getOrdValue(a)), n, g) else: @@ -742,7 +759,8 @@ proc getConstExpr(m: PSym, n: PNode; g: ModuleGraph): PNode = of nkHiddenStdConv, nkHiddenSubConv, nkConv: var a = getConstExpr(m, n.sons[1], g) if a == nil: return - result = foldConv(n, a, g, check=n.kind == nkHiddenStdConv) + # XXX: we should enable `check` for other conversion types too + result = foldConv(n, a, g, check=n.kind == nkHiddenSubConv) of nkCast: var a = getConstExpr(m, n.sons[1], g) if a == nil: return |