1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 04:22:20 +02:00

Improvements to overflow arithmetic

This commit is contained in:
Brian Fiete 2022-01-11 10:36:22 -05:00
parent eb375362a1
commit bf97431cdb
12 changed files with 91 additions and 45 deletions

View file

@ -73,7 +73,7 @@ namespace System
} }
while (valLeft < 0) while (valLeft < 0)
{ {
strChars[char8Idx] = (char8)('0' - (valLeft % 10)); strChars[char8Idx] = (char8)('0' &- (valLeft % 10));
valLeft /= 10; valLeft /= 10;
char8Idx--; char8Idx--;
} }

View file

@ -91,7 +91,7 @@ namespace System
} }
while ((valLeft < 0) || (minNumeralsLeft > 0)) while ((valLeft < 0) || (minNumeralsLeft > 0))
{ {
strChars[char8Idx] = (char8)('0' - (valLeft % 10)); strChars[char8Idx] = (char8)('0' &- (valLeft % 10));
valLeft /= 10; valLeft /= 10;
char8Idx--; char8Idx--;
minNumeralsLeft--; minNumeralsLeft--;

View file

@ -80,7 +80,7 @@ namespace System
{ {
for (int32 i = 1; i < 56; i++) for (int32 i = 1; i < 56; i++)
{ {
SeedArray[i] -= SeedArray[1 + (i + 30) % 55]; SeedArray[i] &-= SeedArray[1 + (i + 30) % 55];
if (SeedArray[i] < 0) SeedArray[i] += MBIG; if (SeedArray[i] < 0) SeedArray[i] += MBIG;
} }
} }

View file

@ -129,27 +129,27 @@ namespace System.Security.Cryptography
// The MD5 transformation for all four rounds. // The MD5 transformation for all four rounds.
mixin STEP_F(var a, var b, var c, var d, var x, var t, var s) mixin STEP_F(var a, var b, var c, var d, var x, var t, var s)
{ {
a += F!(b, c, d) + x + t; a &+= F!(b, c, d) &+ x &+ t;
a = ((a << s) | ((a & 0xffffffff) >> (32 - s))); a = ((a << s) | ((a & 0xffffffff) >> (32 - s)));
a += b; a &+= b;
} }
mixin STEP_G(var a, var b, var c, var d, var x, var t, var s) mixin STEP_G(var a, var b, var c, var d, var x, var t, var s)
{ {
a += G!(b, c, d) + x + t; a &+= G!(b, c, d) &+ x &+ t;
a = ((a << s) | ((a & 0xffffffff) >> (32 - s))); a = ((a << s) | ((a & 0xffffffff) >> (32 - s)));
a += b; a &+= b;
} }
mixin STEP_H(var a, var b, var c, var d, var x, var t, var s) mixin STEP_H(var a, var b, var c, var d, var x, var t, var s)
{ {
a += H!(b, c, d) + x + t; a &+= H!(b, c, d) &+ x &+ t;
a = ((a << s) | ((a & 0xffffffff) >> (32 - s))); a = ((a << s) | ((a & 0xffffffff) >> (32 - s)));
a += b; a &+= b;
} }
mixin STEP_I(var a, var b, var c, var d, var x, var t, var s) mixin STEP_I(var a, var b, var c, var d, var x, var t, var s)
{ {
a += I!(b, c, d) + x + t; a &+= I!(b, c, d) &+ x &+ t;
a = ((a << s) | ((a & 0xffffffff) >> (32 - s))); a = ((a << s) | ((a & 0xffffffff) >> (32 - s)));
a += b; a &+= b;
} }
// SET reads 4 input bytes in little-endian byte order and stores them // SET reads 4 input bytes in little-endian byte order and stores them
@ -249,10 +249,10 @@ namespace System.Security.Cryptography
STEP_I!(c, d, a, b, GET!(2), 0x2ad7d2bb, 15); STEP_I!(c, d, a, b, GET!(2), 0x2ad7d2bb, 15);
STEP_I!(b, c, d, a, GET!(9), 0xeb86d391, 21); STEP_I!(b, c, d, a, GET!(9), 0xeb86d391, 21);
a += saved_a; a &+= saved_a;
b += saved_b; b &+= saved_b;
c += saved_c; c &+= saved_c;
d += saved_d; d &+= saved_d;
ptr += 64; ptr += 64;
} }

