1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 03:52:19 +02:00

Circular data detection fix, TypeDataChanged rebuild fix

This commit is contained in:
Brian Fiete 2021-11-03 07:07:49 -07:00
parent 617cdcbede
commit 5674bf80c0
4 changed files with 80 additions and 53 deletions

View file

@ -37,7 +37,7 @@ namespace System
public static extern String CallerProject; public static extern String CallerProject;
[LinkName("#CallerExpression")] [LinkName("#CallerExpression")]
public static extern String[Int32.MaxValue] CallerExpression; public static extern String[0x0FFFFFFF] CallerExpression;
[LinkName("#ProjectName")] [LinkName("#ProjectName")]
public static extern String ProjectName; public static extern String ProjectName;

View file

@ -21,7 +21,7 @@ namespace System
public static extern String CallerProject; public static extern String CallerProject;
[LinkName("#CallerExpression")] [LinkName("#CallerExpression")]
public static extern String[Int32.MaxValue] CallerExpression; public static extern String[0x0FFFFFFF] CallerExpression;
[LinkName("#ProjectName")] [LinkName("#ProjectName")]
public static extern String ProjectName; public static extern String ProjectName;

View file

@ -1154,11 +1154,6 @@ void BfContext::TypeDataChanged(BfDependedType* dType, bool isNonStaticDataChang
auto dependentType = depItr.mKey; auto dependentType = depItr.mKey;
auto dependencyFlags = depItr.mValue.mFlags; auto dependencyFlags = depItr.mValue.mFlags;
if (dependentType->mRevision == mCompiler->mRevision)
{
continue;
}
auto dependentDType = dependentType->ToDependedType(); auto dependentDType = dependentType->ToDependedType();
if (dependentDType != NULL) if (dependentDType != NULL)
{ {
@ -1201,13 +1196,14 @@ void BfContext::TypeDataChanged(BfDependedType* dType, bool isNonStaticDataChang
{ {
TypeDataChanged(dependentDType, false); TypeDataChanged(dependentDType, false);
// The ConstValue dependency may be that dependentType used one of our consts as // The ConstValue dependency may be that dependentType used one of our consts as
// a default value to a method param, so assume callsites need rebuilding // a default value to a method param, so assume callsites need rebuilding
if (dependentTypeInstance != NULL) if (dependentTypeInstance != NULL)
TypeMethodSignaturesChanged(dependentTypeInstance); TypeMethodSignaturesChanged(dependentTypeInstance);
} }
if (dependentType->mRevision != mCompiler->mRevision)
{
// We need to include DependencyFlag_ParamOrReturnValue because it could be a struct that changes its splatting ability // We need to include DependencyFlag_ParamOrReturnValue because it could be a struct that changes its splatting ability
// We can't ONLY check against structs, though, because a type could change from a class to a struct // We can't ONLY check against structs, though, because a type could change from a class to a struct
if (dependencyFlags & if (dependencyFlags &
@ -1218,13 +1214,18 @@ void BfContext::TypeDataChanged(BfDependedType* dType, bool isNonStaticDataChang
RebuildType(dependentType); RebuildType(dependentType);
} }
} }
}
else else
{
if (dependentType->mRevision != mCompiler->mRevision)
{ {
// Not a type instance, probably something like a sized array // Not a type instance, probably something like a sized array
RebuildType(dependentType); RebuildType(dependentType);
} }
} }
}
if (dType->mRevision != mCompiler->mRevision)
RebuildType(dType); RebuildType(dType);
} }
@ -1242,11 +1243,8 @@ void BfContext::TypeMethodSignaturesChanged(BfTypeInstance* typeInst)
auto dependentType = depItr.mKey; auto dependentType = depItr.mKey;
auto dependencyFlags = depItr.mValue.mFlags; auto dependencyFlags = depItr.mValue.mFlags;
if (dependentType->mRevision == mCompiler->mRevision) if (dependentType->mRevision != mCompiler->mRevision)
{ {
continue;
}
// We don't need to cascade rebuilding for method-based usage - just rebuild the type directly (unlike TypeDataChanged, which cascades) // We don't need to cascade rebuilding for method-based usage - just rebuild the type directly (unlike TypeDataChanged, which cascades)
if ((dependencyFlags & BfDependencyMap::DependencyFlag_Calls) || if ((dependencyFlags & BfDependencyMap::DependencyFlag_Calls) ||
(dependencyFlags & BfDependencyMap::DependencyFlag_VirtualCall) || (dependencyFlags & BfDependencyMap::DependencyFlag_VirtualCall) ||
@ -1260,6 +1258,7 @@ void BfContext::TypeMethodSignaturesChanged(BfTypeInstance* typeInst)
} }
} }
} }
}
void BfContext::TypeInlineMethodInternalsChanged(BfTypeInstance* typeInst) void BfContext::TypeInlineMethodInternalsChanged(BfTypeInstance* typeInst)
{ {
@ -1271,8 +1270,11 @@ void BfContext::TypeInlineMethodInternalsChanged(BfTypeInstance* typeInst)
for (auto& depItr : typeInst->mDependencyMap) for (auto& depItr : typeInst->mDependencyMap)
{ {
auto dependentType = depItr.mKey; auto dependentType = depItr.mKey;
auto dependencyFlags = depItr.mValue.mFlags; auto dependencyFlags = depItr.mValue.mFlags;
if (dependentType->mRevision != mCompiler->mRevision)
{
// We don't need to cascade rebuilding for method-based usage - just rebuild the type directly (unlike TypeDataChanged, which cascades) // We don't need to cascade rebuilding for method-based usage - just rebuild the type directly (unlike TypeDataChanged, which cascades)
if ((dependencyFlags & BfDependencyMap::DependencyFlag_InlinedCall) != 0) if ((dependencyFlags & BfDependencyMap::DependencyFlag_InlinedCall) != 0)
{ {
@ -1280,6 +1282,7 @@ void BfContext::TypeInlineMethodInternalsChanged(BfTypeInstance* typeInst)
} }
} }
} }
}
void BfContext::TypeConstEvalChanged(BfTypeInstance* typeInst) void BfContext::TypeConstEvalChanged(BfTypeInstance* typeInst)
{ {
@ -1299,6 +1302,7 @@ void BfContext::TypeConstEvalChanged(BfTypeInstance* typeInst)
auto depTypeInst = dependentType->ToTypeInstance(); auto depTypeInst = dependentType->ToTypeInstance();
if (depTypeInst != NULL) if (depTypeInst != NULL)
TypeConstEvalChanged(depTypeInst); TypeConstEvalChanged(depTypeInst);
if (dependentType->mRevision != mCompiler->mRevision)
RebuildType(dependentType); RebuildType(dependentType);
} }
else if ((dependencyFlags & BfDependencyMap::DependencyFlag_ConstEvalConstField) != 0) else if ((dependencyFlags & BfDependencyMap::DependencyFlag_ConstEvalConstField) != 0)
@ -1306,6 +1310,7 @@ void BfContext::TypeConstEvalChanged(BfTypeInstance* typeInst)
auto depTypeInst = dependentType->ToTypeInstance(); auto depTypeInst = dependentType->ToTypeInstance();
if (depTypeInst != NULL) if (depTypeInst != NULL)
TypeConstEvalFieldChanged(depTypeInst); TypeConstEvalFieldChanged(depTypeInst);
if (dependentType->mRevision != mCompiler->mRevision)
RebuildType(dependentType); RebuildType(dependentType);
} }
} }
@ -1328,6 +1333,7 @@ void BfContext::TypeConstEvalFieldChanged(BfTypeInstance* typeInst)
auto depTypeInst = dependentType->ToTypeInstance(); auto depTypeInst = dependentType->ToTypeInstance();
if (depTypeInst != NULL) if (depTypeInst != NULL)
TypeConstEvalFieldChanged(depTypeInst); TypeConstEvalFieldChanged(depTypeInst);
if (dependentType->mRevision != mCompiler->mRevision)
RebuildType(dependentType); RebuildType(dependentType);
} }
} }

View file

@ -900,7 +900,9 @@ void BfModule::TypeFailed(BfTypeInstance* typeInstance)
bool BfModule::CheckCircularDataError() bool BfModule::CheckCircularDataError()
{ {
bool hadError = false; // Find two loops of mCurTypeInstance. Just finding one loop can give some false errors.
BfTypeState* circularTypeStateEnd = NULL;
int checkIdx = 0; int checkIdx = 0;
auto checkTypeState = mContext->mCurTypeState; auto checkTypeState = mContext->mCurTypeState;
@ -908,7 +910,7 @@ bool BfModule::CheckCircularDataError()
while (true) while (true)
{ {
if (checkTypeState == NULL) if (checkTypeState == NULL)
return hadError; return false;
if (checkTypeState->mResolveKind == BfTypeState::ResolveKind_UnionInnerType) if (checkTypeState->mResolveKind == BfTypeState::ResolveKind_UnionInnerType)
{ {
@ -919,30 +921,38 @@ bool BfModule::CheckCircularDataError()
if (isPreBaseCheck) if (isPreBaseCheck)
{ {
if (checkTypeState->mPopulateType != BfPopulateType_Declaration) if (checkTypeState->mPopulateType != BfPopulateType_Declaration)
return hadError; return false;
} }
else else
{ {
if (checkTypeState->mPopulateType == BfPopulateType_Declaration) if (checkTypeState->mPopulateType == BfPopulateType_Declaration)
return hadError; return false;
if ((checkIdx > 0) && (checkTypeState->mCurBaseTypeRef == NULL) && (checkTypeState->mCurAttributeTypeRef == NULL) && (checkTypeState->mCurFieldDef == NULL) && if ((checkIdx > 0) && (checkTypeState->mCurBaseTypeRef == NULL) && (checkTypeState->mCurAttributeTypeRef == NULL) && (checkTypeState->mCurFieldDef == NULL) &&
((checkTypeState->mType == NULL) || (checkTypeState->mType->IsTypeInstance()))) ((checkTypeState->mType == NULL) || (checkTypeState->mType->IsTypeInstance())))
return hadError; return false;
} }
if ((checkTypeState->mType == mCurTypeInstance) && (checkIdx > 0)) if ((checkTypeState->mType == mCurTypeInstance) && (checkIdx > 0))
{
if (circularTypeStateEnd == NULL)
circularTypeStateEnd = checkTypeState;
else
break; break;
}
checkTypeState = checkTypeState->mPrevState; checkTypeState = checkTypeState->mPrevState;
checkIdx++; checkIdx++;
} }
bool hadError = false;
checkTypeState = mContext->mCurTypeState->mPrevState; checkTypeState = mContext->mCurTypeState->mPrevState;
while (true) while (true)
{ {
if (checkTypeState == NULL) if (checkTypeState == NULL)
return hadError; return hadError;
if (checkTypeState == circularTypeStateEnd)
return hadError;
if (checkTypeState->mResolveKind == BfTypeState::ResolveKind_UnionInnerType) if (checkTypeState->mResolveKind == BfTypeState::ResolveKind_UnionInnerType)
{ {
// Skip over this to actual data references // Skip over this to actual data references
@ -1223,6 +1233,15 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
if (arrayType->mElementCount > 0) if (arrayType->mElementCount > 0)
{ {
arrayType->mSize = (int)(arrayType->mElementType->GetStride() * arrayType->mElementCount); arrayType->mSize = (int)(arrayType->mElementType->GetStride() * arrayType->mElementCount);
if (arrayType->mElementType->mSize > 0)
{
int64 maxElements = 0x7FFFFFFF / arrayType->mElementType->GetStride();
if (arrayType->mElementCount > maxElements)
{
Fail(StrFormat("Array size overflow: %s", TypeToString(arrayType).c_str()));
arrayType->mSize = 0x7FFFFFFF;
}
}
arrayType->mAlign = std::max((int32)arrayType->mElementType->mAlign, 1); arrayType->mAlign = std::max((int32)arrayType->mElementType->mAlign, 1);
} }
else if (arrayType->mElementCount < 0) else if (arrayType->mElementCount < 0)
@ -1237,6 +1256,8 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType
arrayType->mAlign = 1; arrayType->mAlign = 1;
} }
BF_ASSERT(arrayType->mSize >= 0);
if (!typeFailed) if (!typeFailed)
arrayType->mWantsGCMarking = elementType->WantsGCMarking(); arrayType->mWantsGCMarking = elementType->WantsGCMarking();
resolvedTypeRef->mDefineState = BfTypeDefineState_DefinedAndMethodsSlotted; resolvedTypeRef->mDefineState = BfTypeDefineState_DefinedAndMethodsSlotted;
@ -4874,7 +4895,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
FinishGenericParams(resolvedTypeRef); FinishGenericParams(resolvedTypeRef);
} }
if (populateType == BfPopulateType_Data) if (populateType <= BfPopulateType_Data)
return; return;
disableYield.Release(); disableYield.Release();