From d6566982f2df807796a622014168eac6ea60a07c Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Thu, 30 Jan 2020 07:06:16 -0800 Subject: [PATCH] Boxing result change, warning on boxing obj, boxing generics --- IDEHelper/Compiler/BfExprEvaluator.cpp | 45 ++++++++++++++---------- IDEHelper/Compiler/BfModule.cpp | 14 ++++++-- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 24 +++++++++++-- IDEHelper/Compiler/BfResolvedTypeUtils.h | 4 +-- 4 files changed, 60 insertions(+), 27 deletions(-) diff --git a/IDEHelper/Compiler/BfExprEvaluator.cpp b/IDEHelper/Compiler/BfExprEvaluator.cpp index 46763a9a..42de1f5b 100644 --- a/IDEHelper/Compiler/BfExprEvaluator.cpp +++ b/IDEHelper/Compiler/BfExprEvaluator.cpp @@ -1939,7 +1939,7 @@ void BfMethodMatcher::TryDevirtualizeCall(BfTypedValue target, BfTypedValue* ori auto boxedMethodInstance = useModule->ReferenceExternalMethodInstance(methodRef.mImplementingMethod); BfBoxedType* vBoxedType = (BfBoxedType*)methodRef.mImplementingMethod.mTypeInstance; - mBestMethodTypeInstance = vBoxedType->mElementType; + mBestMethodTypeInstance = vBoxedType->mElementType->ToTypeInstance(); mBestMethodInstance = mModule->GetMethodInstance(mBestMethodTypeInstance, boxedMethodInstance.mMethodInstance->mMethodDef, BfTypeVector()); mBestMethodDef = mBestMethodInstance.mMethodInstance->mMethodDef; } @@ -11752,38 +11752,45 @@ void BfExprEvaluator::Visit(BfBoxExpression* boxExpr) auto exprValue = mModule->CreateValueFromExpression(boxExpr->mExpression); if (exprValue) { + bool doFail = false; + bool doWarn = false; + if (exprValue.mType->IsGenericParam()) { BF_ASSERT(mModule->mCurMethodInstance->mIsUnspecialized); auto genericParamTarget = (BfGenericParamType*)exprValue.mType; auto genericParamInstance = mModule->GetGenericParamInstance(genericParamTarget); - bool isBoxable = false; + + if ((genericParamInstance->mGenericParamFlags & (BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr | BfGenericParamFlag_Class)) == BfGenericParamFlag_Class) + doWarn = true; - if (genericParamInstance->mGenericParamFlags & (BfGenericParamFlag_Struct | BfGenericParamFlag_StructPtr)) - isBoxable = true; - - if ((genericParamInstance->mTypeConstraint != NULL) && (exprValue.mType->IsValueTypeOrValueTypePtr())) - isBoxable = true; - - if (isBoxable) - { - mResult = mModule->GetDefaultTypedValue(mModule->mContext->mBfObjectType); - return; - } + if ((genericParamInstance->mTypeConstraint != NULL) && (genericParamInstance->mTypeConstraint->IsObjectOrInterface())) + doWarn = true; + } + else + { + doFail = !exprValue.mType->IsValueTypeOrValueTypePtr(); + doWarn = exprValue.mType->IsObjectOrInterface(); } - if (!exprValue.mType->IsValueTypeOrValueTypePtr()) + if (doWarn) + { + mModule->Warn(0, StrFormat("Boxing is unnecessary since type '%s' is already a reference type.", mModule->TypeToString(exprValue.mType).c_str()), boxExpr->mExpression); + mResult = exprValue; + return; + } + + if (doFail) { mModule->Fail(StrFormat("Box target '%s' must be a value type or pointer to a value type", mModule->TypeToString(exprValue.mType).c_str()), boxExpr->mExpression); return; } - //BfType* boxedType = mModule->CreateBoxedType(exprValue.mType); - - //auto scopeData = mModule->FindScope(boxExpr->mAllocNode); - - mResult = mModule->BoxValue(boxExpr->mExpression, exprValue, mModule->mContext->mBfObjectType, allocTarget); + BfType* boxedType = mModule->CreateBoxedType(exprValue.mType); + if (boxedType == NULL) + boxedType = mModule->mContext->mBfObjectType; + mResult = mModule->BoxValue(boxExpr->mExpression, exprValue, boxedType, allocTarget); if (!mResult) { mModule->Fail(StrFormat("Type '%s' is not boxable", mModule->TypeToString(exprValue.mType).c_str()), boxExpr->mExpression); diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index c25d8d3e..50dda3a7 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -3653,7 +3653,7 @@ void BfModule::CreateDynamicCastMethod() if (mCurTypeInstance->IsBoxed()) { BfBoxedType* boxedType = (BfBoxedType*)mCurTypeInstance; - BfTypeInstance* innerType = boxedType->mElementType; + BfTypeInstance* innerType = boxedType->mElementType->ToTypeInstance(); FindSubTypes(innerType, &typeMatches, &exChecks, isInterfacePass); @@ -8425,6 +8425,14 @@ BfTypedValue BfModule::BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp { if (toType == mContext->mBfObjectType) return BfTypedValue(mBfIRBuilder->GetFakeVal(), toType); + if (toType->IsBoxed()) + { + BfBoxedType* boxedType = (BfBoxedType*)toType; + if (typedVal.mType == boxedType->mElementType) + return BfTypedValue(mBfIRBuilder->GetFakeVal(), toType); + else + return BfTypedValue(); + } } BP_ZONE("BoxValue"); @@ -16900,7 +16908,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) mBfIRBuilder->ClearDebugLocation(); BfBoxedType* boxedType = (BfBoxedType*) mCurTypeInstance; - BfTypeInstance* innerType = boxedType->mElementType; + BfTypeInstance* innerType = boxedType->mElementType->ToTypeInstance(); PopulateType(innerType, BfPopulateType_DataAndMethods); mBfIRBuilder->PopulateType(mCurTypeInstance); BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None; @@ -19246,7 +19254,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool { auto boxedType = (BfBoxedType*)mCurTypeInstance; // If we failed a lookup here then we better have also failed it in the original type - BF_ASSERT(boxedType->mElementType->mModule->mHadBuildError || mContext->mFailTypes.Contains(boxedType->mElementType)); + BF_ASSERT(boxedType->mElementType->ToTypeInstance()->mModule->mHadBuildError || mContext->mFailTypes.Contains(boxedType->mElementType->ToTypeInstance())); } } diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index f7294850..6851d835 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -4774,13 +4774,16 @@ BfBoxedType* BfModule::CreateBoxedType(BfType* resolvedTypeRef) } BfTypeInstance* typeInst = resolvedTypeRef->ToTypeInstance(); - if (typeInst == NULL) + if ((typeInst == NULL) && (!resolvedTypeRef->IsGenericParam())) return NULL; auto boxedType = mContext->mBoxedTypePool.Get(); boxedType->mContext = mContext; - boxedType->mElementType = typeInst; - boxedType->mTypeDef = boxedType->mElementType->mTypeDef; + boxedType->mElementType = resolvedTypeRef; + if (typeInst != NULL) + boxedType->mTypeDef = typeInst->mTypeDef; + else + boxedType->mTypeDef = mCompiler->mValueTypeTypeDef; boxedType->mBoxedFlags = isStructPtr ? BfBoxedType::BoxedFlags_StructPtr : BfBoxedType::BoxedFlags_None; auto resolvedBoxedType = ResolveType(boxedType); if (resolvedBoxedType != boxedType) @@ -9102,6 +9105,21 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp } } + if (typedVal.mType->IsBoxed()) + { + BfBoxedType* boxedType = (BfBoxedType*)typedVal.mType; + if (boxedType->mElementType->IsGenericParam()) + { + // If we have a boxed generic param, the actual available interfaces constraints won't be + // handled, so we need to pass through again as the root generic param + BfTypedValue unboxedValue = typedVal; + unboxedValue.mType = boxedType->mElementType; + auto result = CastToValue(srcNode, unboxedValue, toType, (BfCastFlags)(castFlags | BfCastFlags_SilentFail), resultFlags); + if (result) + return result; + } + } + if (mayBeBox) { BfScopeData* scopeData = NULL; diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 3fd3977a..1c44a34a 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -1579,7 +1579,7 @@ public: Array mVirtualMethodTable; BfHotTypeData* mHotTypeData; int mVirtualMethodTableSize; // With hot reloading, mVirtualMethodTableSize can be larger than mInterfaceMethodTable (live vtable versioning) - Array mFieldInstances; + Array mFieldInstances; Array mInternalMethods; Dictionary mStaticSearchMap; bool mHasStaticInitMethod; @@ -1744,7 +1744,7 @@ public: }; public: - BfTypeInstance* mElementType; + BfType* mElementType; BfBoxedType* mBoxedBaseType; BoxedFlags mBoxedFlags;