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; }