mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Fixed deferred targeted boxing, DisableChecks, sized array generics
This commit is contained in:
parent
a94b52ff58
commit
b640bf9d5e
8 changed files with 189 additions and 89 deletions
|
@ -382,6 +382,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
|
|||
mCReprAttributeTypeDef = NULL;
|
||||
mAlignAttributeTypeDef = NULL;
|
||||
mNoDiscardAttributeTypeDef = NULL;
|
||||
mDisableChecksAttributeTypeDef = NULL;
|
||||
mDisableObjectAccessChecksAttributeTypeDef = NULL;
|
||||
mDbgRawAllocDataTypeDef = NULL;
|
||||
mDeferredCallTypeDef = NULL;
|
||||
|
@ -5835,6 +5836,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
|
|||
mCReprAttributeTypeDef = _GetRequiredType("System.CReprAttribute");
|
||||
mAlignAttributeTypeDef = _GetRequiredType("System.AlignAttribute");
|
||||
mNoDiscardAttributeTypeDef = _GetRequiredType("System.NoDiscardAttribute");
|
||||
mDisableChecksAttributeTypeDef = _GetRequiredType("System.DisableChecksAttribute");
|
||||
mDisableObjectAccessChecksAttributeTypeDef = _GetRequiredType("System.DisableObjectAccessChecksAttribute");
|
||||
mDbgRawAllocDataTypeDef = _GetRequiredType("System.DbgRawAllocData");
|
||||
mDeferredCallTypeDef = _GetRequiredType("System.DeferredCall");
|
||||
|
|
|
@ -380,6 +380,7 @@ public:
|
|||
BfTypeDef* mCReprAttributeTypeDef;
|
||||
BfTypeDef* mAlignAttributeTypeDef;
|
||||
BfTypeDef* mNoDiscardAttributeTypeDef;
|
||||
BfTypeDef* mDisableChecksAttributeTypeDef;
|
||||
BfTypeDef* mDisableObjectAccessChecksAttributeTypeDef;
|
||||
BfTypeDef* mFriendAttributeTypeDef;
|
||||
BfTypeDef* mCheckedAttributeTypeDef;
|
||||
|
|
|
@ -2396,7 +2396,7 @@ void BfExprEvaluator::Visit(BfCaseExpression* caseExpr)
|
|||
}
|
||||
}
|
||||
|
||||
bool isPayloadEnum = caseValAddr.mType->IsPayloadEnum();
|
||||
bool isPayloadEnum = (caseValAddr.mType != NULL) && (caseValAddr.mType->IsPayloadEnum());
|
||||
auto tupleExpr = BfNodeDynCast<BfTupleExpression>(caseExpr->mCaseExpression);
|
||||
|
||||
if ((caseValAddr) &&
|
||||
|
@ -5172,7 +5172,12 @@ BfTypedValue BfExprEvaluator::CreateCall(BfAstNode* targetSrc, const BfTypedValu
|
|||
|
||||
if ((argValue) && (arg != NULL))
|
||||
{
|
||||
//
|
||||
{
|
||||
SetAndRestoreValue<BfScopeData*> prevScopeData(mModule->mCurMethodState->mOverrideScope, boxScopeData);
|
||||
argValue = mModule->Cast(arg, argValue, wantType);
|
||||
}
|
||||
|
||||
if (!argValue)
|
||||
{
|
||||
failed = true;
|
||||
|
@ -7368,8 +7373,6 @@ void BfExprEvaluator::LookupQualifiedName(BfAstNode* nameNode, BfIdentifierNode*
|
|||
prevTarget = mPropTarget;
|
||||
}
|
||||
}
|
||||
/*if ((mResult) || (mPropDef != NULL))
|
||||
break;*/
|
||||
}
|
||||
|
||||
if (mPropDef != NULL)
|
||||
|
@ -13738,6 +13741,33 @@ void BfExprEvaluator::CheckPropFail(BfMethodDef* propMethodDef, BfMethodInstance
|
|||
BfTypedValue BfExprEvaluator::GetResult(bool clearResult, bool resolveGenericType)
|
||||
{
|
||||
if ((!mResult) && (mPropDef != NULL))
|
||||
{
|
||||
bool handled = false;
|
||||
if (mPropTarget.mType->IsGenericTypeInstance())
|
||||
{
|
||||
auto genericTypeInst = (BfGenericTypeInstance*)mPropTarget.mType;
|
||||
if (genericTypeInst->mTypeDef == mModule->mCompiler->mSizedArrayTypeDef)
|
||||
{
|
||||
if (mPropDef->mName == "Count")
|
||||
{
|
||||
auto sizedType = genericTypeInst->mTypeGenericArguments[1];
|
||||
if (sizedType->IsConstExprValue())
|
||||
{
|
||||
auto constExprType = (BfConstExprValueType*)sizedType;
|
||||
mResult = BfTypedValue(mModule->GetConstValue(constExprType->mValue.mInt64), mModule->GetPrimitiveType(BfTypeCode_IntPtr));
|
||||
handled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
BF_ASSERT(mModule->mCurMethodInstance->mIsUnspecialized);
|
||||
mResult = BfTypedValue(mModule->mBfIRBuilder->GetUndefConstValue(BfTypeCode_IntPtr), mModule->GetPrimitiveType(BfTypeCode_IntPtr));
|
||||
handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled)
|
||||
{
|
||||
BfMethodDef* matchedMethod = GetPropertyMethodDef(mPropDef, BfMethodType_PropertyGetter, mPropCheckedKind);
|
||||
if (matchedMethod == NULL)
|
||||
|
@ -13806,6 +13836,7 @@ BfTypedValue BfExprEvaluator::GetResult(bool clearResult, bool resolveGenericTyp
|
|||
BF_ASSERT(!mResult.mType->IsRef());
|
||||
}
|
||||
}
|
||||
}
|
||||
mPropDef = NULL;
|
||||
mPropDefBypassVirtual = false;
|
||||
mIndexerValues.clear();
|
||||
|
@ -15838,6 +15869,10 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
|
|||
return;
|
||||
}
|
||||
|
||||
bool wantsChecks = checkedKind == BfCheckedKind_Checked;
|
||||
if (checkedKind == BfCheckedKind_NotSet)
|
||||
wantsChecks = mModule->GetDefaultCheckedKind() == BfCheckedKind_Checked;
|
||||
|
||||
//target.mType = mModule->ResolveGenericType(target.mType);
|
||||
if (target.mType->IsVar())
|
||||
{
|
||||
|
@ -15914,7 +15949,7 @@ void BfExprEvaluator::Visit(BfIndexerExpression* indexerExpr)
|
|||
return;
|
||||
}
|
||||
}
|
||||
else if (mModule->HasCompiledOutput())
|
||||
else if ((mModule->HasCompiledOutput()) && (wantsChecks))
|
||||
{
|
||||
if (checkedKind == BfCheckedKind_NotSet)
|
||||
checkedKind = mModule->GetDefaultCheckedKind();
|
||||
|
|
|
@ -2495,18 +2495,10 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
|
|||
errorString += StrFormat("\n while compiling project '%s'", mProject->mName.c_str());
|
||||
}
|
||||
|
||||
if ((mCurTypeInstance != NULL) && (mCurMethodState != NULL))
|
||||
if (mCurTypeInstance != NULL)
|
||||
{
|
||||
auto checkMethodState = mCurMethodState;
|
||||
while (checkMethodState != NULL)
|
||||
auto _CheckMethodInstance = [&](BfMethodInstance* methodInstance)
|
||||
{
|
||||
auto methodInstance = checkMethodState->mMethodInstance;
|
||||
if (methodInstance == NULL)
|
||||
{
|
||||
checkMethodState = checkMethodState->mPrevMethodState;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Propogatea the fail all the way to the main method (assuming we're in a local method or lambda)
|
||||
methodInstance->mHasFailed = true;
|
||||
|
||||
|
@ -2516,7 +2508,7 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
|
|||
//auto unspecializedMethod = &mCurMethodInstance->mMethodInstanceGroup->mMethodSpecializationMap.begin()->second;
|
||||
auto unspecializedMethod = methodInstance->mMethodInstanceGroup->mDefault;
|
||||
if (unspecializedMethod->mHasFailed)
|
||||
return NULL; // At least SOME error has already been reported
|
||||
return false; // At least SOME error has already been reported
|
||||
}
|
||||
|
||||
if (isSpecializedMethod)
|
||||
|
@ -2536,8 +2528,30 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
|
|||
errorString += StrFormat("\n while specializing type '%s'", TypeToString(mCurTypeInstance).c_str());
|
||||
isWhileSpecializing = true;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
if (mCurMethodState != NULL)
|
||||
{
|
||||
auto checkMethodState = mCurMethodState;
|
||||
while (checkMethodState != NULL)
|
||||
{
|
||||
auto methodInstance = checkMethodState->mMethodInstance;
|
||||
if (methodInstance == NULL)
|
||||
{
|
||||
checkMethodState = checkMethodState->mPrevMethodState;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!_CheckMethodInstance(methodInstance))
|
||||
return NULL;
|
||||
checkMethodState = checkMethodState->mPrevMethodState;
|
||||
}
|
||||
}
|
||||
else if (mCurMethodInstance != NULL)
|
||||
{
|
||||
if (!_CheckMethodInstance(mCurMethodInstance))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Keep in mind that all method specializations with generic type instances as its method generic params
|
||||
|
@ -2553,6 +2567,12 @@ BfError* BfModule::Fail(const StringImpl& error, BfAstNode* refNode, bool isPers
|
|||
}
|
||||
}
|
||||
|
||||
if ((!isWhileSpecializing) && ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType())))
|
||||
{
|
||||
errorString += StrFormat("\n while specializing type '%s'", TypeToString(mCurTypeInstance).c_str());
|
||||
isWhileSpecializing = true;
|
||||
}
|
||||
|
||||
if (!mHadBuildError)
|
||||
mHadBuildError = true;
|
||||
|
||||
|
@ -3028,6 +3048,8 @@ BfModuleOptions BfModule::GetModuleOptions()
|
|||
|
||||
BfCheckedKind BfModule::GetDefaultCheckedKind()
|
||||
{
|
||||
if ((mCurMethodState != NULL) && (mCurMethodState->mDisableChecks))
|
||||
return BfCheckedKind_Unchecked;
|
||||
bool runtimeChecks = mCompiler->mOptions.mRuntimeChecks;
|
||||
auto typeOptions = GetTypeOptions();
|
||||
if (typeOptions != NULL)
|
||||
|
@ -16922,6 +16944,8 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
|||
auto customAttributes = methodInstance->GetCustomAttributes();
|
||||
if ((customAttributes != NULL) && (customAttributes->Contains(mCompiler->mDisableObjectAccessChecksAttributeTypeDef)))
|
||||
mCurMethodState->mIgnoreObjectAccessCheck = true;
|
||||
if ((customAttributes != NULL) && (customAttributes->Contains(mCompiler->mDisableChecksAttributeTypeDef)))
|
||||
mCurMethodState->mDisableChecks = true;
|
||||
|
||||
if ((methodDef->mMethodType == BfMethodType_CtorNoBody) && (!methodDef->mIsStatic) &&
|
||||
((methodInstance->mChainType == BfMethodChainType_ChainHead) || (methodInstance->mChainType == BfMethodChainType_None)))
|
||||
|
|
|
@ -899,6 +899,7 @@ public:
|
|||
int mBlockNestLevel; // 0 = top level
|
||||
bool mIsEmbedded; // Is an embedded statement (ie: if () stmt) not wrapped in a block
|
||||
bool mIgnoreObjectAccessCheck;
|
||||
bool mDisableChecks;
|
||||
BfMixinState* mMixinState;
|
||||
BfClosureState* mClosureState;
|
||||
BfDeferredCallEmitState* mDeferredCallEmitState;
|
||||
|
@ -910,6 +911,7 @@ public:
|
|||
BfScopeData mHeadScope;
|
||||
BfScopeData* mCurScope;
|
||||
BfScopeData* mTailScope; // Usually equals mCurScope
|
||||
BfScopeData* mOverrideScope;
|
||||
TempKind mTempKind; // Used for var inference, etc
|
||||
bool mInDeferredBlock;
|
||||
bool mHadReturn;
|
||||
|
@ -942,6 +944,7 @@ public:
|
|||
mHeadScope.mIsScopeHead = true;
|
||||
mCurScope = &mHeadScope;
|
||||
mTailScope = &mHeadScope;
|
||||
mOverrideScope = NULL;
|
||||
mHadReturn = false;
|
||||
mLeftBlockUncond = false;
|
||||
mLeftBlockCond = false;
|
||||
|
@ -956,6 +959,7 @@ public:
|
|||
mNoBind = false;
|
||||
mIsEmbedded = false;
|
||||
mIgnoreObjectAccessCheck = false;
|
||||
mDisableChecks = false;
|
||||
mInConditionalBlock = false;
|
||||
mAllowUinitReads = false;
|
||||
mCancelledDeferredCall = false;
|
||||
|
|
|
@ -4338,10 +4338,19 @@ BfTypeInstance* BfModule::GetWrappedStructType(BfType* type, bool allowSpecializ
|
|||
{
|
||||
if (allowSpecialized)
|
||||
{
|
||||
if (type->IsUnknownSizedArray())
|
||||
{
|
||||
BfUnknownSizedArrayType* sizedArrayType = (BfUnknownSizedArrayType*)type;
|
||||
BfTypeVector typeVector;
|
||||
typeVector.Add(sizedArrayType->mElementType);
|
||||
typeVector.Add(sizedArrayType->mElementCountSource);
|
||||
return ResolveTypeDef(mCompiler->mSizedArrayTypeDef, typeVector, BfPopulateType_Data)->ToTypeInstance();
|
||||
}
|
||||
|
||||
BfSizedArrayType* sizedArrayType = (BfSizedArrayType*)type;
|
||||
BfTypeVector typeVector;
|
||||
typeVector.Add(sizedArrayType->mElementType);
|
||||
auto sizeValue = BfTypedValue(GetConstValue(sizedArrayType->mElementCount), GetPrimitiveType(BfTypeCode_IntPtr));
|
||||
auto sizeValue = BfTypedValue(GetConstValue(BF_MAX(sizedArrayType->mElementCount, 0)), GetPrimitiveType(BfTypeCode_IntPtr));
|
||||
typeVector.Add(CreateConstExprValueType(sizeValue));
|
||||
return ResolveTypeDef(mCompiler->mSizedArrayTypeDef, typeVector, BfPopulateType_Data)->ToTypeInstance();
|
||||
}
|
||||
|
@ -9038,7 +9047,12 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
|||
{
|
||||
BfScopeData* scopeData = NULL;
|
||||
if (mCurMethodState != NULL)
|
||||
{
|
||||
if (mCurMethodState->mOverrideScope)
|
||||
scopeData = mCurMethodState->mOverrideScope;
|
||||
else
|
||||
scopeData = mCurMethodState->mCurScope;
|
||||
}
|
||||
|
||||
if ((castFlags & BfCastFlags_WarnOnBox) != 0)
|
||||
{
|
||||
|
|
|
@ -2155,8 +2155,8 @@ public:
|
|||
|
||||
virtual bool IsDependentOnUnderlyingType() override { return true; }
|
||||
virtual BfType* GetUnderlyingType() override { return mElementType; }
|
||||
virtual bool IsUnspecializedType() override { return mElementType->IsUnspecializedType(); }
|
||||
virtual bool IsUnspecializedTypeVariation() override { return mElementType->IsUnspecializedTypeVariation(); }
|
||||
virtual bool IsUnspecializedType() override { return mElementType->IsUnspecializedType() || mElementCountSource->IsUnspecializedType(); }
|
||||
virtual bool IsUnspecializedTypeVariation() override { return mElementType->IsUnspecializedTypeVariation() || mElementCountSource->IsUnspecializedTypeVariation(); }
|
||||
virtual bool CanBeValuelessType() override { return true; }
|
||||
// Leave the default "zero sized" definition
|
||||
//virtual bool IsValuelessType() override { return mElementType->IsValuelessType(); }
|
||||
|
|
|
@ -42,4 +42,24 @@ namespace Tests
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
class ConstGenerics
|
||||
{
|
||||
public static float GetSum<TCount>(float[TCount] vals) where TCount : const int
|
||||
{
|
||||
float total = 0;
|
||||
for (int i < vals.Count)
|
||||
total += vals[i];
|
||||
return total;
|
||||
}
|
||||
|
||||
[Test]
|
||||
public static void TestBasics()
|
||||
{
|
||||
float[5] fVals = .(10, 20, 30, 40, 50);
|
||||
|
||||
float totals = GetSum(fVals);
|
||||
Test.Assert(totals == 10+20+30+40+50);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue