1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28:20 +02:00

Added overflow operators &+, &-, &*

This commit is contained in:
Brian Fiete 2021-07-15 06:01:17 -07:00
parent 8d2b222c1a
commit d475d3641f
7 changed files with 151 additions and 25 deletions

View file

@ -1500,6 +1500,12 @@ const char* Beefy::BfTokenToString(BfToken token)
return ">>=";
case BfToken_AndEquals:
return "&=";
case BfToken_AndMinus:
return "&-";
case BfToken_AndPlus:
return "&+";
case BfToken_AndStar:
return "&*";
case BfToken_OrEquals:
return "|=";
case BfToken_XorEquals:
@ -1630,11 +1636,14 @@ int Beefy::BfGetBinaryOpPrecendence(BfBinaryOp binOp)
switch (binOp)
{
case BfBinaryOp_Multiply:
case BfBinaryOp_OverflowMultiply:
case BfBinaryOp_Divide:
case BfBinaryOp_Modulus:
case BfBinaryOp_Modulus:
return 13;
case BfBinaryOp_Add:
case BfBinaryOp_Subtract:
case BfBinaryOp_Subtract:
case BfBinaryOp_OverflowAdd:
case BfBinaryOp_OverflowSubtract:
return 12;
case BfBinaryOp_LeftShift:
case BfBinaryOp_RightShift:
@ -1682,6 +1691,9 @@ const char* Beefy::BfGetOpName(BfBinaryOp binOp)
case BfBinaryOp_Add: return "+";
case BfBinaryOp_Subtract: return "-";
case BfBinaryOp_Multiply: return "*";
case BfBinaryOp_OverflowAdd: return "&+";
case BfBinaryOp_OverflowSubtract: return "&-";
case BfBinaryOp_OverflowMultiply: return "&*";
case BfBinaryOp_Divide: return "/";
case BfBinaryOp_Modulus: return "%";
case BfBinaryOp_BitwiseAnd: return "&";
@ -1742,6 +1754,12 @@ BfBinaryOp Beefy::BfTokenToBinaryOp(BfToken token)
return BfBinaryOp_Subtract;
case BfToken_Star:
return BfBinaryOp_Multiply;
case BfToken_AndPlus:
return BfBinaryOp_OverflowAdd;
case BfToken_AndMinus:
return BfBinaryOp_OverflowSubtract;
case BfToken_AndStar:
return BfBinaryOp_OverflowMultiply;
case BfToken_ForwardSlash:
return BfBinaryOp_Divide;
case BfToken_Modulus:

View file

@ -210,6 +210,9 @@ enum BfToken : uint8
BfToken_ShiftLeftEquals,
BfToken_ShiftRightEquals,
BfToken_AndEquals,
BfToken_AndMinus,
BfToken_AndPlus,
BfToken_AndStar,
BfToken_OrEquals,
BfToken_XorEquals,
BfToken_NullCoalsceEquals,
@ -1795,6 +1798,9 @@ enum BfBinaryOp
BfBinaryOp_Add,
BfBinaryOp_Subtract,
BfBinaryOp_Multiply,
BfBinaryOp_OverflowAdd,
BfBinaryOp_OverflowSubtract,
BfBinaryOp_OverflowMultiply,
BfBinaryOp_Divide,
BfBinaryOp_Modulus,
BfBinaryOp_BitwiseAnd,

View file

@ -21177,11 +21177,20 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
BfBinaryOp findBinaryOp = binaryOp;
bool isComparison = (binaryOp >= BfBinaryOp_Equality) && (binaryOp <= BfBinaryOp_LessThanOrEqual);
for (int pass = 0; pass < 2; pass++)
{
BfBinaryOp oppositeBinaryOp = BfGetOppositeBinaryOp(findBinaryOp);
bool foundOp = false;
BfBinaryOp overflowBinaryOp = BfBinaryOp_None;
if (findBinaryOp == BfBinaryOp_OverflowAdd)
overflowBinaryOp = BfBinaryOp_Add;
else if (findBinaryOp == BfBinaryOp_OverflowSubtract)
overflowBinaryOp = BfBinaryOp_Subtract;
else if (findBinaryOp == BfBinaryOp_OverflowMultiply)
overflowBinaryOp = BfBinaryOp_Multiply;
bool foundOp = false;
BfResolvedArg leftArg;
leftArg.mExpression = leftExpression;
@ -21225,7 +21234,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
bool invertResult = false;
BfType* operatorConstraintReturnType = NULL;
bool wasTransformedUsage = pass == 1;
bool wasTransformedUsage = (pass == 1);
while (true)
{
@ -21288,7 +21297,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
}
}
}
else if (operatorDef->mOperatorDeclaration->mBinOp == oppositeBinaryOp)
else if ((operatorDef->mOperatorDeclaration->mBinOp == oppositeBinaryOp) || (operatorDef->mOperatorDeclaration->mBinOp == overflowBinaryOp))
oppositeOperatorDefs.Add(operatorDef);
}
@ -21309,7 +21318,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
methodMatcher.mBestMethodDef = oppositeOperatorDef;
methodMatcher.mBestMethodTypeInstance = checkType;
methodMatcher.mSelfType = entry.mSrcType;
wasTransformedUsage = true;
if (oppositeBinaryOp != BfBinaryOp_None)
wasTransformedUsage = true;
}
}
else
@ -21322,7 +21332,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
{
operatorConstraintReturnType = returnType;
methodMatcher.mSelfType = entry.mSrcType;
wasTransformedUsage = true;
if (oppositeBinaryOp != BfBinaryOp_None)
wasTransformedUsage = true;
}
}
}
@ -21332,7 +21343,8 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
if (methodMatcher.CheckMethod(NULL, checkType, oppositeOperatorDef, false))
{
methodMatcher.mSelfType = entry.mSrcType;
wasTransformedUsage = true;
if (oppositeBinaryOp != BfBinaryOp_None)
wasTransformedUsage = true;
}
}
}
@ -21526,12 +21538,12 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
if (pass == 1)
break;
auto flippedBinaryOp = BfGetFlippedBinaryOp(findBinaryOp);
auto flippedBinaryOp = BfGetFlippedBinaryOp(findBinaryOp);
if (flippedBinaryOp != BfBinaryOp_None)
findBinaryOp = flippedBinaryOp;
findBinaryOp = flippedBinaryOp;
}
auto prevResultType = resultType;
if ((leftValue.mType->IsPrimitiveType()) && (!rightValue.mType->IsTypedPrimitive()))
resultType = leftValue.mType;
@ -21567,7 +21579,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
}
//TODO: Allow all pointer comparisons, but only allow SUBTRACTION between equal pointer types
if (binaryOp == BfBinaryOp_Subtract)
if ((binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowSubtract))
{
if (!mModule->CanCast(*otherTypedValue, resultType))
{
@ -21622,7 +21634,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
// One pointer
if ((!otherType->IsIntegral()) ||
((binaryOp != BfBinaryOp_Add) && (binaryOp != BfBinaryOp_Subtract)))
((binaryOp != BfBinaryOp_Add) && (binaryOp != BfBinaryOp_Subtract) && (binaryOp != BfBinaryOp_OverflowAdd) && (binaryOp != BfBinaryOp_OverflowSubtract)))
{
_OpFail();
return;
@ -21632,7 +21644,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
BfIRValue addValue = otherTypedValue->mValue;
if ((!otherTypedValue->mType->IsSigned()) && (otherTypedValue->mType->mSize < mModule->mSystem->mPtrSize))
addValue = mModule->mBfIRBuilder->CreateNumericCast(addValue, false, BfTypeCode_UIntPtr);
if (binaryOp == BfBinaryOp_Subtract)
if ((binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowSubtract))
{
if (resultTypeSrc == rightExpression)
mModule->Fail("Cannot subtract a pointer from an integer", resultTypeSrc);
@ -21731,7 +21743,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
}
// Allow integer offsetting
if ((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract))
if ((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowAdd) || (binaryOp == BfBinaryOp_OverflowSubtract))
{
if (otherType->IsIntegral())
needsOtherCast = false;
@ -21954,7 +21966,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
if (rightValue.mType->IsIntegral())
explicitCast = true;
}
else if (((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract)) && (resultType->IsChar()) && (otherType->IsInteger()))
else if (((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowAdd) || (binaryOp == BfBinaryOp_OverflowSubtract)) && (resultType->IsChar()) && (otherType->IsInteger()))
{
// charVal += intVal;
explicitCast = true;
@ -21980,14 +21992,15 @@ void BfExprEvaluator::PerformBinaryOperation(BfAstNode* leftExpression, BfAstNod
}
else
{
if ((binaryOp == BfBinaryOp_Subtract) && (resultType->IsChar()) && (otherType->IsChar()))
if (((binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowSubtract)) &&
(resultType->IsChar()) && (otherType->IsChar()))
{
// "wchar - char" subtraction will always fit into int32, because of unicode range
resultType = mModule->GetPrimitiveType(BfTypeCode_Int32);
explicitCast = true;
}
else if ((otherType->IsChar()) &&
((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract)))
((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowAdd) || (binaryOp == BfBinaryOp_OverflowSubtract)))
{
mModule->Fail(StrFormat("Cannot perform operation between types '%s' and '%s'",
mModule->TypeToString(leftValue.mType).c_str(),
@ -22142,6 +22155,7 @@ void BfExprEvaluator::PerformBinaryOperation(BfType* resultType, BfIRValue convL
if ((resultType->IsChar()) &&
((binaryOp == BfBinaryOp_Multiply) ||
(binaryOp == BfBinaryOp_OverflowMultiply) ||
(binaryOp == BfBinaryOp_Divide) ||
(binaryOp == BfBinaryOp_Modulus)))
{
@ -22151,15 +22165,18 @@ void BfExprEvaluator::PerformBinaryOperation(BfType* resultType, BfIRValue convL
switch (binaryOp)
{
case BfBinaryOp_Add:
case BfBinaryOp_Add:
case BfBinaryOp_OverflowAdd:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateAdd(convLeftValue, convRightValue), resultType);
mModule->CheckRangeError(resultType, opToken);
break;
case BfBinaryOp_Subtract:
case BfBinaryOp_Subtract:
case BfBinaryOp_OverflowSubtract:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateSub(convLeftValue, convRightValue), resultType);
mModule->CheckRangeError(resultType, opToken);
break;
case BfBinaryOp_Multiply:
case BfBinaryOp_Multiply:
case BfBinaryOp_OverflowMultiply:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateMul(convLeftValue, convRightValue), resultType);
mModule->CheckRangeError(resultType, opToken);
break;

View file

@ -754,6 +754,15 @@ String BfGNUMangler::Mangle(BfMethodInstance* methodInst)
case BfBinaryOp_Multiply:
methodName = "ml";
break;
case BfBinaryOp_OverflowAdd:
methodName = "opl";
break;
case BfBinaryOp_OverflowSubtract:
methodName = "omi";
break;
case BfBinaryOp_OverflowMultiply:
methodName = "oml";
break;
case BfBinaryOp_Divide:
methodName = "dv";
break;
@ -1872,6 +1881,15 @@ void BfMSMangler::Mangle(StringImpl& name, bool is64Bit, BfMethodInstance* metho
case BfBinaryOp_Multiply:
name += "?D";
break;
case BfBinaryOp_OverflowAdd:
name += "?OH";
break;
case BfBinaryOp_OverflowSubtract:
name += "?OG";
break;
case BfBinaryOp_OverflowMultiply:
name += "?OD";
break;
case BfBinaryOp_Divide:
name += "?K";
break;

View file

@ -1549,6 +1549,21 @@ void BfParser::NextToken(int endIdx, bool outerIsInterpolate)
mToken = BfToken_AndEquals;
mTokenEnd = ++mSrcIdx;
}
else if (mSrc[mSrcIdx] == '+')
{
mToken = BfToken_AndPlus;
mTokenEnd = ++mSrcIdx;
}
else if (mSrc[mSrcIdx] == '-')
{
mToken = BfToken_AndMinus;
mTokenEnd = ++mSrcIdx;
}
else if (mSrc[mSrcIdx] == '*')
{
mToken = BfToken_AndStar;
mTokenEnd = ++mSrcIdx;
}
else
mToken = BfToken_Ampersand;
mSyntaxToken = BfSyntaxToken_Token;

View file

@ -5975,13 +5975,13 @@ void DbgExprEvaluator::PerformBinaryOperation(ASTREF(BfExpression*)& leftExpress
// One pointer
if ((!otherType->IsInteger()) ||
((binaryOp != BfBinaryOp_Add) && (binaryOp != BfBinaryOp_Subtract) && (!isCompare)))
((binaryOp != BfBinaryOp_Add) && (binaryOp != BfBinaryOp_Subtract) && (binaryOp != BfBinaryOp_OverflowAdd) && (binaryOp != BfBinaryOp_OverflowSubtract) && (!isCompare)))
{
Fail("Can only add or subtract integer values from pointers", rightExpression);
return;
}
if ((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract))
if ((binaryOp == BfBinaryOp_Add) || (binaryOp == BfBinaryOp_Subtract) || (binaryOp == BfBinaryOp_OverflowAdd) || (binaryOp == BfBinaryOp_OverflowSubtract))
{
auto underlyingType = otherType->GetUnderlyingType();
mResult.mType = resultType;
@ -6262,6 +6262,7 @@ void DbgExprEvaluator::PerformBinaryOperation(DbgType* resultType, DbgTypedValue
switch (binaryOp)
{
case BfBinaryOp_Add:
case BfBinaryOp_OverflowAdd:
if (resultType->mTypeCode == DbgType_Single)
mResult.mSingle = convLeftValue.mSingle + convRightValue.mSingle;
else if (resultType->mTypeCode == DbgType_Double)
@ -6270,6 +6271,7 @@ void DbgExprEvaluator::PerformBinaryOperation(DbgType* resultType, DbgTypedValue
mResult.mInt64 = convLeftValue.GetInt64() + convRightValue.GetInt64();
break;
case BfBinaryOp_Subtract:
case BfBinaryOp_OverflowSubtract:
if (resultType->mTypeCode == DbgType_Single)
mResult.mSingle = convLeftValue.mSingle - convRightValue.mSingle;
else if (resultType->mTypeCode == DbgType_Double)
@ -6278,6 +6280,7 @@ void DbgExprEvaluator::PerformBinaryOperation(DbgType* resultType, DbgTypedValue
mResult.mInt64 = convLeftValue.GetInt64() - convRightValue.GetInt64();
break;
case BfBinaryOp_Multiply:
case BfBinaryOp_OverflowMultiply:
if (resultType->mTypeCode == DbgType_Single)
mResult.mSingle = convLeftValue.mSingle * convRightValue.mSingle;
else if (resultType->mTypeCode == DbgType_Double)

View file

@ -198,6 +198,41 @@ namespace Tests
}
}
struct StructH
{
public static int operator+(StructH lhs, int rhs)
{
return 1;
}
public static int operator+(int lhs, StructH rhs)
{
return 2;
}
[Commutable]
public static int operator+(StructH lhs, float rhs)
{
return 3;
}
public static int operator&+(StructH lhs, int rhs)
{
return 4;
}
public static int operator&+(int lhs, StructH rhs)
{
return 5;
}
[Commutable]
public static int operator&+(StructH lhs, float rhs)
{
return 6;
}
}
struct StructOp<T, T2> where T : operator T + T2
{
public T DoIt(T val, T2 val2)
@ -428,6 +463,20 @@ namespace Tests
Test.Assert(10 + sf == 2);
Test.Assert(sf + 1.0f == 3);
Test.Assert(2.0f + sf == 3);
Test.Assert(sf &+ 10 == 1);
Test.Assert(10 &+ sf == 2);
Test.Assert(sf &+ 1.0f == 3);
Test.Assert(2.0f &+ sf == 3);
StructH sh = default;
Test.Assert(sh + 10 == 1);
Test.Assert(10 + sh == 2);
Test.Assert(sh + 1.0f == 3);
Test.Assert(2.0f + sh == 3);
Test.Assert(sh &+ 10 == 4);
Test.Assert(10 &+ sh == 5);
Test.Assert(sh &+ 1.0f == 6);
Test.Assert(2.0f &+ sh == 6);
StructG sg = .(100);
StructG sg2 = .(200);