1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 04:22:20 +02:00

IOnTypeInit + IOnTypeDone combo with IOnFieldInit/IOnMethodInit

This commit is contained in:
Brian Fiete 2025-02-22 12:07:31 -08:00
parent a5b032cc39
commit b3cf2a0d04

View file

@ -2498,191 +2498,221 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
{ {
for (auto& customAttribute : customAttributes->mAttributes) for (auto& customAttribute : customAttributes->mAttributes)
{ {
if ((customAttribute.mDeclaringType->IsExtension()) && (typeInstance->IsGenericTypeInstance()) && (!typeInstance->IsUnspecializedTypeVariation()))
{
if (!typeInstance->IsTypeMemberIncluded(customAttribute.mDeclaringType, typeInstance->mTypeDef, this))
continue;
}
auto attrType = customAttribute.mType;
BfMethodInstance* methodInstance = NULL;
bool isFieldApply = false; bool isFieldApply = false;
BfIRValue irValue; bool hasFieldApply = false;
int checkDepth = 0; bool hasTypeApply = false;
auto checkAttrType = attrType;
while (checkAttrType != NULL) for (int pass = 0; pass < 2; pass++)
{ {
mContext->mUnreifiedModule->PopulateType(checkAttrType, BfPopulateType_DataAndMethods); if (pass == 1)
if (checkAttrType->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted)
break;
for (auto& ifaceEntry : checkAttrType->mInterfaces)
{ {
isFieldApply = false; if ((hasFieldApply) && (hasTypeApply))
isFieldApply = (ceEmitContext != NULL) && (fieldInstance != NULL) && (ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIOnFieldInitTypeDef));
if ((isFieldApply) ||
((ceEmitContext != NULL) && (ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIComptimeTypeApply))) ||
((ceEmitContext != NULL) && (ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIOnTypeInitTypeDef))) ||
((ceEmitContext == NULL) && (ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIOnTypeDoneTypeDef))))
{ {
// Passes // Keep going - do the field apply now
} }
else else
continue; break;
prevAttrInstances.TryGetValue(checkAttrType, &irValue);
methodInstance = checkAttrType->mInterfaceMethodTable[ifaceEntry.mStartInterfaceTableIdx].mMethodRef;
break;
} }
if (methodInstance != NULL)
break;
checkAttrType = checkAttrType->mBaseType; if ((customAttribute.mDeclaringType->IsExtension()) && (typeInstance->IsGenericTypeInstance()) && (!typeInstance->IsUnspecializedTypeVariation()))
checkDepth++;
}
if (methodInstance == NULL)
continue;
SetAndRestoreValue<CeEmitContext*> prevEmitContext(mCompiler->mCeMachine->mCurEmitContext, ceEmitContext);
auto ceContext = mCompiler->mCeMachine->AllocContext();
defer({ mCompiler->mCeMachine->ReleaseContext(ceContext); });
BfIRValue attrVal =ceContext->CreateAttribute(customAttribute.mRef, this, typeInstance->mConstHolder, &customAttribute);
for (int baseIdx = 0; baseIdx < checkDepth; baseIdx++)
attrVal = mBfIRBuilder->CreateExtractValue(attrVal, 0);
SizedArray<BfIRValue, 1> args;
if (!attrType->IsValuelessType())
args.Add(attrVal);
if (isFieldApply)
{
auto fieldInfoType = ResolveTypeDef(mCompiler->mReflectFieldInfoTypeDef);
if (fieldInfoType != NULL)
{ {
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true); if (!typeInstance->IsTypeMemberIncluded(customAttribute.mDeclaringType, typeInstance->mTypeDef, this))
SizedArray<BfIRValue, 9> fieldData = continue;
{
mBfIRBuilder->CreateConstAggZero(mBfIRBuilder->MapType(fieldInfoType->ToTypeInstance()->mBaseType, BfIRPopulateType_Identity)),
mBfIRBuilder->CreateTypeOf(mCurTypeInstance), // mTypeInstance
CreateFieldData(fieldInstance, -1)
};
FixConstValueParams(fieldInfoType->ToTypeInstance(), fieldData);
auto fieldDataAgg = mBfIRBuilder->CreateConstAgg(mBfIRBuilder->MapType(fieldInfoType, BfIRPopulateType_Identity), fieldData);
args.Add(fieldDataAgg);
} }
}
else
args.Add(mBfIRBuilder->CreateTypeOf(typeInstance));
if (methodInstance->GetParamCount() > 1) auto attrType = customAttribute.mType;
{
if (irValue) BfMethodInstance* methodInstance = NULL;
args.Add(irValue); BfIRValue irValue;
else int checkDepth = 0;
args.Add(mBfIRBuilder->CreateConstNull()); auto checkAttrType = attrType;
} while (checkAttrType != NULL)
else {
{ mContext->mUnreifiedModule->PopulateType(checkAttrType, BfPopulateType_DataAndMethods);
// Only allow a single instance if (checkAttrType->mDefineState < BfTypeDefineState_DefinedAndMethodsSlotted)
if (irValue) break;
for (auto& ifaceEntry : checkAttrType->mInterfaces)
{
isFieldApply = false;
isFieldApply = (ceEmitContext != NULL) && (fieldInstance != NULL) && (ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIOnFieldInitTypeDef));
if (((ceEmitContext != NULL) && (ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIComptimeTypeApply))) ||
((ceEmitContext != NULL) && (ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIOnTypeInitTypeDef))) ||
((ceEmitContext == NULL) && (ifaceEntry.mInterfaceType->IsInstanceOf(mCompiler->mIOnTypeDoneTypeDef))))
{
// Passes
hasTypeApply = true;
if (pass == 1)
{
// Only find field inits now
continue;
}
}
else if (isFieldApply)
{
// Field passes
hasFieldApply = true;
if (methodInstance != NULL)
continue;
}
else
continue;
prevAttrInstances.TryGetValue(checkAttrType, &irValue);
methodInstance = checkAttrType->mInterfaceMethodTable[ifaceEntry.mStartInterfaceTableIdx].mMethodRef;
if (pass == 1)
break;
}
if (methodInstance != NULL)
break;
checkAttrType = checkAttrType->mBaseType;
checkDepth++;
}
if (methodInstance == NULL)
continue; continue;
}
DoPopulateType_CeCheckEnum(typeInstance, underlyingTypeDeferred); SetAndRestoreValue<CeEmitContext*> prevEmitContext(mCompiler->mCeMachine->mCurEmitContext, ceEmitContext);
if (fieldInstance != NULL) auto ceContext = mCompiler->mCeMachine->AllocContext();
mCompiler->mCeMachine->mFieldInstanceSet.Add(fieldInstance); defer({ mCompiler->mCeMachine->ReleaseContext(ceContext); });
BfTypedValue result;
///
{
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
CeCallSource callSource; BfIRValue attrVal = ceContext->CreateAttribute(customAttribute.mRef, this, typeInstance->mConstHolder, &customAttribute);
callSource.mRefNode = customAttribute.mRef; for (int baseIdx = 0; baseIdx < checkDepth; baseIdx++)
attrVal = mBfIRBuilder->CreateExtractValue(attrVal, 0);
SizedArray<BfIRValue, 1> args;
if (!attrType->IsValuelessType())
args.Add(attrVal);
if (isFieldApply) if (isFieldApply)
{ {
callSource.mKind = CeCallSource::Kind_FieldInit; auto fieldInfoType = ResolveTypeDef(mCompiler->mReflectFieldInfoTypeDef);
callSource.mFieldInstance = fieldInstance; if (fieldInfoType != NULL)
{
SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
SizedArray<BfIRValue, 9> fieldData =
{
mBfIRBuilder->CreateConstAggZero(mBfIRBuilder->MapType(fieldInfoType->ToTypeInstance()->mBaseType, BfIRPopulateType_Identity)),
mBfIRBuilder->CreateTypeOf(mCurTypeInstance), // mTypeInstance
CreateFieldData(fieldInstance, -1)
};
FixConstValueParams(fieldInfoType->ToTypeInstance(), fieldData);
auto fieldDataAgg = mBfIRBuilder->CreateConstAgg(mBfIRBuilder->MapType(fieldInfoType, BfIRPopulateType_Identity), fieldData);
args.Add(fieldDataAgg);
}
} }
else if (ceEmitContext != NULL) else
args.Add(mBfIRBuilder->CreateTypeOf(typeInstance));
if (methodInstance->GetParamCount() > 1)
{ {
callSource.mKind = CeCallSource::Kind_TypeInit; if (irValue)
args.Add(irValue);
else
args.Add(mBfIRBuilder->CreateConstNull());
} }
else else
{ {
callSource.mKind = CeCallSource::Kind_TypeDone; // Only allow a single instance
if (irValue)
continue;
} }
result = ceContext->Call(callSource, this, methodInstance, args, (CeEvalFlags)(CeEvalFlags_ForceReturnThis | CeEvalFlags_IgnoreConstEncodeFailure), NULL); DoPopulateType_CeCheckEnum(typeInstance, underlyingTypeDeferred);
} if (fieldInstance != NULL)
if (fieldInstance != NULL) mCompiler->mCeMachine->mFieldInstanceSet.Add(fieldInstance);
mCompiler->mCeMachine->mFieldInstanceSet.Remove(fieldInstance); BfTypedValue result;
if (result.mType == methodInstance->GetOwner()) ///
prevAttrInstances[methodInstance->GetOwner()] = result.mValue;
if (ceEmitContext == NULL)
continue;
if (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotted)
return;
if (typeInstance->mDefineState != BfTypeDefineState_CETypeInit)
{
// We populated before we could finish
AssertErrorState();
}
else
{
auto owner = methodInstance->GetOwner();
int typeId = owner->mTypeId;
if ((!result) && (mCompiler->mFastFinish))
{ {
if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext == NULL)) SetAndRestoreValue<bool> prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, true);
typeInstance->mCeTypeInfo->mNext = new BfCeTypeInfo();
if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext != NULL)) CeCallSource callSource;
typeInstance->mCeTypeInfo->mNext->mFastFinished = true; callSource.mRefNode = customAttribute.mRef;
if (typeInstance->mCeTypeInfo != NULL) if (isFieldApply)
{ {
BfCeTypeEmitEntry* entry = NULL; callSource.mKind = CeCallSource::Kind_FieldInit;
if (typeInstance->mCeTypeInfo->mTypeIFaceMap.TryGetValue(typeId, &entry)) callSource.mFieldInstance = fieldInstance;
}
else if (ceEmitContext != NULL)
{
callSource.mKind = CeCallSource::Kind_TypeInit;
}
else
{
callSource.mKind = CeCallSource::Kind_TypeDone;
}
result = ceContext->Call(callSource, this, methodInstance, args, (CeEvalFlags)(CeEvalFlags_ForceReturnThis | CeEvalFlags_IgnoreConstEncodeFailure), NULL);
}
if (fieldInstance != NULL)
mCompiler->mCeMachine->mFieldInstanceSet.Remove(fieldInstance);
if (result.mType == methodInstance->GetOwner())
prevAttrInstances[methodInstance->GetOwner()] = result.mValue;
if (ceEmitContext == NULL)
continue;
if (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotted)
return;
if (typeInstance->mDefineState != BfTypeDefineState_CETypeInit)
{
// We populated before we could finish
AssertErrorState();
}
else
{
auto owner = methodInstance->GetOwner();
int typeId = owner->mTypeId;
if ((!result) && (mCompiler->mFastFinish))
{
if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext == NULL))
typeInstance->mCeTypeInfo->mNext = new BfCeTypeInfo();
if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext != NULL))
typeInstance->mCeTypeInfo->mNext->mFastFinished = true;
if (typeInstance->mCeTypeInfo != NULL)
{ {
ceEmitContext->mEmitData = entry->mEmitData; BfCeTypeEmitEntry* entry = NULL;
if (typeInstance->mCeTypeInfo->mTypeIFaceMap.TryGetValue(typeId, &entry))
{
ceEmitContext->mEmitData = entry->mEmitData;
}
} }
} }
} else
else
{
if (ceEmitContext->HasEmissions())
{ {
if (typeInstance->mCeTypeInfo == NULL) if (ceEmitContext->HasEmissions())
typeInstance->mCeTypeInfo = new BfCeTypeInfo(); {
if (typeInstance->mCeTypeInfo->mNext == NULL) if (typeInstance->mCeTypeInfo == NULL)
typeInstance->mCeTypeInfo->mNext = new BfCeTypeInfo(); typeInstance->mCeTypeInfo = new BfCeTypeInfo();
if (typeInstance->mCeTypeInfo->mNext == NULL)
typeInstance->mCeTypeInfo->mNext = new BfCeTypeInfo();
BfCeTypeEmitEntry entry; BfCeTypeEmitEntry entry;
entry.mEmitData = ceEmitContext->mEmitData; entry.mEmitData = ceEmitContext->mEmitData;
typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap[typeId] = entry; typeInstance->mCeTypeInfo->mNext->mTypeIFaceMap[typeId] = entry;
typeInstance->mCeTypeInfo->mNext->mAlign = BF_MAX(typeInstance->mCeTypeInfo->mNext->mAlign, ceEmitContext->mAlign); typeInstance->mCeTypeInfo->mNext->mAlign = BF_MAX(typeInstance->mCeTypeInfo->mNext->mAlign, ceEmitContext->mAlign);
}
if ((ceEmitContext->mFailed) && (typeInstance->mCeTypeInfo != NULL))
typeInstance->mCeTypeInfo->mFailed = true;
} }
if ((ceEmitContext->mFailed) && (typeInstance->mCeTypeInfo != NULL)) if ((ceEmitContext->HasEmissions()) && (!mCompiler->mFastFinish))
typeInstance->mCeTypeInfo->mFailed = true; {
} String ctxStr = "comptime ";
ctxStr += methodInstance->mMethodDef->mName;
ctxStr += " of ";
ctxStr += TypeToString(attrType);
ctxStr += " to ";
ctxStr += TypeToString(typeInstance);
ctxStr += " ";
ctxStr += customAttribute.mRef->LocationToString();
if ((ceEmitContext->HasEmissions()) && (!mCompiler->mFastFinish)) UpdateCEEmit(ceEmitContext, typeInstance, customAttribute.mDeclaringType, ctxStr, customAttribute.mRef, BfCeTypeEmitSourceKind_Type);
{ }
String ctxStr = "comptime ";
ctxStr += methodInstance->mMethodDef->mName;
ctxStr += " of ";
ctxStr += TypeToString(attrType);
ctxStr += " to ";
ctxStr += TypeToString(typeInstance);
ctxStr += " ";
ctxStr += customAttribute.mRef->LocationToString();
UpdateCEEmit(ceEmitContext, typeInstance, customAttribute.mDeclaringType, ctxStr, customAttribute.mRef, BfCeTypeEmitSourceKind_Type);
} }
} }
} }
@ -2747,7 +2777,7 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance*
if (typeInstance->mCustomAttributes != NULL) if (typeInstance->mCustomAttributes != NULL)
HandleCEAttributes(ceEmitContext, typeInstance, NULL, typeInstance->mCustomAttributes, prevAttrInstances, underlyingTypeDeferred); HandleCEAttributes(ceEmitContext, typeInstance, NULL, typeInstance->mCustomAttributes, prevAttrInstances, underlyingTypeDeferred);
if (ceEmitContext != NULL) if ((ceEmitContext != NULL) || (onCompileKind == BfCEOnCompileKind_TypeDone))
{ {
for (auto& fieldInstance : typeInstance->mFieldInstances) for (auto& fieldInstance : typeInstance->mFieldInstances)
{ {