View file

@ -142,7 +142,7 @@ namespace System.Security.Cryptography
for (i = 0, j = 0; i < 16; ++i, j += 4) for (i = 0, j = 0; i < 16; ++i, j += 4)
m[i] = ((uint32)mData[j] << 24) | ((uint32)mData[j + 1] << 16) | ((uint32)mData[j + 2] << 8) | ((uint32)mData[j + 3]); m[i] = ((uint32)mData[j] << 24) | ((uint32)mData[j + 1] << 16) | ((uint32)mData[j + 2] << 8) | ((uint32)mData[j + 3]);
for ( ; i < 64; ++i) for ( ; i < 64; ++i)
m[i] = SIG1!(m[i - 2]) + m[i - 7] + SIG0!(m[i - 15]) + m[i - 16]; m[i] = SIG1!(m[i - 2]) &+ m[i - 7] &+ SIG0!(m[i - 15]) &+ m[i - 16];
a = mState[0]; a = mState[0];
b = mState[1]; b = mState[1];
@ -155,26 +155,26 @@ namespace System.Security.Cryptography
for (i = 0; i < 64; ++i) for (i = 0; i < 64; ++i)
{ {
t1 = h + EP1!(e) + CH!(e,f,g) + k[i] + m[i]; t1 = h &+ EP1!(e) &+ CH!(e,f,g) &+ k[i] &+ m[i];
t2 = EP0!(a) + MAJ!(a,b,c); t2 = EP0!(a) &+ MAJ!(a,b,c);
h = g; h = g;
g = f; g = f;
f = e; f = e;
e = d + t1; e = d &+ t1;
d = c; d = c;
c = b; c = b;
b = a; b = a;
a = t1 + t2; a = t1 &+ t2;
} }
mState[0] += a; mState[0] &+= a;
mState[1] += b; mState[1] &+= b;
mState[2] += c; mState[2] &+= c;
mState[3] += d; mState[3] &+= d;
mState[4] += e; mState[4] &+= e;
mState[5] += f; mState[5] &+= f;
mState[6] += g; mState[6] &+= g;
mState[7] += h; mState[7] &+= h;
} }
public void Update(Span<uint8> data) public void Update(Span<uint8> data)

View file

@ -397,14 +397,14 @@ namespace System
let intSize = sizeof(int); let intSize = sizeof(int);
while (charsLeft >= intSize) while (charsLeft >= intSize)
{ {
hash = (hash ^ *((int*)curPtr)) + (hash * 16777619); hash = (hash ^ *((int*)curPtr)) &+ (hash &* 16777619);
charsLeft -= intSize; charsLeft -= intSize;
curPtr += intSize; curPtr += intSize;
} }
while (charsLeft > 1) while (charsLeft > 1)
{ {
hash = ((hash ^ (int)*curPtr) << 5) - hash; hash = ((hash ^ (int)*curPtr) << 5) &- hash;
charsLeft--; charsLeft--;
curPtr++; curPtr++;
} }
@ -1774,8 +1774,8 @@ namespace System
//Contract.Assert((char8A | char8B) <= 0x7F, "strings have to be ASCII"); //Contract.Assert((char8A | char8B) <= 0x7F, "strings have to be ASCII");
// uppercase both chars - notice that we need just one compare per char // uppercase both chars - notice that we need just one compare per char
if ((uint32)(charA - 'a') <= (uint32)('z' - 'a')) charA -= 0x20; if ((uint32)(charA &- 'a') <= (uint32)('z' - 'a')) charA -= 0x20;
if ((uint32)(charB - 'a') <= (uint32)('z' - 'a')) charB -= 0x20; if ((uint32)(charB &- 'a') <= (uint32)('z' - 'a')) charB -= 0x20;
//Return the (case-insensitive) difference between them. //Return the (case-insensitive) difference between them.
if (charA != charB) if (charA != charB)
@ -1807,8 +1807,8 @@ namespace System
//Contract.Assert((char8A | char8B) <= 0x7F, "strings have to be ASCII"); //Contract.Assert((char8A | char8B) <= 0x7F, "strings have to be ASCII");
// uppercase both chars - notice that we need just one compare per char // uppercase both chars - notice that we need just one compare per char
if ((uint32)(charA - 'a') <= (uint32)('z' - 'a')) charA -= 0x20; if ((uint32)(charA &- 'a') <= (uint32)('z' - 'a')) charA -= 0x20;
if ((uint32)(charB - 'a') <= (uint32)('z' - 'a')) charB -= 0x20; if ((uint32)(charB &- 'a') <= (uint32)('z' - 'a')) charB -= 0x20;
//Return the (case-insensitive) difference between them. //Return the (case-insensitive) difference between them.
if (charA != charB) if (charA != charB)
@ -1835,8 +1835,8 @@ namespace System
//Contract.Assert((char8A | char8B) <= 0x7F, "strings have to be ASCII"); //Contract.Assert((char8A | char8B) <= 0x7F, "strings have to be ASCII");
// uppercase both chars - notice that we need just one compare per char // uppercase both chars - notice that we need just one compare per char
if ((uint32)(charA - 'a') <= (uint32)('z' - 'a')) charA -= 0x20; if ((uint32)(charA &- 'a') <= (uint32)('z' - 'a')) charA -= 0x20;
if ((uint32)(charB - 'a') <= (uint32)('z' - 'a')) charB -= 0x20; if ((uint32)(charB &- 'a') <= (uint32)('z' - 'a')) charB -= 0x20;
//Return the (case-insensitive) difference between them. //Return the (case-insensitive) difference between them.
if (charA != charB) if (charA != charB)

View file

@ -9226,7 +9226,7 @@ bool BeMCContext::DoLegalization()
else else
{ {
bool addCanBeLEA = bool addCanBeLEA =
((inst->mKind == BeMCInstKind_Sub) || (inst->mKind == BeMCInstKind_Add)) && ((inst->mKind == BeMCInstKind_Sub) || (inst->mKind == BeMCInstKind_Add)) && (!inst->mDisableShortForm) &&
(arg0Type->mSize >= 2) && // Int8s don't have an LEA (arg0Type->mSize >= 2) && // Int8s don't have an LEA
(GetFixedOperand(inst->mResult).IsNativeReg()) && (arg0.IsNativeReg()) && (arg1.IsImmediateInt()); (GetFixedOperand(inst->mResult).IsNativeReg()) && (arg0.IsNativeReg()) && (arg1.IsImmediateInt());
@ -10209,7 +10209,7 @@ bool BeMCContext::DoLegalization()
handled = true; handled = true;
} }
if (handled) if (!handled)
{ {
if (inst->mResult) if (inst->mResult)
{ {
@ -14338,6 +14338,7 @@ void BeMCContext::DoCodeEmission()
{ {
if ((inst->mResult) && (inst->mResult != inst->mArg0)) if ((inst->mResult) && (inst->mResult != inst->mArg0))
{ {
BF_ASSERT(!inst->mDisableShortForm);
BF_ASSERT(inst->mResult.IsNativeReg()); BF_ASSERT(inst->mResult.IsNativeReg());
BF_ASSERT(inst->mArg0.IsNativeReg()); BF_ASSERT(inst->mArg0.IsNativeReg());
BF_ASSERT(inst->mArg1.IsImmediate()); BF_ASSERT(inst->mArg1.IsImmediate());
@ -14538,9 +14539,9 @@ void BeMCContext::DoCodeEmission()
if (result) if (result)
{ {
BF_ASSERT(inst->mArg1.IsImmediate()); BF_ASSERT(inst->mArg1.IsImmediate());
if ((inst->mArg0.IsNativeReg()) && if ((inst->mArg0.IsNativeReg()) && (!inst->mDisableShortForm) &&
((inst->mArg1.mImmediate == 2) || (inst->mArg1.mImmediate == 4) || (inst->mArg1.mImmediate == 8))) ((inst->mArg1.mImmediate == 2) || (inst->mArg1.mImmediate == 4) || (inst->mArg1.mImmediate == 8)))
{ {
// LEA form // LEA form
auto resultType = GetType(inst->mArg0); auto resultType = GetType(inst->mArg0);
if (resultType->mTypeCode != BeTypeCode_Int8) if (resultType->mTypeCode != BeTypeCode_Int8)
@ -16030,6 +16031,7 @@ BeMCOperand BeMCContext::AllocBinaryOp(BeMCInstKind instKind, const BeMCOperand&
if (overflowCheckKind != BeMCOverflowCheckKind_None) if (overflowCheckKind != BeMCOverflowCheckKind_None)
{ {
mcInst->mDisableShortForm = true;
AllocInst(BeMCInstKind_CondBr, BeMCOperand::FromImmediate(1), BeMCOperand::FromCmpKind((overflowCheckKind == BeMCOverflowCheckKind_B) ? BeCmpKind_NB : BeCmpKind_NO)); AllocInst(BeMCInstKind_CondBr, BeMCOperand::FromImmediate(1), BeMCOperand::FromCmpKind((overflowCheckKind == BeMCOverflowCheckKind_B) ? BeCmpKind_NB : BeCmpKind_NO));
AllocInst(BeMCInstKind_DbgBreak); AllocInst(BeMCInstKind_DbgBreak);
} }

View file

@ -564,6 +564,7 @@ class BeMCInst
{ {
public: public:
BeMCInstKind mKind; BeMCInstKind mKind;
bool mDisableShortForm;
BeMCOperand mResult; BeMCOperand mResult;
BeMCOperand mArg0; BeMCOperand mArg0;

View file

@ -1513,6 +1513,12 @@ const char* Beefy::BfTokenToString(BfToken token)
return "&+"; return "&+";
case BfToken_AndStar: case BfToken_AndStar:
return "&*"; return "&*";
case BfToken_AndMinusEquals:
return "&-=";
case BfToken_AndPlusEquals:
return "&+=";
case BfToken_AndStarEquals:
return "&*=";
case BfToken_OrEquals: case BfToken_OrEquals:
return "|="; return "|=";
case BfToken_XorEquals: case BfToken_XorEquals:
@ -1620,6 +1626,12 @@ BfBinaryOp Beefy::BfAssignOpToBinaryOp(BfAssignmentOp assignmentOp)
return BfBinaryOp_Multiply; return BfBinaryOp_Multiply;
case BfAssignmentOp_Divide: case BfAssignmentOp_Divide:
return BfBinaryOp_Divide; return BfBinaryOp_Divide;
case BfAssignmentOp_OverflowAdd:
return BfBinaryOp_OverflowAdd;
case BfAssignmentOp_OverflowSubtract:
return BfBinaryOp_OverflowSubtract;
case BfAssignmentOp_OverflowMultiply:
return BfBinaryOp_OverflowMultiply;
case BfAssignmentOp_Modulus: case BfAssignmentOp_Modulus:
return BfBinaryOp_Modulus; return BfBinaryOp_Modulus;
case BfAssignmentOp_ShiftLeft: case BfAssignmentOp_ShiftLeft:
@ -1898,7 +1910,13 @@ BfAssignmentOp Beefy::BfTokenToAssignmentOp(BfToken token)
case BfToken_MinusEquals: case BfToken_MinusEquals:
return BfAssignmentOp_Subtract; return BfAssignmentOp_Subtract;
case BfToken_MultiplyEquals: case BfToken_MultiplyEquals:
return BfAssignmentOp_Multiply; return BfAssignmentOp_Multiply;
case BfToken_AndPlusEquals:
return BfAssignmentOp_OverflowAdd;
case BfToken_AndMinusEquals:
return BfAssignmentOp_OverflowSubtract;
case BfToken_AndStarEquals:
return BfAssignmentOp_OverflowMultiply;
case BfToken_DivideEquals: case BfToken_DivideEquals:
return BfAssignmentOp_Divide; return BfAssignmentOp_Divide;
case BfToken_ModulusEquals: case BfToken_ModulusEquals:

View file

@ -205,7 +205,6 @@ enum BfToken : uint8
BfToken_PlusEquals, BfToken_PlusEquals,
BfToken_MinusEquals, BfToken_MinusEquals,
BfToken_MultiplyEquals, BfToken_MultiplyEquals,
BfToken_DivideEquals, BfToken_DivideEquals,
BfToken_ModulusEquals, BfToken_ModulusEquals,
BfToken_ShiftLeftEquals, BfToken_ShiftLeftEquals,
@ -214,6 +213,9 @@ enum BfToken : uint8
BfToken_AndMinus, BfToken_AndMinus,
BfToken_AndPlus, BfToken_AndPlus,
BfToken_AndStar, BfToken_AndStar,
BfToken_AndMinusEquals,
BfToken_AndPlusEquals,
BfToken_AndStarEquals,
BfToken_OrEquals, BfToken_OrEquals,
BfToken_XorEquals, BfToken_XorEquals,
BfToken_NullCoalsceEquals, BfToken_NullCoalsceEquals,
@ -1843,6 +1845,9 @@ enum BfAssignmentOp
BfAssignmentOp_Add, BfAssignmentOp_Add,
BfAssignmentOp_Subtract, BfAssignmentOp_Subtract,
BfAssignmentOp_Multiply, BfAssignmentOp_Multiply,
BfAssignmentOp_OverflowAdd,
BfAssignmentOp_OverflowSubtract,
BfAssignmentOp_OverflowMultiply,
BfAssignmentOp_Divide, BfAssignmentOp_Divide,
BfAssignmentOp_Modulus, BfAssignmentOp_Modulus,
BfAssignmentOp_ShiftLeft, BfAssignmentOp_ShiftLeft,

View file

@ -22667,6 +22667,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfType* resultType, BfIRValue convL
auto _GetOverflowKind = [&](bool wantOverflow) auto _GetOverflowKind = [&](bool wantOverflow)
{ {
if (resultType->IsFloat())
return BfOverflowCheckKind_None;
if (!wantOverflow) if (!wantOverflow)
return BfOverflowCheckKind_None; return BfOverflowCheckKind_None;
if (mModule->GetDefaultCheckedKind() != BfCheckedKind_Checked) if (mModule->GetDefaultCheckedKind() != BfCheckedKind_Checked)

View file

@ -1559,17 +1559,35 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
} }
else if (mSrc[mSrcIdx] == '+') else if (mSrc[mSrcIdx] == '+')
{ {
mToken = BfToken_AndPlus; if (mSrc[mSrcIdx + 1] == '=')
{
mToken = BfToken_AndPlusEquals;
++mSrcIdx;
}
else
mToken = BfToken_AndPlus;
mTokenEnd = ++mSrcIdx; mTokenEnd = ++mSrcIdx;
} }
else if (mSrc[mSrcIdx] == '-') else if (mSrc[mSrcIdx] == '-')
{ {
mToken = BfToken_AndMinus; if (mSrc[mSrcIdx + 1] == '=')
{
mToken = BfToken_AndMinusEquals;
++mSrcIdx;
}
else
mToken = BfToken_AndMinus;
mTokenEnd = ++mSrcIdx; mTokenEnd = ++mSrcIdx;
} }
else if (mSrc[mSrcIdx] == '*') else if (mSrc[mSrcIdx] == '*')
{ {
mToken = BfToken_AndStar; if (mSrc[mSrcIdx + 1] == '=')
{
mToken = BfToken_AndStarEquals;
++mSrcIdx;
}
else
mToken = BfToken_AndStar;
mTokenEnd = ++mSrcIdx; mTokenEnd = ++mSrcIdx;
} }
else else