From 0a78b5cc3515a56f5580fd35d214913006965664 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 28 Sep 2020 12:41:42 -0700 Subject: [PATCH] Improvements and safety for const exprs --- IDEHelper/Compiler/BfCompiler.h | 6 +- IDEHelper/Compiler/BfMangler.cpp | 59 +++++++++------ IDEHelper/Compiler/BfModule.cpp | 74 +++++++++++++++--- IDEHelper/Compiler/BfModule.h | 1 + IDEHelper/Compiler/BfModuleTypeUtils.cpp | 88 ++++++++++++++++------ IDEHelper/Compiler/BfResolvedTypeUtils.cpp | 64 ++++++++++------ IDEHelper/Compiler/BfResolvedTypeUtils.h | 21 ++++-- IDEHelper/Tests/src/ConstExprs.bf | 62 +++++++++++++++ 8 files changed, 290 insertions(+), 85 deletions(-) create mode 100644 IDEHelper/Tests/src/ConstExprs.bf diff --git a/IDEHelper/Compiler/BfCompiler.h b/IDEHelper/Compiler/BfCompiler.h index 0719bf81..8df75221 100644 --- a/IDEHelper/Compiler/BfCompiler.h +++ b/IDEHelper/Compiler/BfCompiler.h @@ -67,7 +67,7 @@ public: int mMethodDeclarations; int mTypesPopulated; int mMethodsProcessed; - int mUnreifiedMethodsProcessed; + int mUnreifiedMethodsProcessed; int mQueuedTypesProcessed; int mTypesQueued; @@ -82,7 +82,7 @@ public: int mReifiedModuleCount; int mIRBytes; - int mConstBytes; + int mConstBytes; }; Stats mStats; @@ -122,7 +122,7 @@ public: bool mDebugAlloc; bool mOmitDebugHelpers; - bool mUseDebugBackingParams; + bool mUseDebugBackingParams; bool mWriteIR; bool mGenerateObj; diff --git a/IDEHelper/Compiler/BfMangler.cpp b/IDEHelper/Compiler/BfMangler.cpp index 9746c74a..19388bda 100644 --- a/IDEHelper/Compiler/BfMangler.cpp +++ b/IDEHelper/Compiler/BfMangler.cpp @@ -423,13 +423,7 @@ void BfGNUMangler::Mangle(MangleContext& mangleContext, StringImpl& name, BfType name += "v"; else name += "U4void"; - return; - case BfTypeCode_Var: - if ((mangleContext.mCCompat) || (mangleContext.mInArgs)) - name += "v"; - else - name += "U3var"; - return; + return; case BfTypeCode_Self: if ((mangleContext.mCCompat) || (mangleContext.mInArgs)) name += "U8concrete"; @@ -494,6 +488,19 @@ void BfGNUMangler::Mangle(MangleContext& mangleContext, StringImpl& name, BfType name += "f"; return; case BfTypeCode_Double: name += "d"; return; + + case BfTypeCode_Var: + if ((mangleContext.mCCompat) || (mangleContext.mInArgs)) + name += "v"; + else + name += "U3var"; + return; + case BfTypeCode_Let: + name += "U3let"; return; + case BfTypeCode_IntUnknown: + name += "U4iunk"; return; + case BfTypeCode_UIntUnknown: + name += "U4uunk"; return; default: break; } @@ -1455,21 +1462,7 @@ void BfMSMangler::Mangle(MangleContext& mangleContext, StringImpl& name, BfType* } return; case BfTypeCode_None: - name += "X"; return; - case BfTypeCode_Dot: - name += "Tdot@@"; return; - case BfTypeCode_Var: - if ((mangleContext.mCCompat) || (mangleContext.mInArgs)) - name += "X"; - else - name += "Tvar@@"; - return; - case BfTypeCode_Self: - if ((mangleContext.mCCompat) || (mangleContext.mInArgs)) - name += "X"; - else - name += "Tself@@"; - return; + name += "X"; return; case BfTypeCode_Int8: name += "C"; return; case BfTypeCode_UInt8: @@ -1512,6 +1505,28 @@ void BfMSMangler::Mangle(MangleContext& mangleContext, StringImpl& name, BfType* } isLongPrim = true; break; + + case BfTypeCode_Dot: + name += "Tdot@@"; return; + case BfTypeCode_Var: + if ((mangleContext.mCCompat) || (mangleContext.mInArgs)) + name += "X"; + else + name += "Tvar@@"; + return; + case BfTypeCode_Self: + if ((mangleContext.mCCompat) || (mangleContext.mInArgs)) + name += "X"; + else + name += "Tself@@"; + return; + case BfTypeCode_Let: + name += "Tlet@@"; return; + case BfTypeCode_IntUnknown: + name += "Tiunk@@"; return; + case BfTypeCode_UIntUnknown: + name += "Tuunk@@"; return; + default: name += "?"; return; } diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index b58361bf..e1796623 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -4766,7 +4766,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin return *irValuePtr; } - BfTypeInstance* typeInstance = type->ToTypeInstance(); + BfTypeInstance* typeInstance = type->ToTypeInstance(); BfType* typeInstanceType = ResolveTypeDef(mCompiler->mReflectTypeInstanceTypeDef); mBfIRBuilder->PopulateType(typeInstanceType, BfIRPopulateType_Full_ForceDefinition); @@ -4855,6 +4855,11 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin BfMangler::Mangle(typeDataName, mCompiler->GetMangleKind(), type, mContext->mScratchModule); } + if (typeDataName == "sBfTypeData.?") + { + NOP; + } + int typeCode = BfTypeCode_None; if (typeInstance != NULL) @@ -12042,13 +12047,20 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM BF_ASSERT(instModule == mParentModule); } else if (instModule != this) - { + { + if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mMethodInfoEx != NULL) && (mCurMethodInstance->mMethodInfoEx->mMinDependDepth >= 32)) + flags = (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_DepthExceeded); + if ((!mIsReified) && (instModule->mIsReified)) { BF_ASSERT(!mCompiler->mIsResolveOnly); // A resolve-only module is specializing a method from a type in a reified module, // we need to take care that this doesn't cause anything new to become reified - return mContext->mUnreifiedModule->GetMethodInstance(typeInst, methodDef, methodGenericArguments, (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_ExplicitResolveOnlyPass), foreignType); + BfModuleMethodInstance moduleMethodInstance = mContext->mUnreifiedModule->GetMethodInstance(typeInst, methodDef, methodGenericArguments, (BfGetMethodInstanceFlags)(flags | BfGetMethodInstanceFlag_ExplicitResolveOnlyPass), foreignType); + if (!moduleMethodInstance) + return moduleMethodInstance; + SetMethodDependency(moduleMethodInstance.mMethodInstance); + return moduleMethodInstance; } else { @@ -12081,6 +12093,8 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM // Not extern // Create the instance in the proper module and then create a reference in this one moduleMethodInst = instModule->GetMethodInstance(typeInst, methodDef, methodGenericArguments, defFlags, foreignType); + if (!moduleMethodInst) + return moduleMethodInst; tryModuleMethodLookup = true; if ((mIsReified) && (!moduleMethodInst.mMethodInstance->mIsReified)) @@ -12091,7 +12105,10 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM } if (tryModuleMethodLookup) + { + SetMethodDependency(moduleMethodInst.mMethodInstance); return ReferenceExternalMethodInstance(moduleMethodInst.mMethodInstance, flags); + } if (((flags & BfGetMethodInstanceFlag_ForceInline) != 0) && (!methodDef->mAlwaysInline)) { @@ -12422,6 +12439,8 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM if ((methodInstance != NULL) && (!doingRedeclare)) { + SetMethodDependency(methodInstance); + if (methodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_Decl_AwaitingReference) { /*if ((!mCompiler->mIsResolveOnly) && (!isReified)) @@ -12535,7 +12554,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM GetMethodInstance(typeInst, methodDef, BfTypeVector(), BfGetMethodInstanceFlag_UnspecializedPass); } } - + if (methodInstance == NULL) { if (lookupMethodGenericArguments.size() == 0) @@ -12547,7 +12566,18 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM BfLogSysM("Created Default MethodInst: %p TypeInst: %p Group: %p\n", methodInstance, typeInst, methodInstGroup); } else - { + { + bool depthExceeded = ((flags & BfGetMethodInstanceFlag_DepthExceeded) != 0); + + if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mMethodInfoEx != NULL) && (mCurMethodInstance->mMethodInfoEx->mMinDependDepth >= 32)) + depthExceeded = true; + + if (depthExceeded) + { + Fail("Generic method dependency depth exceeded", methodDef->GetRefNode()); + return BfModuleMethodInstance(); + } + BfMethodInstance** methodInstancePtr = NULL; bool added = methodInstGroup->mMethodSpecializationMap->TryAdd(lookupMethodGenericArguments, NULL, &methodInstancePtr); BF_ASSERT(added); @@ -12561,7 +12591,7 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM } if ((prevIRFunc) && (!prevIRFunc.IsFake())) - methodInstance->mIRFunction = prevIRFunc; // Take it over + methodInstance->mIRFunction = prevIRFunc; // Take it over } /*// 24 bits for typeid, 20 for method id, 20 for specialization index @@ -12679,7 +12709,9 @@ BfModuleMethodInstance BfModule::GetMethodInstance(BfTypeInstance* typeInst, BfM { BF_ASSERT(!methodInstance->mIsReified); declareModule = mContext->mUnreifiedModule; - } + } + + SetMethodDependency(methodInstance); SetAndRestoreValue prevMethodInstance(declareModule->mCurMethodInstance, methodInstance); SetAndRestoreValue prevTypeInstance(declareModule->mCurTypeInstance, typeInst); @@ -20214,9 +20246,6 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool { BP_ZONE("BfModule::BfMethodDeclaration"); - // If we are doing this then we may end up creating methods when var types are unknown still, failing on splat/zero-sized info - BF_ASSERT((!mContext->mResolvingVarField) || (mBfIRBuilder->mIgnoreWrites)); - // We could trigger a DoMethodDeclaration from a const resolver or other location, so we reset it here // to effectively make mIgnoreWrites method-scoped SetAndRestoreValue prevIgnoreWrites(mBfIRBuilder->mIgnoreWrites, mWantsIRIgnoreWrites || mCurMethodInstance->mIsUnspecialized); @@ -20228,6 +20257,10 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool if (mCurMethodInstance->mMethodInstanceGroup->mOnDemandKind == BfMethodOnDemandKind_NoDecl_AwaitingReference) mCurMethodInstance->mMethodInstanceGroup->mOnDemandKind = BfMethodOnDemandKind_Decl_AwaitingReference; + + // If we are doing this then we may end up creating methods when var types are unknown still, failing on splat/zero-sized info + BF_ASSERT((!mCurTypeInstance->mResolvingVarField) || (mBfIRBuilder->mIgnoreWrites)); + bool ignoreWrites = mBfIRBuilder->mIgnoreWrites; if ((!isTemporaryFunc) && (mCurTypeInstance->mDefineState < BfTypeDefineState_Defined)) @@ -22256,6 +22289,27 @@ bool BfModule::SlotInterfaceMethod(BfMethodInstance* methodInstance) return true; } +void BfModule::SetMethodDependency(BfMethodInstance* methodInstance) +{ + if (methodInstance->mMethodInfoEx == NULL) + return; + + int wantMinDepth = -1; + + if (mCurTypeInstance != NULL) + wantMinDepth = mCurTypeInstance->mDependencyMap.mMinDependDepth + 1; + + if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mMethodInfoEx != NULL) && (mCurMethodInstance->mMethodInfoEx->mMinDependDepth != -1)) + { + int wantTypeMinDepth = mCurMethodInstance->mMethodInfoEx->mMinDependDepth + 1; + if ((wantMinDepth == -1) || (wantTypeMinDepth < wantMinDepth)) + wantMinDepth = wantTypeMinDepth; + } + + if ((methodInstance->mMethodInfoEx->mMinDependDepth == -1) || (wantMinDepth < methodInstance->mMethodInfoEx->mMinDependDepth)) + methodInstance->mMethodInfoEx->mMinDependDepth = wantMinDepth; +} + void BfModule::DbgFinish() { if ((mBfIRBuilder == NULL) || (mExtensionCount != 0)) diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index d581545f..edd45e73 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1844,6 +1844,7 @@ public: void CompareDeclTypes(BfTypeDef* newDeclType, BfTypeDef* prevDeclType, bool& isBetter, bool& isWorse); bool SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityContext* ambiguityContext = NULL); bool SlotInterfaceMethod(BfMethodInstance* methodInstance); + void SetMethodDependency(BfMethodInstance* methodInstance); BfModuleMethodInstance ReferenceExternalMethodInstance(BfMethodInstance* methodInstance, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None); BfModule* GetOrCreateMethodModule(BfMethodInstance* methodInstance); BfModuleMethodInstance GetMethodInstance(BfTypeInstance* typeInst, BfMethodDef* methodDef, const BfTypeVector& methodGenericArguments, BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None, BfTypeInstance* foreignType = NULL); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index d47b2e5f..95ef0138 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -330,9 +330,7 @@ bool BfModule::ValidateGenericConstraints(BfTypeReference* typeRef, BfTypeInstan return true; } - auto typeDef = genericTypeInst->mTypeDef; - //for (int paramIdx = 0; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size(); paramIdx++) - + auto typeDef = genericTypeInst->mTypeDef; for (int paramIdx = 0; paramIdx < (int)genericTypeInst->mGenericTypeInfo->mGenericParams.size(); paramIdx++) { auto genericParamInstance = genericTypeInst->mGenericTypeInfo->mGenericParams[paramIdx]; @@ -501,6 +499,18 @@ void BfModule::CheckInjectNewRevision(BfTypeInstance* typeInstance) void BfModule::InitType(BfType* resolvedTypeRef, BfPopulateType populateType) { BP_ZONE("BfModule::InitType"); + + if (auto depType = resolvedTypeRef->ToDependedType()) + { + if ((mCurMethodInstance != NULL) && (mCurMethodInstance->mMethodInfoEx != NULL)) + { + depType->mDependencyMap.mMinDependDepth = mCurMethodInstance->mMethodInfoEx->mMinDependDepth + 1; + } + else if (mCurTypeInstance != NULL) + { + depType->mDependencyMap.mMinDependDepth = mCurTypeInstance->mDependencyMap.mMinDependDepth + 1; + } + } SetAndRestoreValue prevTypeInstance(mCurTypeInstance, resolvedTypeRef->ToTypeInstance()); SetAndRestoreValue prevMethodInstance(mCurMethodInstance, NULL); @@ -2143,7 +2153,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy auto _AddStaticSearch = [&](BfTypeDef* typeDef) { if (typeDef->mStaticSearch.IsEmpty()) - return; + return; BfStaticSearch* staticSearch; if (typeInstance->mStaticSearchMap.TryAdd(typeDef, NULL, &staticSearch)) { @@ -2162,9 +2172,9 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy staticSearch->mStaticTypes.Add(staticTypeInst); AddDependency(staticTypeInst, typeInstance, BfDependencyMap::DependencyFlag_StaticValue); } - } + } } - } + } }; if (typeDef->mIsCombinedPartial) @@ -7090,7 +7100,7 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy populateModule->PopulateType(resolvedTypeRef, populateType); if ((genericTypeInstance != NULL) && (genericTypeInstance != mCurTypeInstance) && (populateType > BfPopulateType_Identity)) - { + { bool doValidate = (genericTypeInstance->mGenericTypeInfo->mHadValidateErrors) || (!genericTypeInstance->mGenericTypeInfo->mValidatedGenericConstraints) || (genericTypeInstance->mGenericTypeInfo->mIsUnspecializedVariation); @@ -7102,6 +7112,13 @@ BfType* BfModule::ResolveTypeResult(BfTypeReference* typeRef, BfType* resolvedTy doValidate = false; if (auto curGenericTypeInstance = mCurTypeInstance->ToGenericTypeInstance()) { + if ((curGenericTypeInstance->mDependencyMap.mMinDependDepth > 32) && + (genericTypeInstance->mDependencyMap.mMinDependDepth > 32)) + { + Fail(StrFormat("Generic type dependency depth exceeded for type '{}'", TypeToString(genericTypeInstance).c_str()), typeRef); + return NULL; + } + if (curGenericTypeInstance->mGenericTypeInfo->mHadValidateErrors) doValidate = false; } @@ -7731,9 +7748,15 @@ BfTypedValue BfModule::TryLookupGenericConstVaue(BfIdentifierNode* identifierNod BfExprEvaluator exprEvaluator(this); exprEvaluator.mExpectingType = genericTypeConstraint; - exprEvaluator.GetLiteral(identifierNode, constExprValueType->mValue); + exprEvaluator.GetLiteral(identifierNode, constExprValueType->mValue); + + if (exprEvaluator.mResult) + { + auto castedVal = CastToValue(identifierNode, exprEvaluator.mResult, genericTypeConstraint, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_SilentFail)); + if (castedVal) + return BfTypedValue(castedVal, genericTypeConstraint); + } - // We don't want to validate type here return exprEvaluator.mResult; } else if (genericParamResult->IsGenericParam()) @@ -8732,7 +8755,7 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula for (auto genericArgRef : genericArguments) { - auto genericArg = ResolveTypeRef(genericArgRef, BfPopulateType_Identity, BfResolveTypeRefFlag_AllowGenericMethodParamConstValue); + auto genericArg = ResolveTypeRef(genericArgRef, BfPopulateType_Identity, (BfResolveTypeRefFlags)(BfResolveTypeRefFlag_AllowGenericTypeParamConstValue | BfResolveTypeRefFlag_AllowGenericMethodParamConstValue)); if (genericArg == NULL) { mContext->mResolvedTypes.RemoveEntry(resolvedEntry); @@ -8816,10 +8839,16 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula auto genericArg = genericArgs[genericParamIdx + startDefGenericParamIdx]; genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.push_back(genericArg); genericTypeInst->mGenericTypeInfo->mTypeGenericArgumentRefs.push_back(genericArgRef); + + if (genericArg->IsConstExprValue()) + { + NOP; + } + genericParamIdx++; } - resolvedEntry->mValue = genericTypeInst; + resolvedEntry->mValue = genericTypeInst; CheckUnspecializedGenericType(genericTypeInst, populateType); populateModule->InitType(genericTypeInst, populateType); @@ -9290,22 +9319,29 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula return ResolveTypeRef(constTypeRef->mElementType, populateType, (BfResolveTypeRefFlags)(resolveFlags & BfResolveTypeRefFlag_NoResolveGenericParam)); } else if (auto constExprTypeRef = BfNodeDynCastExact(typeRef)) - { + { + if ((mCurTypeInstance != NULL) && (mCurTypeInstance->mDependencyMap.mMinDependDepth > 32)) + { + Fail("Generic type dependency depth exceeded", typeRef); + mContext->mResolvedTypes.RemoveEntry(resolvedEntry); + return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags); + } + + BfVariant result; + BfType* resultType = NULL; + if (constExprTypeRef->mConstExpr != NULL) + { + result = mContext->mResolvedTypes.EvaluateToVariant(&lookupCtx, constExprTypeRef->mConstExpr, resultType); + BF_ASSERT(resultType != NULL); + } + auto constExprType = new BfConstExprValueType(); constExprType->mContext = mContext; - BfVariant result; - if (constExprTypeRef->mConstExpr != NULL) - { - BfType* constGenericParam = NULL; - result = mContext->mResolvedTypes.EvaluateToVariant(&lookupCtx, constExprTypeRef->mConstExpr, constGenericParam); - BF_ASSERT(constGenericParam == NULL); - } - - constExprType->mType = GetPrimitiveType(result.mTypeCode); + constExprType->mType = resultType; BF_ASSERT(constExprType->mType != NULL); if (constExprType->mType == NULL) - constExprType->mType = GetPrimitiveType(BfTypeCode_IntPtr); + constExprType->mType = GetPrimitiveType(BfTypeCode_Let); constExprType->mValue = result; resolvedEntry->mValue = constExprType; @@ -9318,8 +9354,9 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula } BF_ASSERT(BfResolvedTypeSet::Equals(constExprType, typeRef, &lookupCtx)); #endif + + populateModule->InitType(constExprType, populateType); - populateModule->InitType(constExprType, populateType); return constExprType; } else @@ -11689,6 +11726,9 @@ void BfModule::VariantToString(StringImpl& str, const BfVariant& variant) str += ".0"; } break; + case BfTypeCode_Let: + str += "?"; + break; default: break; } } @@ -12165,7 +12205,7 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF { auto constExprValueType = (BfConstExprValueType*)resolvedType; str += "const "; - + DoTypeToString(str, constExprValueType->mType, typeNameFlags, genericMethodNameOverrides); str += " "; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp index c504680e..aad6e6a7 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.cpp +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.cpp @@ -74,6 +74,16 @@ bool BfDependencyMap::AddUsedBy(BfType* dependentType, BfDependencyMap::Dependen DependencyEntry* dependencyEntry = NULL; if (mTypeSet.TryAddRaw(dependentType, NULL, &dependencyEntry)) { + if ((flags & ~DependencyFlag_UnspecializedType) != 0) + { + if (auto dependentDepType = dependentType->ToDependedType()) + { + int tryDepth = dependentDepType->mDependencyMap.mMinDependDepth + 1; + if (tryDepth < mMinDependDepth) + mMinDependDepth = tryDepth; + } + } + dependencyEntry->mRevision = dependentType->mRevision; dependencyEntry->mFlags = flags; return true; @@ -1344,7 +1354,10 @@ void BfCustomAttributes::ReportMemory(MemReporter* memReporter) BfModuleMethodInstance::BfModuleMethodInstance(BfMethodInstance* methodInstance) { mMethodInstance = methodInstance; - mFunc = mMethodInstance->mIRFunction; + if (methodInstance != NULL) + mFunc = mMethodInstance->mIRFunction; + else + mFunc = BfIRValue(); // if (methodInstance->GetImportCallKind() == BfImportCallKind_Thunk) // { // auto declModule = methodInstance->mDeclModule; @@ -2515,18 +2528,19 @@ BfResolvedTypeSet::~BfResolvedTypeSet() #define HASH_CONSTEXPR 12 #define HASH_GLOBAL 13 -BfVariant BfResolvedTypeSet::EvaluateToVariant(LookupContext* ctx, BfExpression* expr, BfType*& constGenericParam) +BfVariant BfResolvedTypeSet::EvaluateToVariant(LookupContext* ctx, BfExpression* expr, BfType*& outType) { BfConstResolver constResolver(ctx->mModule); BfVariant variant = { BfTypeCode_None }; + constResolver.mAllowGenericConstValue = true; auto result = constResolver.Resolve(expr); - if (result) - { + outType = result.mType; + if (result) + { if (result.mKind == BfTypedValueKind_GenericConstValue) - { - constGenericParam = result.mType; + { return variant; - } + } else { variant = ctx->mModule->TypedValueToVariant(expr, result, true); @@ -2709,7 +2723,9 @@ int BfResolvedTypeSet::Hash(BfType* type, LookupContext* ctx, bool allowRef) else if (type->IsConstExprValue()) { BfConstExprValueType* constExprValueType = (BfConstExprValueType*)type; - return ((int)constExprValueType->mValue.mTypeCode << 17) ^ (constExprValueType->mValue.mInt32 << 3) ^ HASH_CONSTTYPE; + int hashVal = ((int)constExprValueType->mValue.mTypeCode << 17) ^ (constExprValueType->mValue.mInt32 << 3) ^ HASH_CONSTTYPE; + hashVal = ((hashVal ^ (Hash(constExprValueType->mType, ctx, BfHashFlag_AllowRef))) << 5) - hashVal; + return hashVal; } else { @@ -3216,21 +3232,23 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash else if (auto constExprTypeRef = BfNodeDynCastExact(typeRef)) { BfVariant result; + BfType* resultType = NULL; if (constExprTypeRef->mConstExpr != NULL) { - BfType* constGenericParam = NULL; - result = EvaluateToVariant(ctx, constExprTypeRef->mConstExpr, constGenericParam); - if (constGenericParam != NULL) - return Hash(constGenericParam, ctx); + result = EvaluateToVariant(ctx, constExprTypeRef->mConstExpr, resultType); + if ((resultType != NULL) && (resultType->IsGenericParam())) + return Hash(resultType, ctx); } - if (result.mTypeCode == BfTypeCode_None) + if (resultType == NULL) { ctx->mFailed = true; return 0; } - return ((int)result.mTypeCode << 17) ^ (result.mInt32 << 3) ^ HASH_CONSTTYPE; + auto hashVal = ((int)result.mTypeCode << 17) ^ (result.mInt32 << 3) ^ HASH_CONSTTYPE; + hashVal = ((hashVal ^ (Hash(resultType, ctx, BfHashFlag_AllowRef))) << 5) - hashVal; + return hashVal; } else if (auto dotTypeRef = BfNodeDynCastExact(typeRef)) { @@ -3884,9 +3902,9 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext* if (constExprTypeRef->mConstExpr == NULL) return false; - BfType* constGenericParam = NULL; - result = EvaluateToVariant(ctx, constExprTypeRef->mConstExpr, constGenericParam); - return constGenericParam == lhs; + BfType* resultType = NULL; + result = EvaluateToVariant(ctx, constExprTypeRef->mConstExpr, resultType); + return resultType == lhs; } return false; @@ -3999,9 +4017,9 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext* BfVariant result; if (constExprTypeRef->mConstExpr != NULL) { - BfType* constGenericParam = NULL; - result = EvaluateToVariant(ctx, constExprTypeRef->mConstExpr, constGenericParam); - if (constGenericParam != NULL) + BfType* resultType = NULL; + result = EvaluateToVariant(ctx, constExprTypeRef->mConstExpr, resultType); + if (resultType != lhsConstExprType->mType) return false; } @@ -4455,4 +4473,8 @@ int BfTypeUtils::GetSplatCount(BfType* type) return splatCount; } - +BfConstExprValueType::~BfConstExprValueType() +{ +// mContext->mTypeConstExprCount--; +// BF_ASSERT(mContext->mTypeConstExprCount == 0); +} diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index f1b29141..958c42bd 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -69,7 +69,8 @@ enum BfGetMethodInstanceFlags : uint16 BfGetMethodInstanceFlag_ForceInline = 0x80, BfGetMethodInstanceFlag_Friend = 0x100, BfGetMethodInstanceFlag_DisableObjectAccessChecks = 0x200, - BfGetMethodInstanceFlag_NoInline = 0x400 + BfGetMethodInstanceFlag_NoInline = 0x400, + BfGetMethodInstanceFlag_DepthExceeded = 0x800 }; class BfDependencyMap @@ -109,12 +110,12 @@ public: struct DependencyEntry { - int mRevision; + int mRevision; DependencyFlags mFlags; DependencyEntry(int revision, DependencyFlags flags) { - mRevision = revision; + mRevision = revision; mFlags = flags; } }; @@ -122,8 +123,14 @@ public: public: typedef Dictionary TypeMap; TypeMap mTypeSet; + int mMinDependDepth; public: + BfDependencyMap() + { + mMinDependDepth = 0; + } + bool AddUsedBy(BfType* dependentType, DependencyFlags flags); bool IsEmpty(); TypeMap::iterator begin(); @@ -761,6 +768,7 @@ public: BfTypeVector mMethodGenericArguments; Dictionary mGenericTypeBindings; BfMethodCustomAttributes* mMethodCustomAttributes; + int mMinDependDepth; BfMethodInfoEx() { @@ -768,6 +776,7 @@ public: mForeignType = NULL; mClosureInstanceInfo = NULL; mMethodCustomAttributes = NULL; + mMinDependDepth = -1; } ~BfMethodInfoEx(); @@ -1701,7 +1710,7 @@ public: bool mValidatedGenericConstraints; bool mHadValidateErrors; bool mInitializedGenericParams; - bool mFinishedGenericParams; + bool mFinishedGenericParams; Array mProjectsReferenced; // Generic methods that only refer to these projects don't need a specialized extension public: @@ -2300,6 +2309,8 @@ public: BfVariant mValue; public: + ~BfConstExprValueType(); + virtual bool IsConstExprValue() override { return true; } virtual BfType* GetUnderlyingType() override { return mType; } }; @@ -2397,7 +2408,7 @@ public: public: static BfTypeDef* FindRootCommonOuterType(BfTypeDef* outerType, LookupContext* ctx, BfTypeInstance*& outCheckTypeInstance); - static BfVariant EvaluateToVariant(LookupContext* ctx, BfExpression* expr, BfType*& constGenericParam); + static BfVariant EvaluateToVariant(LookupContext* ctx, BfExpression* expr, BfType*& outType); static bool GenericTypeEquals(BfTypeInstance* lhsGenericType, BfTypeVector* lhsTypeGenericArguments, BfTypeReference* rhs, LookupContext* ctx, int& genericParamOffset); static bool GenericTypeEquals(BfTypeInstance* lhsGenericType, BfTypeVector* typeGenericArguments, BfTypeReference* rhs, BfTypeDef* rhsTypeDef, LookupContext* ctx); static void HashGenericArguments(BfTypeReference* typeRef, LookupContext* ctx, int& hash); diff --git a/IDEHelper/Tests/src/ConstExprs.bf b/IDEHelper/Tests/src/ConstExprs.bf new file mode 100644 index 00000000..4eb87250 --- /dev/null +++ b/IDEHelper/Tests/src/ConstExprs.bf @@ -0,0 +1,62 @@ +#pragma warning disable 168 +using System; +namespace Tests +{ + class ConstExprs + { + enum EnumA + { + A, + B, + C + } + + class ClassA where TSize : const int + { + public int GetVal() + { + return TSize; + } + } + + class ClassB where TSize : const int + { + ClassA mVal = new ClassA(); + var mVal2 = new ClassA(); + + public int GetVal() + { + return mVal.GetVal(); + } + + public int GetVal2() + { + return mVal2.GetVal(); + } + } + + class ClassC where TEnum : const EnumA + { + public int Test() + { + EnumA ea = TEnum; + if (TEnum == .A) + { + return 1; + } + return 0; + } + } + + [Test] + public static void TestBasics() + { + ClassB cb = scope .(); + Test.Assert(cb.GetVal() == 123); + Test.Assert(cb.GetVal2() == 223); + + ClassC cc = scope .(); + Test.Assert(cc.Test() == 1); + } + } +}