mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 19:48:20 +02:00
Fixed const expr canonicalization and negative value issues
This commit is contained in:
parent
e7f079f611
commit
fa7638621d
7 changed files with 53 additions and 22 deletions
|
@ -7986,7 +7986,7 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
||||||
{
|
{
|
||||||
if (BfIRConstHolder::IsInt(primType->mTypeDef->mTypeCode))
|
if (BfIRConstHolder::IsInt(primType->mTypeDef->mTypeCode))
|
||||||
{
|
{
|
||||||
if (!mCompiler->mSystem->DoesLiteralFit(primType->mTypeDef->mTypeCode, constExprValueType->mValue.mUInt64))
|
if (!mCompiler->mSystem->DoesLiteralFit(primType->mTypeDef->mTypeCode, constExprValueType->mValue))
|
||||||
{
|
{
|
||||||
if ((!ignoreErrors) && (PreFail()))
|
if ((!ignoreErrors) && (PreFail()))
|
||||||
*errorOut = Fail(StrFormat("Const generic argument '%s', declared with const '%lld', does not fit into const constraint '%s' for '%s'", genericParamInst->GetName().c_str(),
|
*errorOut = Fail(StrFormat("Const generic argument '%s', declared with const '%lld', does not fit into const constraint '%s' for '%s'", genericParamInst->GetName().c_str(),
|
||||||
|
@ -17051,7 +17051,10 @@ void BfModule::EmitCtorBody(bool& skipBody)
|
||||||
mCompiler->mResolvePassData->mSourceClassifier->SetElementType(fieldDef->mInitializer, BfSourceElementType_Normal);
|
mCompiler->mResolvePassData->mSourceClassifier->SetElementType(fieldDef->mInitializer, BfSourceElementType_Normal);
|
||||||
mCompiler->mResolvePassData->mSourceClassifier->VisitChild(fieldDef->mInitializer);
|
mCompiler->mResolvePassData->mSourceClassifier->VisitChild(fieldDef->mInitializer);
|
||||||
|
|
||||||
auto wantType = ResolveTypeRef(fieldDef->mTypeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowInferredSizedArray);
|
BfType* wantType = NULL;
|
||||||
|
if ((!BfNodeIsA<BfVarTypeReference>(fieldDef->mTypeRef)) &&
|
||||||
|
(!BfNodeIsA<BfLetTypeReference>(fieldDef->mTypeRef)))
|
||||||
|
wantType = ResolveTypeRef(fieldDef->mTypeRef, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowInferredSizedArray);
|
||||||
if ((wantType != NULL) &&
|
if ((wantType != NULL) &&
|
||||||
((wantType->IsVar()) || (wantType->IsLet()) || (wantType->IsRef())))
|
((wantType->IsVar()) || (wantType->IsLet()) || (wantType->IsRef())))
|
||||||
wantType = NULL;
|
wantType = NULL;
|
||||||
|
|
|
@ -2770,13 +2770,26 @@ BfResolvedTypeSet::~BfResolvedTypeSet()
|
||||||
|
|
||||||
BfVariant BfResolvedTypeSet::EvaluateToVariant(LookupContext* ctx, BfExpression* expr, BfType*& outType)
|
BfVariant BfResolvedTypeSet::EvaluateToVariant(LookupContext* ctx, BfExpression* expr, BfType*& outType)
|
||||||
{
|
{
|
||||||
|
outType = NULL;
|
||||||
|
|
||||||
BfConstResolver constResolver(ctx->mModule);
|
BfConstResolver constResolver(ctx->mModule);
|
||||||
BfVariant variant = { BfTypeCode_None };
|
BfVariant variant = { BfTypeCode_None };
|
||||||
constResolver.mAllowGenericConstValue = true;
|
constResolver.mAllowGenericConstValue = true;
|
||||||
auto result = constResolver.Resolve(expr);
|
constResolver.mBfEvalExprFlags = BfEvalExprFlags_NoCast;
|
||||||
outType = result.mType;
|
constResolver.mExpectingType = ctx->mModule->GetPrimitiveType(BfTypeCode_Int64);
|
||||||
if (result)
|
auto result = constResolver.Resolve(expr);
|
||||||
{
|
if (result)
|
||||||
|
{
|
||||||
|
// Limit the types of constants to prevent duplicate values with different types - we don't want to hash a typeref with an int32
|
||||||
|
// when the constraint requirement is int64 (but we don't know that at hash time)
|
||||||
|
if ((result.mType->IsInteger()) && ((result.mType->mSize < 8) || (result.mType->GetTypeCode() == BfTypeCode_IntPtr)))
|
||||||
|
result = ctx->mModule->Cast(expr, result, ctx->mModule->GetPrimitiveType(BfTypeCode_Int64));
|
||||||
|
else if ((result.mType->IsFloat()) && (result.mType->mSize < 8))
|
||||||
|
result = ctx->mModule->Cast(expr, result, ctx->mModule->GetPrimitiveType(BfTypeCode_Double));
|
||||||
|
else if ((result.mType->IsChar()) && (result.mType->mSize < 4))
|
||||||
|
result = ctx->mModule->Cast(expr, result, ctx->mModule->GetPrimitiveType(BfTypeCode_Char32));
|
||||||
|
outType = result.mType;
|
||||||
|
|
||||||
if (result.mKind == BfTypedValueKind_GenericConstValue)
|
if (result.mKind == BfTypedValueKind_GenericConstValue)
|
||||||
{
|
{
|
||||||
return variant;
|
return variant;
|
||||||
|
@ -2784,18 +2797,6 @@ BfVariant BfResolvedTypeSet::EvaluateToVariant(LookupContext* ctx, BfExpression*
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
variant = ctx->mModule->TypedValueToVariant(expr, result, true);
|
variant = ctx->mModule->TypedValueToVariant(expr, result, true);
|
||||||
|
|
||||||
// Limit the types of constants to prevent duplicate values with different types - we don't want to hash a typeref with an int32
|
|
||||||
// when the constraint requirement is int64 (but we don't know that at hash time)
|
|
||||||
if (BfIRConstHolder::IsChar(variant.mTypeCode))
|
|
||||||
variant.mTypeCode = BfTypeCode_Char32;
|
|
||||||
else if (BfIRConstHolder::IsInt(variant.mTypeCode))
|
|
||||||
variant.mTypeCode = BfTypeCode_Int64;
|
|
||||||
else if (variant.mTypeCode == BfTypeCode_Float)
|
|
||||||
{
|
|
||||||
variant.mTypeCode = BfTypeCode_Double;
|
|
||||||
variant.mDouble = variant.mSingle;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return variant;
|
return variant;
|
||||||
|
|
|
@ -568,6 +568,7 @@ public:
|
||||||
virtual bool IsValueTypeOrValueTypePtr() { return false; }
|
virtual bool IsValueTypeOrValueTypePtr() { return false; }
|
||||||
virtual bool IsWrappableType() { return false; }
|
virtual bool IsWrappableType() { return false; }
|
||||||
virtual bool IsPrimitiveType() { return false; }
|
virtual bool IsPrimitiveType() { return false; }
|
||||||
|
virtual BfTypeCode GetTypeCode() { return BfTypeCode_None; }
|
||||||
virtual bool IsBoolean() { return false; }
|
virtual bool IsBoolean() { return false; }
|
||||||
virtual bool IsInteger() { return false; }
|
virtual bool IsInteger() { return false; }
|
||||||
virtual bool IsIntegral() { return false; }
|
virtual bool IsIntegral() { return false; }
|
||||||
|
@ -620,6 +621,7 @@ public:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual bool IsPrimitiveType() override { return true; }
|
virtual bool IsPrimitiveType() override { return true; }
|
||||||
|
virtual BfTypeCode GetTypeCode() override { return mTypeDef->mTypeCode; }
|
||||||
virtual bool IsWrappableType() override { return (mTypeDef->mTypeCode >= BfTypeCode_Boolean) && (mTypeDef->mTypeCode <= BfTypeCode_Double); }
|
virtual bool IsWrappableType() override { return (mTypeDef->mTypeCode >= BfTypeCode_Boolean) && (mTypeDef->mTypeCode <= BfTypeCode_Double); }
|
||||||
virtual BfPrimitiveType* ToPrimitiveType() override { return this; }
|
virtual BfPrimitiveType* ToPrimitiveType() override { return this; }
|
||||||
//virtual bool IsValueType() override { return mTypeDef->mTypeCode != BfTypeCode_None; }
|
//virtual bool IsValueType() override { return mTypeDef->mTypeCode != BfTypeCode_None; }
|
||||||
|
@ -1969,7 +1971,7 @@ public:
|
||||||
virtual BfPrimitiveType* ToPrimitiveType() override { return GetUnderlyingType()->ToPrimitiveType(); }
|
virtual BfPrimitiveType* ToPrimitiveType() override { return GetUnderlyingType()->ToPrimitiveType(); }
|
||||||
virtual bool HasWrappedRepresentation() override { return IsTypedPrimitive(); }
|
virtual bool HasWrappedRepresentation() override { return IsTypedPrimitive(); }
|
||||||
|
|
||||||
int GetEndingInstanceAlignment() { if (mInstSize % mInstAlign == 0) return mInstAlign; return mInstSize % mInstAlign; }
|
int GetEndingInstanceAlignment() { if (mInstSize % mInstAlign == 0) return mInstAlign; return mInstSize % mInstAlign; }
|
||||||
virtual bool HasTypeFailed() override { return mTypeFailed; }
|
virtual bool HasTypeFailed() override { return mTypeFailed; }
|
||||||
virtual bool IsReified() override { return mIsReified; }
|
virtual bool IsReified() override { return mIsReified; }
|
||||||
virtual bool NeedsExplicitAlignment() override { return !IsSizeAligned() || mIsPacked; }
|
virtual bool NeedsExplicitAlignment() override { return !IsSizeAligned() || mIsPacked; }
|
||||||
|
@ -1979,6 +1981,7 @@ public:
|
||||||
virtual bool IsSplattable() override { BF_ASSERT((mInstSize >= 0) || (!IsComposite())); return mIsSplattable; }
|
virtual bool IsSplattable() override { BF_ASSERT((mInstSize >= 0) || (!IsComposite())); return mIsSplattable; }
|
||||||
virtual int GetSplatCount() override;
|
virtual int GetSplatCount() override;
|
||||||
virtual bool IsTypeInstance() override { return true; }
|
virtual bool IsTypeInstance() override { return true; }
|
||||||
|
virtual BfTypeCode GetTypeCode() override { return mTypeDef->mTypeCode; }
|
||||||
virtual bool IsInterface() override { return mTypeDef->mTypeCode == BfTypeCode_Interface; }
|
virtual bool IsInterface() override { return mTypeDef->mTypeCode == BfTypeCode_Interface; }
|
||||||
virtual bool IsValueType() override { return (mTypeDef->mTypeCode == BfTypeCode_Struct) || (mTypeDef->mTypeCode == BfTypeCode_Enum); }
|
virtual bool IsValueType() override { return (mTypeDef->mTypeCode == BfTypeCode_Struct) || (mTypeDef->mTypeCode == BfTypeCode_Enum); }
|
||||||
virtual bool IsOpaque() override { return mTypeDef->mIsOpaque; }
|
virtual bool IsOpaque() override { return mTypeDef->mIsOpaque; }
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "BfResolvePass.h"
|
#include "BfResolvePass.h"
|
||||||
#include "MemReporter.h"
|
#include "MemReporter.h"
|
||||||
#include "BfIRCodeGen.h"
|
#include "BfIRCodeGen.h"
|
||||||
|
#include "BfIRBuilder.h"
|
||||||
|
|
||||||
#include "BeefySysLib/util/AllocDebug.h"
|
#include "BeefySysLib/util/AllocDebug.h"
|
||||||
|
|
||||||
|
@ -2300,6 +2301,20 @@ bool BfSystem::DoesLiteralFit(BfTypeCode typeCode, uint64 value)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BfSystem::DoesLiteralFit(BfTypeCode typeCode, const BfVariant& variant)
|
||||||
|
{
|
||||||
|
if ((BfIRConstHolder::IsIntable(typeCode)) && (BfIRConstHolder::IsIntable(variant.mTypeCode)))
|
||||||
|
{
|
||||||
|
if (BfIRConstHolder::IsSigned(variant.mTypeCode))
|
||||||
|
return DoesLiteralFit(typeCode, variant.mInt64);
|
||||||
|
else
|
||||||
|
return DoesLiteralFit(typeCode, variant.mUInt64);
|
||||||
|
}
|
||||||
|
if ((BfIRConstHolder::IsFloat(typeCode)) && (BfIRConstHolder::IsFloat(variant.mTypeCode)))
|
||||||
|
return true;
|
||||||
|
return typeCode == variant.mTypeCode;
|
||||||
|
}
|
||||||
|
|
||||||
BfParser* BfSystem::CreateParser(BfProject* bfProject)
|
BfParser* BfSystem::CreateParser(BfProject* bfProject)
|
||||||
{
|
{
|
||||||
AutoCrit crit(mDataLock);
|
AutoCrit crit(mDataLock);
|
||||||
|
|
|
@ -1630,6 +1630,7 @@ public:
|
||||||
void CreateBasicTypes();
|
void CreateBasicTypes();
|
||||||
bool DoesLiteralFit(BfTypeCode typeCode, int64 value);
|
bool DoesLiteralFit(BfTypeCode typeCode, int64 value);
|
||||||
bool DoesLiteralFit(BfTypeCode typeCode, uint64 value);
|
bool DoesLiteralFit(BfTypeCode typeCode, uint64 value);
|
||||||
|
bool DoesLiteralFit(BfTypeCode typeCode, const BfVariant& variant);
|
||||||
BfParser* CreateParser(BfProject* bfProject);
|
BfParser* CreateParser(BfProject* bfProject);
|
||||||
BfCompiler* CreateCompiler(bool isResolveOnly);
|
BfCompiler* CreateCompiler(bool isResolveOnly);
|
||||||
BfProject* GetProject(const StringImpl& projName);
|
BfProject* GetProject(const StringImpl& projName);
|
||||||
|
|
|
@ -19,14 +19,14 @@ namespace Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ClassB<T, TSize> where TSize : const int
|
class ClassB<T, TSize> where TSize : const int8
|
||||||
{
|
{
|
||||||
ClassA<T, TSize> mVal = new ClassA<T, const TSize>() ~ delete _;
|
ClassA<T, TSize> mVal = new ClassA<T, const TSize>() ~ delete _;
|
||||||
var mVal2 = new ClassA<T, const TSize + 100>() ~ delete _;
|
var mVal2 = new ClassA<T, const TSize + 100>() ~ delete _;
|
||||||
|
|
||||||
public int GetVal()
|
public int GetVal()
|
||||||
{
|
{
|
||||||
return mVal.GetVal();
|
return mVal.GetVal();
|
||||||
}
|
}
|
||||||
|
|
||||||
public int GetVal2()
|
public int GetVal2()
|
||||||
|
@ -55,6 +55,10 @@ namespace Tests
|
||||||
Test.Assert(cb.GetVal() == 123);
|
Test.Assert(cb.GetVal() == 123);
|
||||||
Test.Assert(cb.GetVal2() == 223);
|
Test.Assert(cb.GetVal2() == 223);
|
||||||
|
|
||||||
|
ClassB<float, const -45> cb2 = scope .();
|
||||||
|
Test.Assert(cb2.GetVal() == -45);
|
||||||
|
Test.Assert(cb2.GetVal2() == 55);
|
||||||
|
|
||||||
ClassC<const EnumA.A> cc = scope .();
|
ClassC<const EnumA.A> cc = scope .();
|
||||||
Test.Assert(cc.Test() == 1);
|
Test.Assert(cc.Test() == 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -499,6 +499,10 @@ namespace Tests
|
||||||
const int32 c1 = 1;
|
const int32 c1 = 1;
|
||||||
int i0 = 0;
|
int i0 = 0;
|
||||||
var tVal = Vector2((i0 % c0) * (c1 + c1), 1);
|
var tVal = Vector2((i0 % c0) * (c1 + c1), 1);
|
||||||
|
|
||||||
|
int8 a = 123;
|
||||||
|
int32 b = a + 100;
|
||||||
|
Test.Assert(b == 223);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct IntStruct
|
struct IntStruct
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue