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:
parent
617cdcbede
commit
5674bf80c0
4 changed files with 80 additions and 53 deletions
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue