Merge pull request #2645 from def-/builtin_overflow
Use builtin overflow functions of Clang and GCC (WIP, RFC)
This commit is contained in:
commit
94b7da4297
1 changed files with 122 additions and 54 deletions
|
|
@ -17,6 +17,60 @@ proc raiseOverflow {.compilerproc, noinline.} =
|
||||||
proc raiseDivByZero {.compilerproc, noinline.} =
|
proc raiseDivByZero {.compilerproc, noinline.} =
|
||||||
sysFatal(DivByZeroError, "division by zero")
|
sysFatal(DivByZeroError, "division by zero")
|
||||||
|
|
||||||
|
when defined(builtinOverflow):
|
||||||
|
# Builtin compiler functions for improved performance
|
||||||
|
when sizeof(clong) == 8:
|
||||||
|
proc addInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
|
||||||
|
importc: "__builtin_saddl_overflow", nodecl, nosideeffect.}
|
||||||
|
|
||||||
|
proc subInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
|
||||||
|
importc: "__builtin_ssubl_overflow", nodecl, nosideeffect.}
|
||||||
|
|
||||||
|
proc mulInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
|
||||||
|
importc: "__builtin_smull_overflow", nodecl, nosideeffect.}
|
||||||
|
|
||||||
|
elif sizeof(clonglong) == 8:
|
||||||
|
proc addInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
|
||||||
|
importc: "__builtin_saddll_overflow", nodecl, nosideeffect.}
|
||||||
|
|
||||||
|
proc subInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
|
||||||
|
importc: "__builtin_ssubll_overflow", nodecl, nosideeffect.}
|
||||||
|
|
||||||
|
proc mulInt64Overflow[T: int64|int](a, b: T, c: var T): bool {.
|
||||||
|
importc: "__builtin_smulll_overflow", nodecl, nosideeffect.}
|
||||||
|
|
||||||
|
when sizeof(int) == 8:
|
||||||
|
proc addIntOverflow(a, b: int, c: var int): bool {.inline.} =
|
||||||
|
addInt64Overflow(a, b, c)
|
||||||
|
|
||||||
|
proc subIntOverflow(a, b: int, c: var int): bool {.inline.} =
|
||||||
|
subInt64Overflow(a, b, c)
|
||||||
|
|
||||||
|
proc mulIntOverflow(a, b: int, c: var int): bool {.inline.} =
|
||||||
|
mulInt64Overflow(a, b, c)
|
||||||
|
|
||||||
|
elif sizeof(int) == 4 and sizeof(cint) == 4:
|
||||||
|
proc addIntOverflow(a, b: int, c: var int): bool {.
|
||||||
|
importc: "__builtin_sadd_overflow", nodecl, nosideeffect.}
|
||||||
|
|
||||||
|
proc subIntOverflow(a, b: int, c: var int): bool {.
|
||||||
|
importc: "__builtin_ssub_overflow", nodecl, nosideeffect.}
|
||||||
|
|
||||||
|
proc mulIntOverflow(a, b: int, c: var int): bool {.
|
||||||
|
importc: "__builtin_smul_overflow", nodecl, nosideeffect.}
|
||||||
|
|
||||||
|
proc addInt64(a, b: int64): int64 {.compilerProc, inline.} =
|
||||||
|
if addInt64Overflow(a, b, result):
|
||||||
|
raiseOverflow()
|
||||||
|
|
||||||
|
proc subInt64(a, b: int64): int64 {.compilerProc, inline.} =
|
||||||
|
if subInt64Overflow(a, b, result):
|
||||||
|
raiseOverflow()
|
||||||
|
|
||||||
|
proc mulInt64(a, b: int64): int64 {.compilerproc, inline.} =
|
||||||
|
if mulInt64Overflow(a, b, result):
|
||||||
|
raiseOverflow()
|
||||||
|
else:
|
||||||
proc addInt64(a, b: int64): int64 {.compilerProc, inline.} =
|
proc addInt64(a, b: int64): int64 {.compilerProc, inline.} =
|
||||||
result = a +% b
|
result = a +% b
|
||||||
if (result xor a) >= int64(0) or (result xor b) >= int64(0):
|
if (result xor a) >= int64(0) or (result xor b) >= int64(0):
|
||||||
|
|
@ -29,28 +83,6 @@ proc subInt64(a, b: int64): int64 {.compilerProc, inline.} =
|
||||||
return result
|
return result
|
||||||
raiseOverflow()
|
raiseOverflow()
|
||||||
|
|
||||||
proc negInt64(a: int64): int64 {.compilerProc, inline.} =
|
|
||||||
if a != low(int64): return -a
|
|
||||||
raiseOverflow()
|
|
||||||
|
|
||||||
proc absInt64(a: int64): int64 {.compilerProc, inline.} =
|
|
||||||
if a != low(int64):
|
|
||||||
if a >= 0: return a
|
|
||||||
else: return -a
|
|
||||||
raiseOverflow()
|
|
||||||
|
|
||||||
proc divInt64(a, b: int64): int64 {.compilerProc, inline.} =
|
|
||||||
if b == int64(0):
|
|
||||||
raiseDivByZero()
|
|
||||||
if a == low(int64) and b == int64(-1):
|
|
||||||
raiseOverflow()
|
|
||||||
return a div b
|
|
||||||
|
|
||||||
proc modInt64(a, b: int64): int64 {.compilerProc, inline.} =
|
|
||||||
if b == int64(0):
|
|
||||||
raiseDivByZero()
|
|
||||||
return a mod b
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# This code has been inspired by Python's source code.
|
# This code has been inspired by Python's source code.
|
||||||
# The native int product x*y is either exactly right or *way* off, being
|
# The native int product x*y is either exactly right or *way* off, being
|
||||||
|
|
@ -94,6 +126,27 @@ proc mulInt64(a, b: int64): int64 {.compilerproc.} =
|
||||||
return result
|
return result
|
||||||
raiseOverflow()
|
raiseOverflow()
|
||||||
|
|
||||||
|
proc negInt64(a: int64): int64 {.compilerProc, inline.} =
|
||||||
|
if a != low(int64): return -a
|
||||||
|
raiseOverflow()
|
||||||
|
|
||||||
|
proc absInt64(a: int64): int64 {.compilerProc, inline.} =
|
||||||
|
if a != low(int64):
|
||||||
|
if a >= 0: return a
|
||||||
|
else: return -a
|
||||||
|
raiseOverflow()
|
||||||
|
|
||||||
|
proc divInt64(a, b: int64): int64 {.compilerProc, inline.} =
|
||||||
|
if b == int64(0):
|
||||||
|
raiseDivByZero()
|
||||||
|
if a == low(int64) and b == int64(-1):
|
||||||
|
raiseOverflow()
|
||||||
|
return a div b
|
||||||
|
|
||||||
|
proc modInt64(a, b: int64): int64 {.compilerProc, inline.} =
|
||||||
|
if b == int64(0):
|
||||||
|
raiseDivByZero()
|
||||||
|
return a mod b
|
||||||
|
|
||||||
proc absInt(a: int): int {.compilerProc, inline.} =
|
proc absInt(a: int): int {.compilerProc, inline.} =
|
||||||
if a != low(int):
|
if a != low(int):
|
||||||
|
|
@ -246,6 +299,21 @@ elif false: # asmVersion and (defined(gcc) or defined(llvm_gcc)):
|
||||||
:"%edx"
|
:"%edx"
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
when not declared(addInt) and defined(builtinOverflow):
|
||||||
|
proc addInt(a, b: int): int {.compilerProc, inline.} =
|
||||||
|
if addIntOverflow(a, b, result):
|
||||||
|
raiseOverflow()
|
||||||
|
|
||||||
|
when not declared(subInt) and defined(builtinOverflow):
|
||||||
|
proc subInt(a, b: int): int {.compilerProc, inline.} =
|
||||||
|
if subIntOverflow(a, b, result):
|
||||||
|
raiseOverflow()
|
||||||
|
|
||||||
|
when not declared(mulInt) and defined(builtinOverflow):
|
||||||
|
proc mulInt(a, b: int): int {.compilerProc, inline.} =
|
||||||
|
if mulIntOverflow(a, b, result):
|
||||||
|
raiseOverflow()
|
||||||
|
|
||||||
# Platform independent versions of the above (slower!)
|
# Platform independent versions of the above (slower!)
|
||||||
when not declared(addInt):
|
when not declared(addInt):
|
||||||
proc addInt(a, b: int): int {.compilerProc, inline.} =
|
proc addInt(a, b: int): int {.compilerProc, inline.} =
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue