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:
parent
a5b032cc39
commit
b3cf2a0d04
1 changed files with 184 additions and 154 deletions
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue