dlib/wasm/runtime/core/checkedint.d

84 lines
1.7 KiB
D

module core.checkedint;
version(LDC)
{
import ldc.intrinsics;
}
pragma(inline, true)
uint addu()(uint x, uint y, ref bool overflow)
{
version (LDC)
{
if (!__ctfe)
{
auto res = llvm_uadd_with_overflow(x, y);
overflow |= res.overflow;
return res.result;
}
}
immutable uint r = x + y;
immutable bool o = r < x;
assert(o == (r < y));
if (o)
overflow = true;
return r;
}
uint mulu()(uint x, uint y, ref bool overflow)
{
version (D_InlineAsm_X86) enum useAsm = true;
else version (D_InlineAsm_X86_64) enum useAsm = true;
else enum useAsm = false;
version (LDC)
{
if (!__ctfe)
{
auto res = llvm_umul_with_overflow(x, y);
overflow |= res.overflow;
return res.result;
}
}
else static if (useAsm)
{
if (!__ctfe)
{
uint r;
bool o;
asm pure nothrow @nogc @trusted
{
mov EAX, x;
mul y; // EDX:EAX = EAX * y
mov r, EAX;
setc o;
}
overflow |= o;
return r;
}
}
immutable ulong r = ulong(x) * ulong(y);
if (r >> 32)
overflow = true;
return cast(uint) r;
}
pragma(inline, true)
int adds()(int x, int y, ref bool overflow)
{
version (LDC)
{
if (!__ctfe)
{
auto res = llvm_sadd_with_overflow(x, y);
overflow |= res.overflow;
return res.result;
}
}
long r = cast(long)x + cast(long)y;
if (r < int.min || r > int.max)
overflow = true;
return cast(int)r;
}