diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index bb6ae511..1f66735e 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -519,7 +519,7 @@ bool BfCompiler::IsTypeUsed(BfType* checkType, BfProject* curProject) BfTypeInstance* typeInst = checkType->ToTypeInstance(); if (typeInst != NULL) - { + { if ((typeInst->mTypeDef->mProject != NULL) && (typeInst->mTypeDef->mProject != curProject)) { if (typeInst->mTypeDef->mProject->mTargetType == BfTargetType_BeefDynLib) @@ -4260,18 +4260,7 @@ void BfCompiler::ProcessAutocompleteTempType() if (tempTypeDef->mTypeDeclaration->mAttributes != NULL) { - BfAttributeTargets attrTarget; - if (tempTypeDef->mIsDelegate) - attrTarget = BfAttributeTargets_Delegate; - else if (typeInst->IsEnum()) - attrTarget = BfAttributeTargets_Enum; - else if (typeInst->IsInterface()) - attrTarget = BfAttributeTargets_Interface; - else if (typeInst->IsStruct()) - attrTarget = BfAttributeTargets_Struct; - else - attrTarget = BfAttributeTargets_Class; - auto customAttrs = module->GetCustomAttributes(tempTypeDef->mTypeDeclaration->mAttributes, attrTarget); + auto customAttrs = module->GetCustomAttributes(tempTypeDef); delete customAttrs; } @@ -6293,6 +6282,8 @@ void BfCompiler::CompileReified() { BP_ZONE("Compile_ResolveTypeDefs"); + Array deferTypeDefs; + for (auto typeDef : mSystem->mTypeDefs) { mSystem->CheckLockYield(); @@ -6328,10 +6319,45 @@ void BfCompiler::CompileReified() //TODO: Just because the type is required doesn't mean we want to reify it. Why did we have that check? if ((mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude) && (!isAlwaysInclude)) + { + if (typeDef->mGenericParamDefs.IsEmpty()) + deferTypeDefs.Add(typeDef); continue; + } scratchModule->ResolveTypeDef(typeDef, BfPopulateType_Full); } + + // Resolve remaining typedefs as unreified so we can check their attributes + for (auto typeDef : deferTypeDefs) + { + auto type = mContext->mUnreifiedModule->ResolveTypeDef(typeDef, BfPopulateType_Identity); + if (type == NULL) + continue; + auto typeInst = type->ToTypeInstance(); + if (typeInst == NULL) + continue; + if (typeInst->mIsReified) + continue; + + mContext->mUnreifiedModule->PopulateType(typeInst, BfPopulateType_Interfaces); + if (typeInst->mCustomAttributes == NULL) + continue; + + bool alwaysInclude = false; + for (auto& customAttribute : typeInst->mCustomAttributes->mAttributes) + { + if (customAttribute.mType->mAttributeData != NULL) + { + if (customAttribute.mType->mAttributeData->mAlwaysIncludeUser != 0) + alwaysInclude = true; + if ((customAttribute.mType->mAttributeData->mFlags & BfAttributeFlag_AlwaysIncludeTarget) != 0) + alwaysInclude = true; + } + } + if (alwaysInclude) + mContext->mScratchModule->PopulateType(typeInst, BfPopulateType_Full); + } if (mOptions.mCompileOnDemandKind != BfCompileOnDemandKind_AlwaysInclude) { @@ -6850,26 +6876,16 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) { SizedArray requiredModules; - for (auto typeDef : mSystem->mTypeDefs) + for (auto type : mContext->mResolvedTypes) { - if (typeDef->mIsPartial) + auto typeInst = type->ToTypeInstance(); + if (typeInst == NULL) continue; - - bool isAlwaysInclude = (typeDef->mIsAlwaysInclude) || (typeDef->mProject->mAlwaysIncludeAll); - auto typeOptions = mContext->mScratchModule->GetTypeOptions(typeDef); - if (typeOptions != NULL) - isAlwaysInclude = typeOptions->Apply(isAlwaysInclude, BfOptionFlags_ReflectAlwaysIncludeType); - - if (isAlwaysInclude) - { - auto requiredType = mContext->mScratchModule->ResolveTypeDef(typeDef); - if (requiredType != NULL) - { - auto requiredModule = requiredType->GetModule(); - if (requiredModule != NULL) - requiredModules.push_back(requiredModule); - } - } + if (typeInst->mAlwaysIncludeFlags == BfAlwaysIncludeFlag_None) + continue; + auto requiredModule = typeInst->GetModule(); + if (requiredModule != NULL) + requiredModules.push_back(requiredModule); } mContext->mReferencedIFaceSlots.Clear(); diff --git a/IDEHelper/Compiler/BfIRBuilder.cpp b/IDEHelper/Compiler/BfIRBuilder.cpp index 4c2e306b..578b8337 100644 --- a/IDEHelper/Compiler/BfIRBuilder.cpp +++ b/IDEHelper/Compiler/BfIRBuilder.cpp @@ -1688,6 +1688,19 @@ void BfIRBuilder::ClearConstData() BF_ASSERT(mStream.GetSize() == 0); } +void BfIRBuilder::ClearNonConstData() +{ + mMethodTypeMap.Clear(); + mFunctionMap.Clear(); + mTypeMap.Clear(); + mConstMemMap.Clear(); + mDITemporaryTypes.Clear(); + mSavedDebugLocs.Clear(); + mDeferredDbgTypeDefs.Clear(); + mActiveFunction = BfIRFunction(); + mInsertBlock = BfIRValue(); +} + void BfIRBuilder::Start(const StringImpl& moduleName, int ptrSize, bool isOptimized) { mHasStarted = true; @@ -4789,7 +4802,7 @@ BfIRFunctionType BfIRBuilder::MapMethod(BfMethodInstance* methodInstance) bool useCache = (!mModule->mIsSpecialModule) && (methodInstance->mMethodDef->mIdx >= 0); if (useCache) - { + { BfIRFunctionType* funcType = NULL; if (mMethodTypeMap.TryGetValue(methodInstance, &funcType)) return *funcType; diff --git a/IDEHelper/Compiler/BfIRBuilder.h b/IDEHelper/Compiler/BfIRBuilder.h index a81eb50b..5fda7c7c 100644 --- a/IDEHelper/Compiler/BfIRBuilder.h +++ b/IDEHelper/Compiler/BfIRBuilder.h @@ -38,6 +38,7 @@ class BfIRCodeGen; class BeIRCodeGen; class BfMethodInstance; class BfFieldInstance; +class BfMethodRef; class BfFileInstance; class BfParser; @@ -974,7 +975,7 @@ public: bool mHasDebugLoc; bool mHasDebugInfo; bool mHasDebugLineInfo; - Dictionary mMethodTypeMap; + Dictionary mMethodTypeMap; Dictionary mFunctionMap; Dictionary mTypeMap; Dictionary mConstMemMap; @@ -1134,6 +1135,7 @@ public: void GetBufferData(Array& outBuffer); void ClearConstData(); + void ClearNonConstData(); void Start(const StringImpl& moduleName, int ptrSize, bool isOptimized); void SetBackend(bool isBeefBackend); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 73a93e09..12377c45 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -1103,6 +1103,67 @@ void BfModule::PrepareForIRWriting(BfTypeInstance* typeInst) } } +void BfModule::SetupIRBuilder(bool dbgVerifyCodeGen) +{ + if (mIsScratchModule) + { + mBfIRBuilder->mIgnoreWrites = true; + BF_ASSERT(!dbgVerifyCodeGen); + } +#ifdef _DEBUG + if (mCompiler->mIsResolveOnly) + { + // For "deep" verification testing + /*if (!mIsSpecialModule) + dbgVerifyCodeGen = true;*/ + + // We only want to turn this off on smaller builds for testing + mBfIRBuilder->mIgnoreWrites = true; + if (dbgVerifyCodeGen) + mBfIRBuilder->mIgnoreWrites = false; + if (!mBfIRBuilder->mIgnoreWrites) + { + // The only purpose of not ignoring writes is so we can verify the codegen one instruction at a time + mBfIRBuilder->mDbgVerifyCodeGen = true; + } + } + else if (!mIsReified) + { + mBfIRBuilder->mIgnoreWrites = true; + } + else + { + // We almost always want this to be 'false' unless we need need to be able to inspect the generated LLVM + // code as we walk the AST + //mBfIRBuilder->mDbgVerifyCodeGen = true; + if ( + (mModuleName == "-") + //|| (mModuleName == "BeefTest2_ClearColorValue") + //|| (mModuleName == "Tests_FuncRefs") + ) + mBfIRBuilder->mDbgVerifyCodeGen = true; + + // Just for testing! + //mBfIRBuilder->mIgnoreWrites = true; + } +#else + if (mCompiler->mIsResolveOnly) + { + // Always ignore writes in resolveOnly for release builds + mBfIRBuilder->mIgnoreWrites = true; + } + else + { + // Just for memory testing! This breaks everything. + //mBfIRBuilder->mIgnoreWrites = true; + + // For "deep" verification testing + //mBfIRBuilder->mDbgVerifyCodeGen = true; + } +#endif + mWantsIRIgnoreWrites = mBfIRBuilder->mIgnoreWrites; +} + void BfModule::EnsureIRBuilder(bool dbgVerifyCodeGen) { BF_ASSERT(!mIsDeleting); @@ -1121,64 +1182,7 @@ void BfModule::EnsureIRBuilder(bool dbgVerifyCodeGen) mBfIRBuilder = new BfIRBuilder(this); BfLogSysM("Created mBfIRBuilder %p in %p %s Reified: %d\n", mBfIRBuilder, this, mModuleName.c_str(), mIsReified); - - if (mIsScratchModule) - { - mBfIRBuilder->mIgnoreWrites = true; - BF_ASSERT(!dbgVerifyCodeGen); - } -#ifdef _DEBUG - if (mCompiler->mIsResolveOnly) - { - // For "deep" verification testing - /*if (!mIsSpecialModule) - dbgVerifyCodeGen = true;*/ - - // We only want to turn this off on smaller builds for testing - mBfIRBuilder->mIgnoreWrites = true; - if (dbgVerifyCodeGen) - mBfIRBuilder->mIgnoreWrites = false; - if (!mBfIRBuilder->mIgnoreWrites) - { - // The only purpose of not ignoring writes is so we can verify the codegen one instruction at a time - mBfIRBuilder->mDbgVerifyCodeGen = true; - } - } - else if (!mIsReified) - { - mBfIRBuilder->mIgnoreWrites = true; - } - else - { - // We almost always want this to be 'false' unless we need need to be able to inspect the generated LLVM - // code as we walk the AST - //mBfIRBuilder->mDbgVerifyCodeGen = true; - if ( - (mModuleName == "-") - //|| (mModuleName == "BeefTest2_ClearColorValue") - //|| (mModuleName == "Tests_FuncRefs") - ) - mBfIRBuilder->mDbgVerifyCodeGen = true; - - // Just for testing! - //mBfIRBuilder->mIgnoreWrites = true; - } -#else - if (mCompiler->mIsResolveOnly) - { - // Always ignore writes in resolveOnly for release builds - mBfIRBuilder->mIgnoreWrites = true; - } - else - { - // Just for memory testing! This breaks everything. - //mBfIRBuilder->mIgnoreWrites = true; - - // For "deep" verification testing - //mBfIRBuilder->mDbgVerifyCodeGen = true; - } -#endif - mWantsIRIgnoreWrites = mBfIRBuilder->mIgnoreWrites; + SetupIRBuilder(dbgVerifyCodeGen); } } @@ -6937,7 +6941,7 @@ BfIRValue BfModule::FixClassVData(BfIRValue value) } void BfModule::CheckStaticAccess(BfTypeInstance* typeInstance) -{ +{ // Note: this is not just for perf, it fixes a field var-type resolution issue if (mBfIRBuilder->mIgnoreWrites) return; @@ -11230,7 +11234,7 @@ void BfModule::GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttri if (success) { - if (!attrTypeInst->mAttributeData->mAllowMultiple) + if ((attrTypeInst->mAttributeData->mFlags & BfAttributeFlag_DisallowAllowMultiple) != 0) { for (auto& prevCustomAttribute : customAttributes->mAttributes) { @@ -11258,6 +11262,22 @@ BfCustomAttributes* BfModule::GetCustomAttributes(BfAttributeDirective* attribut return customAttributes; } +BfCustomAttributes* BfModule::GetCustomAttributes(BfTypeDef* typeDef) +{ + BfAttributeTargets attrTarget; + if (typeDef->mIsDelegate) + attrTarget = BfAttributeTargets_Delegate; + else if (typeDef->mTypeCode == BfTypeCode_Enum) + attrTarget = BfAttributeTargets_Enum; + else if (typeDef->mTypeCode == BfTypeCode_Interface) + attrTarget = BfAttributeTargets_Interface; + else if (typeDef->mTypeCode == BfTypeCode_Struct) + attrTarget = BfAttributeTargets_Struct; + else + attrTarget = BfAttributeTargets_Class; + return GetCustomAttributes(typeDef->mTypeDeclaration->mAttributes, attrTarget); +} + void BfModule::FinishAttributeState(BfAttributeState* attributeState) { if ((!attributeState->mUsed) && (attributeState->mSrc != NULL)) @@ -11290,6 +11310,8 @@ void BfModule::ProcessTypeInstCustomAttributes(bool& isPacked, bool& isUnion, bo } else if (typeName == "System.AlwaysIncludeAttribute") { + mCurTypeInstance->mAlwaysIncludeFlags = (BfAlwaysIncludeFlags)(mCurTypeInstance->mAlwaysIncludeFlags | BfAlwaysIncludeFlag_Type); + for (auto setProp : customAttribute.mSetProperties) { BfPropertyDef* propertyDef = setProp.mPropertyRef; @@ -11368,6 +11390,15 @@ void BfModule::ProcessCustomAttributeData() attributeData->mAttributeTargets = (BfAttributeTargets)constant->mInt32; } + if (customAttribute.mCtorArgs.size() == 2) + { + auto constant = mCurTypeInstance->mConstHolder->GetConstant(customAttribute.mCtorArgs[0]); + if ((constant != NULL) && (mBfIRBuilder->IsInt(constant->mTypeCode))) + { + attributeData->mFlags = (BfAttributeFlags)constant->mInt32; + } + } + for (auto& setProp : customAttribute.mSetProperties) { BfPropertyDef* propDef = setProp.mPropertyRef; @@ -11375,14 +11406,18 @@ void BfModule::ProcessCustomAttributeData() if (propDef->mName == "AllowMultiple") { auto constant = mCurTypeInstance->mConstHolder->GetConstant(setProp.mParam.mValue); - if (constant != NULL) - attributeData->mAllowMultiple = constant->mBool; + if ((constant != NULL) && (constant->mBool)) + attributeData->mFlags = (BfAttributeFlags)(attributeData->mFlags & ~BfAttributeFlag_DisallowAllowMultiple); + else + attributeData->mFlags = (BfAttributeFlags)(attributeData->mFlags | BfAttributeFlag_DisallowAllowMultiple); } else if (propDef->mName == "Inherited") { auto constant = mCurTypeInstance->mConstHolder->GetConstant(setProp.mParam.mValue); - if (constant != NULL) - attributeData->mInherited = constant->mBool; + if ((constant != NULL) && (constant->mBool)) + attributeData->mFlags = (BfAttributeFlags)(attributeData->mFlags & ~BfAttributeFlag_NotInherited); + else + attributeData->mFlags = (BfAttributeFlags)(attributeData->mFlags | BfAttributeFlag_NotInherited); } else if (propDef->mName == "ValidOn") { @@ -11406,8 +11441,7 @@ void BfModule::ProcessCustomAttributeData() if ((!hasCustomAttribute) && (mCurTypeInstance->mBaseType->mAttributeData != NULL)) { attributeData->mAttributeTargets = mCurTypeInstance->mBaseType->mAttributeData->mAttributeTargets; - attributeData->mInherited = mCurTypeInstance->mBaseType->mAttributeData->mInherited; - attributeData->mAllowMultiple = mCurTypeInstance->mBaseType->mAttributeData->mAllowMultiple; + attributeData->mFlags = mCurTypeInstance->mBaseType->mAttributeData->mFlags; attributeData->mAlwaysIncludeUser = mCurTypeInstance->mBaseType->mAttributeData->mAlwaysIncludeUser; } @@ -21027,30 +21061,6 @@ void BfModule::SetupIRFunction(BfMethodInstance* methodInstance, StringImpl& man BfIRFunctionType funcType = mBfIRBuilder->MapMethod(methodInstance); - // Don't set these pointers during resolve pass because they may become invalid if it's just a temporary autocomplete method - if (mCompiler->mResolvePassData == NULL) - { - if ((methodDef->mMethodType == BfMethodType_Ctor) && (methodDef->mIsStatic)) - { - typeInstance->mHasStaticInitMethod = true; - } - - if ((methodDef->mMethodType == BfMethodType_Dtor) && (methodDef->mIsStatic)) - { - typeInstance->mHasStaticDtorMethod = true; - } - - if ((methodDef->mMethodType == BfMethodType_Normal) && (methodDef->mIsStatic) && (methodDef->mName == BF_METHODNAME_MARKMEMBERS_STATIC)) - { - typeInstance->mHasStaticMarkMethod = true; - } - - if ((methodDef->mMethodType == BfMethodType_Normal) && (methodDef->mIsStatic) && (methodDef->mName == BF_METHODNAME_FIND_TLS_MEMBERS)) - { - typeInstance->mHasTLSFindMethod = true; - } - } - if (isTemporaryFunc) { BF_ASSERT(((mCompiler->mIsResolveOnly) && (mCompiler->mResolvePassData->mAutoComplete != NULL)) || @@ -23634,6 +23644,8 @@ bool BfModule::Finish() if (HasCompiledOutput()) { + BF_ASSERT(!mBfIRBuilder->mIgnoreWrites); + DbgFinish(); if (mAwaitingInitFinish) diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 449398c9..29f46f56 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1555,8 +1555,9 @@ public: BfTypedValue GetTypedValueFromConstant(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType); BfIRValue ConstantToCurrent(BfConstant* constant, BfIRConstHolder* constHolder, BfType* wantType, bool allowStringId = false); void ValidateCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeTargets attrTarget); - void GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, bool allowNonConstArgs = false, BfCaptureInfo* captureInfo = NULL); + void GetCustomAttributes(BfCustomAttributes* customAttributes, BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, bool allowNonConstArgs = false, BfCaptureInfo* captureInfo = NULL); BfCustomAttributes* GetCustomAttributes(BfAttributeDirective* attributesDirective, BfAttributeTargets attrType, bool allowNonConstArgs = false, BfCaptureInfo* captureInfo = NULL); + BfCustomAttributes* GetCustomAttributes(BfTypeDef* typeDef); void FinishAttributeState(BfAttributeState* attributeState); void ProcessTypeInstCustomAttributes(bool& isPacked, bool& isUnion, bool& isCRepr, bool& isOrdered, int& alignOverride, BfType*& underlyingArrayType, int& underlyingArraySize); void ProcessCustomAttributeData(); @@ -1946,6 +1947,7 @@ public: void Cleanup(); void StartNewRevision(RebuildKind rebuildKind = RebuildKind_All, bool force = false); void PrepareForIRWriting(BfTypeInstance* typeInst); + void SetupIRBuilder(bool dbgVerifyCodeGen); void EnsureIRBuilder(bool dbgVerifyCodeGen = false); void DbgFinish(); BfIRValue CreateForceLinkMarker(BfModule* module, String* outName); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index 57aa3171..db957234 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -1014,17 +1014,46 @@ void BfModule::PopulateType(BfType* resolvedTypeRef, BfPopulateType populateType { if ((typeModule != NULL) && (!typeModule->mIsReified) && (!typeModule->mReifyQueued)) { - BF_ASSERT((mCompiler->mCompileState != BfCompiler::CompileState_Unreified) && (mCompiler->mCompileState != BfCompiler::CompileState_VData)); + bool canFastReify = false; + if (typeModule->mAwaitingInitFinish) + { + canFastReify = true; + for (auto ownedTypes : typeModule->mOwnedTypeInstances) + if (ownedTypes->mDefineState > BfTypeDefineState_HasInterfaces) + canFastReify = false; + } - BfLogSysM("Queued reification of type %p in module %p in PopulateType\n", resolvedTypeRef, typeModule); + if (canFastReify) + { + BfLogSysM("Setting reified type %p in module %p in PopulateType on module awaiting finish\n", resolvedTypeRef, typeModule); + typeModule->mIsReified = true; + typeModule->mWantsIRIgnoreWrites = false; + for (auto ownedTypes : typeModule->mOwnedTypeInstances) + ownedTypes->mIsReified = true; + mCompiler->mStats.mReifiedModuleCount++; + if (typeModule->mBfIRBuilder != NULL) + { + typeModule->mBfIRBuilder->ClearNonConstData(); + typeModule->mBfIRBuilder->mIgnoreWrites = false; + typeModule->SetupIRBuilder(false); + } + else + typeModule->PrepareForIRWriting(resolvedTypeRef->ToTypeInstance()); + } + else + { + BF_ASSERT((mCompiler->mCompileState != BfCompiler::CompileState_Unreified) && (mCompiler->mCompileState != BfCompiler::CompileState_VData)); - BF_ASSERT((typeModule != mContext->mUnreifiedModule) && (typeModule != mContext->mScratchModule)); + BfLogSysM("Queued reification of type %p in module %p in PopulateType\n", resolvedTypeRef, typeModule); - BF_ASSERT(!typeModule->mIsSpecialModule); - // This caused issues - we may need to reify a type and then request a method - typeModule->mReifyQueued = true; - mContext->mReifyModuleWorkList.Add(typeModule); - //typeModule->ReifyModule(); + BF_ASSERT((typeModule != mContext->mUnreifiedModule) && (typeModule != mContext->mScratchModule)); + + BF_ASSERT(!typeModule->mIsSpecialModule); + // This caused issues - we may need to reify a type and then request a method + typeModule->mReifyQueued = true; + mContext->mReifyModuleWorkList.Add(typeModule); + //typeModule->ReifyModule(); + } } } } @@ -3342,29 +3371,10 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy } if (typeInstance->mTypeOptionsIdx == -2) - SetTypeOptions(typeInstance); - -// if (typeInstance->mDefineState == BfTypeDefineState_CETypeInit) -// { -// if (populateType <= BfPopulateType_AllowStaticMethods) -// return; -// -// auto refNode = typeDef->GetRefNode(); -// Fail("OnCompile const evaluation creates a data dependency during TypeInit", refNode); -// mCompiler->mCEMachine->Fail("OnCompile const evaluation creates a data dependency during TypeInit"); -// } -// else if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit) -// { -// typeInstance->mDefineState = BfTypeDefineState_CETypeInit; -// ExecuteCEOnCompile(typeInstance, BfCEOnCompileKind_TypeInit); -// -// if (_CheckTypeDone()) -// return; -// -// if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit) -// typeInstance->mDefineState = BfTypeDefineState_CEPostTypeInit; -// } - + { + SetTypeOptions(typeInstance); + } + if (populateType <= BfPopulateType_AllowStaticMethods) return; @@ -3400,6 +3410,17 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy if (typeOptions != NULL) { typeInstance->mHasBeenInstantiated = typeOptions->Apply(typeInstance->HasBeenInstantiated(), BfOptionFlags_ReflectAssumeInstantiated); + + bool alwaysInclude = typeInstance->mAlwaysIncludeFlags != 0; + if ((typeOptions->Apply(alwaysInclude, BfOptionFlags_ReflectAlwaysIncludeType)) || + (typeOptions->Apply(alwaysInclude, BfOptionFlags_ReflectAlwaysIncludeAll))) + { + typeInstance->mAlwaysIncludeFlags = (BfAlwaysIncludeFlags)(typeInstance->mAlwaysIncludeFlags | BfAlwaysIncludeFlag_Type); + } + else + { + typeInstance->mAlwaysIncludeFlags = BfAlwaysIncludeFlag_None; + } } } @@ -4632,6 +4653,30 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance) { auto methodInstanceGroup = &typeInstance->mMethodInstanceGroups[methodDef->mIdx]; + // Don't set these pointers during resolve pass because they may become invalid if it's just a temporary autocomplete method + if (mCompiler->mResolvePassData == NULL) + { + if ((methodDef->mMethodType == BfMethodType_Ctor) && (methodDef->mIsStatic)) + { + typeInstance->mHasStaticInitMethod = true; + } + + if ((methodDef->mMethodType == BfMethodType_Dtor) && (methodDef->mIsStatic)) + { + typeInstance->mHasStaticDtorMethod = true; + } + + if ((methodDef->mMethodType == BfMethodType_Normal) && (methodDef->mIsStatic) && (methodDef->mName == BF_METHODNAME_MARKMEMBERS_STATIC)) + { + typeInstance->mHasStaticMarkMethod = true; + } + + if ((methodDef->mMethodType == BfMethodType_Normal) && (methodDef->mIsStatic) && (methodDef->mName == BF_METHODNAME_FIND_TLS_MEMBERS)) + { + typeInstance->mHasTLSFindMethod = true; + } + } + // Thsi MAY be generated already // This should still be set to the default value //BF_ASSERT((methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NotSet) || (methodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_AlwaysInclude)); @@ -5724,10 +5769,12 @@ void BfModule::AddMethodToWorkList(BfMethodInstance* methodInstance) if ((!methodInstance->mIRFunction) && (methodInstance->mIsReified) && (!methodInstance->mIsUnspecialized) && (methodInstance->GetImportCallKind() == BfImportCallKind_None)) - { + { if (!mIsModuleMutable) PrepareForIRWriting(methodInstance->GetOwner()); + SetAndRestoreValue prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mWantsIRIgnoreWrites); + BfIRValue func = CreateFunctionFrom(methodInstance, false, methodInstance->mAlwaysInline); if (func) { @@ -8180,10 +8227,8 @@ BfTypeDef* BfModule::FindTypeDefRaw(const BfAtomComposite& findName, int numGene BfTypeDef* protErrorTypeDef = NULL; BfTypeInstance* protErrorOuterType = NULL; - - - if (!lookupCtx.HasValidMatch()) + if ((!lookupCtx.HasValidMatch()) && (typeInstance != NULL)) { std::function _CheckType = [&](BfTypeInstance* typeInstance) { @@ -8233,8 +8278,8 @@ BfTypeDef* BfModule::FindTypeDefRaw(const BfAtomComposite& findName, int numGene }; _CheckType(typeInstance); - } - + } + if (!lookupCtx.HasValidMatch()) { if (mSystem->mTypeDefs.TryGet(findName, NULL)) @@ -8271,6 +8316,12 @@ BfTypeDef* BfModule::FindTypeDefRaw(const BfAtomComposite& findName, int numGene } } + if ((!lookupCtx.HasValidMatch()) && (typeInstance == NULL)) + { + if (useTypeDef->mOuterType != NULL) + return FindTypeDefRaw(findName, numGenericArgs, typeInstance, useTypeDef->mOuterType, error); + } + if ((error != NULL) && (lookupCtx.mAmbiguousTypeDef != NULL)) { if (error->mErrorKind == BfTypeLookupError::BfErrorKind_None) @@ -8292,8 +8343,10 @@ BfTypeDef* BfModule::FindTypeDef(const BfAtomComposite& findName, int numGeneric BP_ZONE("BfModule::FindTypeDef_1"); BfTypeInstance* typeInstance = (typeInstanceOverride != NULL) ? typeInstanceOverride : mCurTypeInstance; - if (typeInstance == NULL) - { + auto useTypeDef = GetActiveTypeDef(typeInstanceOverride, true); + + if ((typeInstance == NULL) && (useTypeDef == NULL)) + { BfProject* project = NULL; if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mParser != NULL)) project = mCompiler->mResolvePassData->mParser->mProject; @@ -8310,11 +8363,9 @@ BfTypeDef* BfModule::FindTypeDef(const BfAtomComposite& findName, int numGeneric } return result; - } + } - auto useTypeDef = GetActiveTypeDef(typeInstanceOverride, true); - - if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL)) + if ((mCompiler->mResolvePassData != NULL) && (mCompiler->mResolvePassData->mAutoComplete != NULL) && (typeInstance != NULL)) { if (mCompiler->mResolvePassData->mAutoCompleteTempTypes.Contains(useTypeDef)) return FindTypeDefRaw(findName, numGenericArgs, typeInstance, useTypeDef, error); @@ -8327,7 +8378,7 @@ BfTypeDef* BfModule::FindTypeDef(const BfAtomComposite& findName, int numGeneric BfTypeLookupEntry* typeLookupEntryPtr = NULL; BfTypeLookupResult* resultPtr = NULL; - if (typeInstance->mLookupResults.TryAdd(typeLookupEntry, &typeLookupEntryPtr, &resultPtr)) + if ((typeInstance != NULL) && (typeInstance->mLookupResults.TryAdd(typeLookupEntry, &typeLookupEntryPtr, &resultPtr))) { typeLookupEntryPtr->mAtomUpdateIdx = typeLookupEntry.mName.GetAtomUpdateIdx(); @@ -8353,7 +8404,7 @@ BfTypeDef* BfModule::FindTypeDef(const BfAtomComposite& findName, int numGeneric } else { - if (resultPtr->mForceLookup) + if ((resultPtr == NULL) || (resultPtr->mForceLookup)) return FindTypeDefRaw(findName, numGenericArgs, typeInstance, useTypeDef, error); else return resultPtr->mTypeDef; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index e41f8a18..ce966df6 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -1571,21 +1571,27 @@ enum BfAttributeTargets : int32 BfAttributeTargets_All = 0x3FFFFF }; +enum BfAttributeFlags : int8 +{ + BfAttributeFlag_None, + BfAttributeFlag_DisallowAllowMultiple = 1, + BfAttributeFlag_NotInherited = 2, + BfAttributeFlag_ReflectAttribute = 4, + BfAttributeFlag_AlwaysIncludeTarget = 8 +}; + class BfAttributeData { public: BfAttributeTargets mAttributeTargets; BfAlwaysIncludeFlags mAlwaysIncludeUser; - bool mInherited; - bool mAllowMultiple; - + BfAttributeFlags mFlags; public: BfAttributeData() { mAttributeTargets = BfAttributeTargets_All; mAlwaysIncludeUser = BfAlwaysIncludeFlag_None; - mInherited = true; - mAllowMultiple = false; + mFlags = BfAttributeFlag_None; } };