1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 11:38:21 +02:00

Fixed comptime geps with non-ptrsize indices

This commit is contained in:
Brian Fiete 2023-03-14 11:56:59 -07:00
parent 398cb0c7ad
commit dd22fa056f
4 changed files with 445 additions and 278 deletions

View file

@ -21183,6 +21183,8 @@ void BfExprEvaluator::Visit(BfTupleExpression* tupleExpr)
if (isExactConst) if (isExactConst)
{ {
mModule->PopulateType(tupleType); mModule->PopulateType(tupleType);
if (tupleType->IsDataIncomplete())
return;
Array<BfIRValue> irValues; Array<BfIRValue> irValues;
irValues.Resize(typedValues.mSize + 1); irValues.Resize(typedValues.mSize + 1);

View file

@ -1108,6 +1108,21 @@ String CeDebugger::Evaluate(const StringImpl& expr, CeFormatInfo formatInfo, int
auto terminatedExpr = expr; auto terminatedExpr = expr;
terminatedExpr.Trim(); terminatedExpr.Trim();
if (terminatedExpr.StartsWith("!"))
{
if (terminatedExpr == "!info")
{
auto ceFrame = GetFrame(callStackIdx);
if (ceFrame != NULL)
{
if (ceFrame->mFunction->mCeFunctionInfo->mMethodInstance != NULL)
OutputMessage(StrFormat("Module: %s\n", ceFrame->mFunction->mCeFunctionInfo->mMethodInstance->GetOwner()->mModule->mModuleName.c_str()));
OutputMessage(StrFormat("Link Name: %s\n", ceFrame->mFunction->mCeFunctionInfo->mName.c_str()));
}
return "";
}
}
if (terminatedExpr.EndsWith(">")) if (terminatedExpr.EndsWith(">"))
parseAsType = true; parseAsType = true;
else if ((terminatedExpr.StartsWith("comptype(")) && (!terminatedExpr.Contains('.'))) else if ((terminatedExpr.StartsWith("comptype(")) && (!terminatedExpr.Contains('.')))

View file

@ -250,39 +250,29 @@ static_assert(BF_ARRAY_COUNT(gOpInfo) == (int)CeOp_COUNT, "gOpName incorrect siz
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
static int FloatToString(float d, char* outStr) static int ToString(float d, char* outStr, bool roundTrip)
{ {
sprintf(outStr, "%1.9g", d); if (!roundTrip)
int len = (int)strlen(outStr);
for (int i = 0; outStr[i] != 0; i++)
{ {
if (outStr[i] == '.') int digits;
{ if (d > 100000)
int checkC = len - 1; digits = 1;
while (true) else if (d > 10000)
{ digits = 2;
char c = outStr[checkC]; else if (d > 1000)
if (c == '.') digits = 3;
{ else if (d > 100)
return checkC; digits = 4;
} else if (d > 10)
else if (c != '0') digits = 5;
{ else
for (int j = i + 1; j <= checkC; j++) digits = 6;
if (outStr[j] == 'e')
return len; sprintf(outStr, "%1.*f", digits, d);
return checkC + 1; }
} else
checkC--; sprintf(outStr, "%1.9g", d);
}
}
}
return len;
}
static int DoubleToString(double d, char* outStr)
{
sprintf(outStr, "%1.17g", d);
int len = (int)strlen(outStr); int len = (int)strlen(outStr);
for (int i = 0; outStr[i] != 0; i++) for (int i = 0; outStr[i] != 0; i++)
{ {
@ -311,9 +301,153 @@ static int DoubleToString(double d, char* outStr)
} }
} }
} }
if ((len == 3) && (outStr[0] == 'i'))
{
strcpy(outStr, "Infinity");
return 8;
}
if ((len == 4) && (outStr[0] == '-') && (outStr[1] == 'i'))
{
strcpy(outStr, "-Infinity");
return 9;
}
if ((len == 9) && (outStr[0] == '-') && (outStr[1] == 'n')) //-nan(xxx)
{
strcpy(outStr, "NaN");
return 3;
}
return len; return len;
} }
static int ToString(double d, char* outStr, bool roundTrip)
{
if (!roundTrip)
{
int digits;
if (d < 0)
{
if (d < -10000000000)
{
sprintf(outStr, "%g", d);
}
else
{
if (d < -1000000000)
digits = 1;
else if (d < -100000000)
digits = 2;
else if (d < -10000000)
digits = 3;
else if (d < -1000000)
digits = 4;
else if (d < -100000)
digits = 5;
else if (d < -10000)
digits = 6;
else if (d < -1000)
digits = 7;
else if (d < -100)
digits = 8;
else if (d < -10)
digits = 9;
else
digits = 10;
sprintf(outStr, "%1.*f", digits, d);
}
}
else
{
if (d > 10000000000)
{
sprintf(outStr, "%g", d);
}
else
{
if (d > 1000000000)
digits = 1;
else if (d > 100000000)
digits = 2;
else if (d > 10000000)
digits = 3;
else if (d > 1000000)
digits = 4;
else if (d > 100000)
digits = 5;
else if (d > 10000)
digits = 6;
else if (d > 1000)
digits = 7;
else if (d > 100)
digits = 8;
else if (d > 10)
digits = 9;
else
digits = 10;
sprintf(outStr, "%1.*f", digits, d);
}
}
}
else
sprintf(outStr, "%1.17g", d);
int len = (int)strlen(outStr);
for (int i = 0; outStr[i] != 0; i++)
{
if (outStr[i] == '.')
{
int checkC = len - 1;
while (true)
{
char c = outStr[checkC];
if (c == '.')
{
return checkC;
}
else if (c == 'e')
{
return len;
}
else if (c != '0')
{
for (int j = i + 1; j <= checkC; j++)
if (outStr[j] == 'e')
return len;
return checkC + 1;
}
checkC--;
}
}
}
if ((len == 3) && (outStr[0] == 'i'))
{
strcpy(outStr, "Infinity");
return 8;
}
if ((len == 4) && (outStr[0] == '-') && (outStr[1] == 'i'))
{
strcpy(outStr, "-Infinity");
return 9;
}
if ((len == 9) && (outStr[0] == '-') && (outStr[1] == 'n')) //-nan(xxx)
{
strcpy(outStr, "NaN");
return 3;
}
return len;
}
static int FloatToString(float d, char* outStr)
{
return ::ToString(d, outStr, false);
}
static int DoubleToString(double d, char* outStr)
{
return ::ToString(d, outStr, false);
}
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
String CeDbgMethodRef::ToString() String CeDbgMethodRef::ToString()
@ -871,6 +1005,261 @@ void CeBuilder::EmitBinaryOp(CeOp iOp, CeOp fOp, const CeOperand& lhs, const CeO
EmitFrameOffset(rhs); EmitFrameOffset(rhs);
} }
CeOperand CeBuilder::EmitNumericCast(const CeOperand& ceValue, BeType* toType, bool valSigned, bool toSigned)
{
CeOperand result;
auto fromType = ceValue.mType;
if (fromType == toType)
{
// If it's just a sign change then leave it alone
result = ceValue;
}
else
{
if ((toType->IsIntable()) && (fromType->IsIntable()) && (toType->mSize <= fromType->mSize))
{
// For truncating values, no actual instructions are needed
// Note that a copy is not needed because of SSA rules
result = ceValue;
result.mType = toType;
}
else
{
result = FrameAlloc(toType);
CeOp op = CeOp_InvalidOp;
BeTypeCode fromTypeCode = fromType->mTypeCode;
BeTypeCode toTypeCode = toType->mTypeCode;
if ((valSigned) && (toSigned))
{
switch (fromTypeCode)
{
case BeTypeCode_Int8:
switch (toTypeCode)
{
case BeTypeCode_Int16:
op = CeOp_Conv_I8_I16;
break;
case BeTypeCode_Int32:
op = CeOp_Conv_I8_I32;
break;
case BeTypeCode_Int64:
op = CeOp_Conv_I8_I64;
break;
case BeTypeCode_Float:
op = CeOp_Conv_I8_F32;
break;
case BeTypeCode_Double:
op = CeOp_Conv_I8_F64;
break;
}
break;
case BeTypeCode_Int16:
switch (toTypeCode)
{
case BeTypeCode_Int32:
op = CeOp_Conv_I16_I32;
break;
case BeTypeCode_Int64:
op = CeOp_Conv_I16_I64;
break;
case BeTypeCode_Float:
op = CeOp_Conv_I16_F32;
break;
case BeTypeCode_Double:
op = CeOp_Conv_I16_F64;
break;
}
break;
case BeTypeCode_Int32:
switch (toTypeCode)
{
case BeTypeCode_Int64:
op = CeOp_Conv_I32_I64;
break;
case BeTypeCode_Float:
op = CeOp_Conv_I32_F32;
break;
case BeTypeCode_Double:
op = CeOp_Conv_I32_F64;
break;
}
break;
case BeTypeCode_Int64:
switch (toTypeCode)
{
case BeTypeCode_Float:
op = CeOp_Conv_I64_F32;
break;
case BeTypeCode_Double:
op = CeOp_Conv_I64_F64;
break;
}
break;
case BeTypeCode_Float:
switch (toTypeCode)
{
case BeTypeCode_Int8:
op = CeOp_Conv_F32_I8;
break;
case BeTypeCode_Int16:
op = CeOp_Conv_F32_I16;
break;
case BeTypeCode_Int32:
op = CeOp_Conv_F32_I32;
break;
case BeTypeCode_Int64:
op = CeOp_Conv_F32_I64;
break;
case BeTypeCode_Double:
op = CeOp_Conv_F32_F64;
break;
}
break;
case BeTypeCode_Double:
switch (toTypeCode)
{
case BeTypeCode_Int8:
op = CeOp_Conv_F64_I8;
break;
case BeTypeCode_Int16:
op = CeOp_Conv_F64_I16;
break;
case BeTypeCode_Int32:
op = CeOp_Conv_F64_I32;
break;
case BeTypeCode_Int64:
op = CeOp_Conv_F64_I64;
break;
case BeTypeCode_Float:
op = CeOp_Conv_F64_F32;
break;
}
break;
}
}
else
{
switch (fromTypeCode)
{
case BeTypeCode_Int8:
switch (toTypeCode)
{
case BeTypeCode_Int16:
op = CeOp_Conv_U8_U16;
break;
case BeTypeCode_Int32:
op = CeOp_Conv_U8_U32;
break;
case BeTypeCode_Int64:
op = CeOp_Conv_U8_U64;
break;
case BeTypeCode_Float:
op = CeOp_Conv_I8_F32;
break;
case BeTypeCode_Double:
op = CeOp_Conv_I8_F64;
break;
}
break;
case BeTypeCode_Int16:
switch (toTypeCode)
{
case BeTypeCode_Int32:
op = CeOp_Conv_U16_U32;
break;
case BeTypeCode_Int64:
op = CeOp_Conv_U16_U64;
break;
case BeTypeCode_Float:
op = CeOp_Conv_U16_F32;
break;
case BeTypeCode_Double:
op = CeOp_Conv_U16_F64;
break;
}
break;
case BeTypeCode_Int32:
switch (toTypeCode)
{
case BeTypeCode_Int64:
op = CeOp_Conv_U32_U64;
break;
case BeTypeCode_Float:
op = CeOp_Conv_U32_F32;
break;
case BeTypeCode_Double:
op = CeOp_Conv_U32_F64;
break;
}
break;
case BeTypeCode_Int64:
switch (toTypeCode)
{
case BeTypeCode_Float:
op = CeOp_Conv_I64_F32;
break;
case BeTypeCode_Double:
op = CeOp_Conv_I64_F64;
break;
}
break;
case BeTypeCode_Float:
switch (toTypeCode)
{
case BeTypeCode_Int8:
op = CeOp_Conv_F32_U8;
break;
case BeTypeCode_Int16:
op = CeOp_Conv_F32_U16;
break;
case BeTypeCode_Int32:
op = CeOp_Conv_F32_U32;
break;
case BeTypeCode_Int64:
op = CeOp_Conv_F32_U64;
break;
}
break;
case BeTypeCode_Double:
switch (toTypeCode)
{
case BeTypeCode_Int8:
op = CeOp_Conv_F64_U8;
break;
case BeTypeCode_Int16:
op = CeOp_Conv_F64_U16;
break;
case BeTypeCode_Int32:
op = CeOp_Conv_F64_U32;
break;
case BeTypeCode_Int64:
op = CeOp_Conv_F64_U64;
break;
}
break;
}
}
if (op == CeOp_InvalidOp)
{
Fail("Invalid conversion op");
}
else
{
Emit(op);
EmitFrameOffset(result);
EmitFrameOffset(ceValue);
}
}
}
return result;
}
void CeBuilder::EmitUnaryOp(CeOp iOp, CeOp fOp, const CeOperand& val, CeOperand& result) void CeBuilder::EmitUnaryOp(CeOp iOp, CeOp fOp, const CeOperand& val, CeOperand& result)
{ {
CeOp op = iOp; CeOp op = iOp;
@ -2089,254 +2478,7 @@ void CeBuilder::Build()
{ {
auto castedInst = (BeNumericCastInst*)inst; auto castedInst = (BeNumericCastInst*)inst;
auto ceValue = GetOperand(castedInst->mValue); auto ceValue = GetOperand(castedInst->mValue);
auto fromType = ceValue.mType; result = EmitNumericCast(ceValue, castedInst->mToType, castedInst->mValSigned, castedInst->mToSigned);
if (fromType == castedInst->mToType)
{
// If it's just a sign change then leave it alone
result = ceValue;
}
else
{
auto toType = castedInst->mToType;
if ((toType->IsIntable()) && (fromType->IsIntable()) && (toType->mSize <= fromType->mSize))
{
// For truncating values, no actual instructions are needed
// Note that a copy is not needed because of SSA rules
result = ceValue;
result.mType = toType;
}
else
{
result = FrameAlloc(toType);
CeOp op = CeOp_InvalidOp;
BeTypeCode fromTypeCode = fromType->mTypeCode;
BeTypeCode toTypeCode = toType->mTypeCode;
if ((castedInst->mValSigned) && (castedInst->mToSigned))
{
switch (fromTypeCode)
{
case BeTypeCode_Int8:
switch (toTypeCode)
{
case BeTypeCode_Int16:
op = CeOp_Conv_I8_I16;
break;
case BeTypeCode_Int32:
op = CeOp_Conv_I8_I32;
break;
case BeTypeCode_Int64:
op = CeOp_Conv_I8_I64;
break;
case BeTypeCode_Float:
op = CeOp_Conv_I8_F32;
break;
case BeTypeCode_Double:
op = CeOp_Conv_I8_F64;
break;
}
break;
case BeTypeCode_Int16:
switch (toTypeCode)
{
case BeTypeCode_Int32:
op = CeOp_Conv_I16_I32;
break;
case BeTypeCode_Int64:
op = CeOp_Conv_I16_I64;
break;
case BeTypeCode_Float:
op = CeOp_Conv_I16_F32;
break;
case BeTypeCode_Double:
op = CeOp_Conv_I16_F64;
break;
}
break;
case BeTypeCode_Int32:
switch (toTypeCode)
{
case BeTypeCode_Int64:
op = CeOp_Conv_I32_I64;
break;
case BeTypeCode_Float:
op = CeOp_Conv_I32_F32;
break;
case BeTypeCode_Double:
op = CeOp_Conv_I32_F64;
break;
}
break;
case BeTypeCode_Int64:
switch (toTypeCode)
{
case BeTypeCode_Float:
op = CeOp_Conv_I64_F32;
break;
case BeTypeCode_Double:
op = CeOp_Conv_I64_F64;
break;
}
break;
case BeTypeCode_Float:
switch (toTypeCode)
{
case BeTypeCode_Int8:
op = CeOp_Conv_F32_I8;
break;
case BeTypeCode_Int16:
op = CeOp_Conv_F32_I16;
break;
case BeTypeCode_Int32:
op = CeOp_Conv_F32_I32;
break;
case BeTypeCode_Int64:
op = CeOp_Conv_F32_I64;
break;
case BeTypeCode_Double:
op = CeOp_Conv_F32_F64;
break;
}
break;
case BeTypeCode_Double:
switch (toTypeCode)
{
case BeTypeCode_Int8:
op = CeOp_Conv_F64_I8;
break;
case BeTypeCode_Int16:
op = CeOp_Conv_F64_I16;
break;
case BeTypeCode_Int32:
op = CeOp_Conv_F64_I32;
break;
case BeTypeCode_Int64:
op = CeOp_Conv_F64_I64;
break;
case BeTypeCode_Float:
op = CeOp_Conv_F64_F32;
break;
}
break;
}
}
else
{
switch (fromTypeCode)
{
case BeTypeCode_Int8:
switch (toTypeCode)
{
case BeTypeCode_Int16:
op = CeOp_Conv_U8_U16;
break;
case BeTypeCode_Int32:
op = CeOp_Conv_U8_U32;
break;
case BeTypeCode_Int64:
op = CeOp_Conv_U8_U64;
break;
case BeTypeCode_Float:
op = CeOp_Conv_I8_F32;
break;
case BeTypeCode_Double:
op = CeOp_Conv_I8_F64;
break;
}
break;
case BeTypeCode_Int16:
switch (toTypeCode)
{
case BeTypeCode_Int32:
op = CeOp_Conv_U16_U32;
break;
case BeTypeCode_Int64:
op = CeOp_Conv_U16_U64;
break;
case BeTypeCode_Float:
op = CeOp_Conv_U16_F32;
break;
case BeTypeCode_Double:
op = CeOp_Conv_U16_F64;
break;
}
break;
case BeTypeCode_Int32:
switch (toTypeCode)
{
case BeTypeCode_Int64:
op = CeOp_Conv_U32_U64;
break;
case BeTypeCode_Float:
op = CeOp_Conv_U32_F32;
break;
case BeTypeCode_Double:
op = CeOp_Conv_U32_F64;
break;
}
break;
case BeTypeCode_Int64:
switch (toTypeCode)
{
case BeTypeCode_Float:
op = CeOp_Conv_I64_F32;
break;
case BeTypeCode_Double:
op = CeOp_Conv_I64_F64;
break;
}
break;
case BeTypeCode_Float:
switch (toTypeCode)
{
case BeTypeCode_Int8:
op = CeOp_Conv_F32_U8;
break;
case BeTypeCode_Int16:
op = CeOp_Conv_F32_U16;
break;
case BeTypeCode_Int32:
op = CeOp_Conv_F32_U32;
break;
case BeTypeCode_Int64:
op = CeOp_Conv_F32_U64;
break;
}
break;
case BeTypeCode_Double:
switch (toTypeCode)
{
case BeTypeCode_Int8:
op = CeOp_Conv_F64_U8;
break;
case BeTypeCode_Int16:
op = CeOp_Conv_F64_U16;
break;
case BeTypeCode_Int32:
op = CeOp_Conv_F64_U32;
break;
case BeTypeCode_Int64:
op = CeOp_Conv_F64_U64;
break;
}
break;
}
}
if (op == CeOp_InvalidOp)
{
Fail("Invalid conversion op");
}
else
{
Emit(op);
EmitFrameOffset(result);
EmitFrameOffset(ceValue);
}
}
}
} }
break; break;
case BeStoreInst::TypeId: case BeStoreInst::TypeId:
@ -2463,6 +2605,9 @@ void CeBuilder::Build()
auto ceVal = GetOperand(castedInst->mPtr); auto ceVal = GetOperand(castedInst->mPtr);
auto ceIdx0 = GetOperand(castedInst->mIdx0, false, true); auto ceIdx0 = GetOperand(castedInst->mIdx0, false, true);
if ((ceIdx0.mType != NULL) && (ceIdx0.mType->mSize < mPtrSize))
ceIdx0 = EmitNumericCast(ceIdx0, mIntPtrType, true, true);
BePointerType* ptrType = (BePointerType*)ceVal.mType; BePointerType* ptrType = (BePointerType*)ceVal.mType;
BF_ASSERT(ptrType->mTypeCode == BeTypeCode_Pointer); BF_ASSERT(ptrType->mTypeCode == BeTypeCode_Pointer);
@ -2473,6 +2618,10 @@ void CeBuilder::Build()
BF_ASSERT(castedInst->mIdx0); BF_ASSERT(castedInst->mIdx0);
auto ceIdx1 = GetOperand(castedInst->mIdx1, false, true); auto ceIdx1 = GetOperand(castedInst->mIdx1, false, true);
if ((ceIdx1.mType != NULL) && (ceIdx1.mType->mSize < mPtrSize))
ceIdx1 = EmitNumericCast(ceIdx1, mIntPtrType, true, true);
if (!ceIdx1.IsImmediate()) if (!ceIdx1.IsImmediate())
{ {
// This path is used when we have a const array that gets indexed by a non-const index value // This path is used when we have a const array that gets indexed by a non-const index value

View file

@ -883,6 +883,7 @@ public:
void EmitZeroes(int size); void EmitZeroes(int size);
void EmitJump(CeOp op, const CeOperand& block); void EmitJump(CeOp op, const CeOperand& block);
void EmitBinarySwitchSection(BeSwitchInst* switchInst, int startIdx, int endIdx); void EmitBinarySwitchSection(BeSwitchInst* switchInst, int startIdx, int endIdx);
CeOperand EmitNumericCast(const CeOperand& ceValue, BeType* toType, bool valSigned, bool toSigned);
void EmitFrameOffset(const CeOperand& val); void EmitFrameOffset(const CeOperand& val);
void FlushPhi(CeBlock* ceBlock, int targetBlockIdx); void FlushPhi(CeBlock* ceBlock, int targetBlockIdx);