From 612368b0f7750f54c6074860eac11dfbb20fa37d Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Thu, 16 Dec 2021 09:38:19 -0500 Subject: [PATCH] Comptime EmitAddInterface --- BeefLibs/corlib/src/Compiler.bf | 7 +++ IDEHelper/Compiler/BfModuleTypeUtils.cpp | 63 ++++++++++++++++++------ IDEHelper/Compiler/BfResolvedTypeUtils.h | 1 + IDEHelper/Compiler/CeMachine.cpp | 15 ++++++ IDEHelper/Compiler/CeMachine.h | 2 + IDEHelper/Tests/src/Comptime.bf | 3 +- 6 files changed, 74 insertions(+), 17 deletions(-) diff --git a/BeefLibs/corlib/src/Compiler.bf b/BeefLibs/corlib/src/Compiler.bf index cb706d01..3030c444 100644 --- a/BeefLibs/corlib/src/Compiler.bf +++ b/BeefLibs/corlib/src/Compiler.bf @@ -257,6 +257,7 @@ namespace System static extern void* Comptime_MethodBuilder_EmitStr(void* native, StringView str); static extern void* Comptime_CreateMethod(int32 typeId, StringView methodName, Type returnType, MethodFlags methodFlags); static extern void Comptime_EmitTypeBody(int32 typeId, StringView text); + static extern void Comptime_EmitAddInterface(int32 typeId, int32 ifaceTypeId); static extern void Comptime_EmitMethodEntry(int64 methodHandle, StringView text); static extern void Comptime_EmitMethodExit(int64 methodHandle, StringView text); static extern void Comptime_EmitMixin(StringView text); @@ -275,6 +276,12 @@ namespace System Comptime_EmitTypeBody((.)owner.TypeId, text); } + [Comptime(OnlyFromComptime=true)] + public static void EmitAddInterface(Type owner, Type iface) + { + Comptime_EmitAddInterface((.)owner.TypeId, (.)iface.TypeId); + } + [Comptime(OnlyFromComptime=true)] public static void EmitMethodEntry(ComptimeMethodInfo methodHandle, StringView text) { diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index d42ece83..6ee0e55f 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -2076,6 +2076,9 @@ void BfModule::FinishCEParseContext(BfAstNode* refNode, BfTypeInstance* typeInst void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, const StringImpl& ctxString, BfAstNode* refNode) { + for (int ifaceTypeId : ceEmitContext->mInterfaces) + typeInstance->mCeTypeInfo->mPendingInterfaces.Add(ifaceTypeId); + if (ceEmitContext->mEmitData.IsEmpty()) return; @@ -3313,6 +3316,27 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy wantPopulateInterfaces = true; } + if ((typeInstance->mCeTypeInfo != NULL) && (!typeInstance->mCeTypeInfo->mPendingInterfaces.IsEmpty())) + { + for (auto ifaceTypeId : typeInstance->mCeTypeInfo->mPendingInterfaces) + { + auto ifaceType = mContext->mTypes[ifaceTypeId]; + if ((ifaceType == NULL) || (!ifaceType->IsInterface())) + continue; + auto ifaceInst = ifaceType->ToTypeInstance(); + + if (ifaceSet.Add(ifaceInst)) + { + // Not base type + BfInterfaceDecl ifaceDecl; + ifaceDecl.mIFaceTypeInst = ifaceInst; + ifaceDecl.mTypeRef = NULL; + ifaceDecl.mDeclaringType = typeDef->GetDefinition(); + interfaces.Add(ifaceDecl); + } + } + } + if (_CheckTypeDone()) return; @@ -3703,12 +3727,22 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy PopulateType(innerType, BfPopulateType_Data); auto innerTypeInst = innerType->ToTypeInstance(); - if ((innerTypeInst != NULL) && (typeInstance->mTypeDef != innerTypeInst->mTypeDef)) + if (innerTypeInst != NULL) { - // Rebuild with proper typedef (generally from inner type comptime emission) - typeInstance->mTypeDef = innerTypeInst->mTypeDef; - DoPopulateType(resolvedTypeRef, populateType); - return; + if (typeInstance->mTypeDef != innerTypeInst->mTypeDef) + { + // Rebuild with proper typedef (generally from inner type comptime emission) + typeInstance->mTypeDef = innerTypeInst->mTypeDef; + DoPopulateType(resolvedTypeRef, populateType); + return; + } + + while (typeInstance->mInterfaces.mSize < innerTypeInst->mInterfaces.mSize) + { + auto ifaceEntry = innerTypeInst->mInterfaces[typeInstance->mInterfaces.mSize]; + typeInstance->mInterfaces.Add(ifaceEntry); + AddDependency(ifaceEntry.mInterfaceType, typeInstance, BfDependencyMap::DependencyFlag_ImplementsInterface); + } } auto baseType = typeInstance->mBaseType; @@ -4014,9 +4048,12 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy } if ((typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit) && (tryCE)) - { + { BF_ASSERT(!typeInstance->mTypeDef->IsEmitted()); + if (typeInstance->mCeTypeInfo != NULL) + typeInstance->mCeTypeInfo->mPendingInterfaces.Clear(); + typeInstance->mDefineState = BfTypeDefineState_CETypeInit; bool hadNewMembers = false; DoCEEmit(typeInstance, hadNewMembers); @@ -4071,6 +4108,9 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy } } + if ((typeInstance->mCeTypeInfo != NULL) && (!typeInstance->mCeTypeInfo->mPendingInterfaces.IsEmpty())) + hadNewMembers = true; + if ((typeInstance->mTypeDef->IsEmitted()) && (typeInstance->mCeTypeInfo == NULL)) { BF_ASSERT(mCompiler->mCanceling); @@ -5676,15 +5716,6 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) else { auto matchedMethodDef = matchedMethod->mMethodDef; -// if (matchedMethodDef->mDeclaringType->IsEmitted()) -// { -// Fail("Boxed interface binding error to emitted method", mCurTypeInstance->mTypeDef->GetRefNode()); -// continue; -// } -// -// if (underlyingTypeInstance->mTypeDef->IsEmitted()) -// matchedMethodDef = underlyingTypeInstance->mTypeDef->mEmitParent->mMethods[matchedMethodDef->mIdx]; - if (!matchedMethod->mIsForeignMethodDef) { BfMethodInstanceGroup* boxedMethodInstanceGroup = &typeInstance->mMethodInstanceGroups[matchedMethod->mMethodDef->mIdx]; @@ -5693,7 +5724,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) boxedMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingDecl; VerifyOnDemandMethods(); } - } + } auto methodFlags = matchedMethod->mIsForeignMethodDef ? BfGetMethodInstanceFlag_ForeignMethodDef : BfGetMethodInstanceFlag_None; methodFlags = (BfGetMethodInstanceFlags)(methodFlags | BfGetMethodInstanceFlag_MethodInstanceOnly); diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 858fc5d0..9b9a1321 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -1828,6 +1828,7 @@ class BfCeTypeInfo public: Dictionary mOnCompileMap; Dictionary mTypeIFaceMap; + Array mPendingInterfaces; Val128 mHash; bool mFailed; BfCeTypeInfo* mNext; diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp index 579630e3..b8054687 100644 --- a/IDEHelper/Compiler/CeMachine.cpp +++ b/IDEHelper/Compiler/CeMachine.cpp @@ -4740,6 +4740,17 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* return false; } } + else if (checkFunction->mFunctionKind == CeFunctionKind_EmitAddInterface) + { + int32 typeId = *(int32*)((uint8*)stackPtr); + int32 ifaceTypeId = *(int32*)((uint8*)stackPtr + sizeof(int32)); + if ((mCurEmitContext == NULL) || (mCurEmitContext->mType->mTypeId != typeId)) + { + _Fail("Code cannot be emitted for this type in this context"); + return false; + } + mCurEmitContext->mInterfaces.Add(ifaceTypeId); + } else if (checkFunction->mFunctionKind == CeFunctionKind_EmitMethodEntry) { int64 methodHandle = *(int64*)((uint8*)stackPtr); @@ -6833,6 +6844,10 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction) { ceFunction->mFunctionKind = CeFunctionKind_EmitTypeBody; } + if (methodDef->mName == "Comptime_EmitAddInterface") + { + ceFunction->mFunctionKind = CeFunctionKind_EmitAddInterface; + } else if (methodDef->mName == "Comptime_EmitMethodEntry") { ceFunction->mFunctionKind = CeFunctionKind_EmitMethodEntry; diff --git a/IDEHelper/Compiler/CeMachine.h b/IDEHelper/Compiler/CeMachine.h index 071b1e4a..6c211e25 100644 --- a/IDEHelper/Compiler/CeMachine.h +++ b/IDEHelper/Compiler/CeMachine.h @@ -289,6 +289,7 @@ enum CeFunctionKind CeFunctionKind_Method_GetParamInfo, CeFunctionKind_EmitTypeBody, + CeFunctionKind_EmitAddInterface, CeFunctionKind_EmitMethodEntry, CeFunctionKind_EmitMethodExit, CeFunctionKind_EmitMixin, @@ -687,6 +688,7 @@ class CeEmitContext public: BfType* mType; BfMethodInstance* mMethodInstance; + Array mInterfaces; String mEmitData; String mExitEmitData; bool mFailed; diff --git a/IDEHelper/Tests/src/Comptime.bf b/IDEHelper/Tests/src/Comptime.bf index 97be881c..453e39c7 100644 --- a/IDEHelper/Tests/src/Comptime.bf +++ b/IDEHelper/Tests/src/Comptime.bf @@ -210,11 +210,12 @@ namespace Tests } Compiler.EmitTypeBody(type, scope $"{SERIALIZE_NAME}{{{serializeBuffer}\n}}\n"); + Compiler.EmitAddInterface(type, typeof(ISerializable)); } } [Serializable] - struct Foo : this(float x, float y), ISerializable + struct Foo : this(float x, float y) { }