1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 19:48:20 +02:00

Boxing result change, warning on boxing obj, boxing generics

This commit is contained in:
Brian Fiete 2020-01-30 07:06:16 -08:00
parent 17fbd8f8d6
commit d6566982f2
4 changed files with 60 additions and 27 deletions

View file

@ -1939,7 +1939,7 @@ void BfMethodMatcher::TryDevirtualizeCall(BfTypedValue target, BfTypedValue* ori
auto boxedMethodInstance = useModule->ReferenceExternalMethodInstance(methodRef.mImplementingMethod); auto boxedMethodInstance = useModule->ReferenceExternalMethodInstance(methodRef.mImplementingMethod);
BfBoxedType* vBoxedType = (BfBoxedType*)methodRef.mImplementingMethod.mTypeInstance; BfBoxedType* vBoxedType = (BfBoxedType*)methodRef.mImplementingMethod.mTypeInstance;
mBestMethodTypeInstance = vBoxedType->mElementType; mBestMethodTypeInstance = vBoxedType->mElementType->ToTypeInstance();
mBestMethodInstance = mModule->GetMethodInstance(mBestMethodTypeInstance, boxedMethodInstance.mMethodInstance->mMethodDef, BfTypeVector()); mBestMethodInstance = mModule->GetMethodInstance(mBestMethodTypeInstance, boxedMethodInstance.mMethodInstance->mMethodDef, BfTypeVector());
mBestMethodDef = mBestMethodInstance.mMethodInstance->mMethodDef; mBestMethodDef = mBestMethodInstance.mMethodInstance->mMethodDef;
} }
@ -11752,38 +11752,45 @@ void BfExprEvaluator::Visit(BfBoxExpression* boxExpr)
auto exprValue = mModule->CreateValueFromExpression(boxExpr->mExpression); auto exprValue = mModule->CreateValueFromExpression(boxExpr->mExpression);
if (exprValue) if (exprValue)
{ {
bool doFail = false;
bool doWarn = false;
if (exprValue.mType->IsGenericParam()) if (exprValue.mType->IsGenericParam())
{ {
BF_ASSERT(mModule->mCurMethodInstance->mIsUnspecialized); BF_ASSERT(mModule->mCurMethodInstance->mIsUnspecialized);
auto genericParamTarget = (BfGenericParamType*)exprValue.mType; auto genericParamTarget = (BfGenericParamType*)exprValue.mType;
auto genericParamInstance = mModule->GetGenericParamInstance(genericParamTarget); 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)) if ((genericParamInstance->mTypeConstraint != NULL) && (genericParamInstance->mTypeConstraint->IsObjectOrInterface()))
isBoxable = true; doWarn = true;
}
if ((genericParamInstance->mTypeConstraint != NULL) && (exprValue.mType->IsValueTypeOrValueTypePtr())) else
isBoxable = true; {
doFail = !exprValue.mType->IsValueTypeOrValueTypePtr();
if (isBoxable) doWarn = exprValue.mType->IsObjectOrInterface();
{
mResult = mModule->GetDefaultTypedValue(mModule->mContext->mBfObjectType);
return;
}
} }
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); 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; return;
} }
//BfType* boxedType = mModule->CreateBoxedType(exprValue.mType); BfType* boxedType = mModule->CreateBoxedType(exprValue.mType);
if (boxedType == NULL)
//auto scopeData = mModule->FindScope(boxExpr->mAllocNode); boxedType = mModule->mContext->mBfObjectType;
mResult = mModule->BoxValue(boxExpr->mExpression, exprValue, boxedType, allocTarget);
mResult = mModule->BoxValue(boxExpr->mExpression, exprValue, mModule->mContext->mBfObjectType, allocTarget);
if (!mResult) if (!mResult)
{ {
mModule->Fail(StrFormat("Type '%s' is not boxable", mModule->TypeToString(exprValue.mType).c_str()), boxExpr->mExpression); mModule->Fail(StrFormat("Type '%s' is not boxable", mModule->TypeToString(exprValue.mType).c_str()), boxExpr->mExpression);

View file

@ -3653,7 +3653,7 @@ void BfModule::CreateDynamicCastMethod()
if (mCurTypeInstance->IsBoxed()) if (mCurTypeInstance->IsBoxed())
{ {
BfBoxedType* boxedType = (BfBoxedType*)mCurTypeInstance; BfBoxedType* boxedType = (BfBoxedType*)mCurTypeInstance;
BfTypeInstance* innerType = boxedType->mElementType; BfTypeInstance* innerType = boxedType->mElementType->ToTypeInstance();
FindSubTypes(innerType, &typeMatches, &exChecks, isInterfacePass); FindSubTypes(innerType, &typeMatches, &exChecks, isInterfacePass);
@ -8425,6 +8425,14 @@ BfTypedValue BfModule::BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
{ {
if (toType == mContext->mBfObjectType) if (toType == mContext->mBfObjectType)
return BfTypedValue(mBfIRBuilder->GetFakeVal(), toType); 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"); BP_ZONE("BoxValue");
@ -16900,7 +16908,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
mBfIRBuilder->ClearDebugLocation(); mBfIRBuilder->ClearDebugLocation();
BfBoxedType* boxedType = (BfBoxedType*) mCurTypeInstance; BfBoxedType* boxedType = (BfBoxedType*) mCurTypeInstance;
BfTypeInstance* innerType = boxedType->mElementType; BfTypeInstance* innerType = boxedType->mElementType->ToTypeInstance();
PopulateType(innerType, BfPopulateType_DataAndMethods); PopulateType(innerType, BfPopulateType_DataAndMethods);
mBfIRBuilder->PopulateType(mCurTypeInstance); mBfIRBuilder->PopulateType(mCurTypeInstance);
BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None; BfGetMethodInstanceFlags flags = BfGetMethodInstanceFlag_None;
@ -19246,7 +19254,7 @@ void BfModule::DoMethodDeclaration(BfMethodDeclaration* methodDeclaration, bool
{ {
auto boxedType = (BfBoxedType*)mCurTypeInstance; auto boxedType = (BfBoxedType*)mCurTypeInstance;
// If we failed a lookup here then we better have also failed it in the original type // 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()));
} }
} }

View file

@ -4774,13 +4774,16 @@ BfBoxedType* BfModule::CreateBoxedType(BfType* resolvedTypeRef)
} }
BfTypeInstance* typeInst = resolvedTypeRef->ToTypeInstance(); BfTypeInstance* typeInst = resolvedTypeRef->ToTypeInstance();
if (typeInst == NULL) if ((typeInst == NULL) && (!resolvedTypeRef->IsGenericParam()))
return NULL; return NULL;
auto boxedType = mContext->mBoxedTypePool.Get(); auto boxedType = mContext->mBoxedTypePool.Get();
boxedType->mContext = mContext; boxedType->mContext = mContext;
boxedType->mElementType = typeInst; boxedType->mElementType = resolvedTypeRef;
boxedType->mTypeDef = boxedType->mElementType->mTypeDef; if (typeInst != NULL)
boxedType->mTypeDef = typeInst->mTypeDef;
else
boxedType->mTypeDef = mCompiler->mValueTypeTypeDef;
boxedType->mBoxedFlags = isStructPtr ? BfBoxedType::BoxedFlags_StructPtr : BfBoxedType::BoxedFlags_None; boxedType->mBoxedFlags = isStructPtr ? BfBoxedType::BoxedFlags_StructPtr : BfBoxedType::BoxedFlags_None;
auto resolvedBoxedType = ResolveType(boxedType); auto resolvedBoxedType = ResolveType(boxedType);
if (resolvedBoxedType != 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) if (mayBeBox)
{ {
BfScopeData* scopeData = NULL; BfScopeData* scopeData = NULL;

View file

@ -1579,7 +1579,7 @@ public:
Array<BfVirtualMethodEntry> mVirtualMethodTable; Array<BfVirtualMethodEntry> mVirtualMethodTable;
BfHotTypeData* mHotTypeData; BfHotTypeData* mHotTypeData;
int mVirtualMethodTableSize; // With hot reloading, mVirtualMethodTableSize can be larger than mInterfaceMethodTable (live vtable versioning) int mVirtualMethodTableSize; // With hot reloading, mVirtualMethodTableSize can be larger than mInterfaceMethodTable (live vtable versioning)
Array<BfFieldInstance> mFieldInstances; Array<BfFieldInstance> mFieldInstances;
Array<BfMethodInstance*> mInternalMethods; Array<BfMethodInstance*> mInternalMethods;
Dictionary<BfTypeDef*, BfStaticSearch> mStaticSearchMap; Dictionary<BfTypeDef*, BfStaticSearch> mStaticSearchMap;
bool mHasStaticInitMethod; bool mHasStaticInitMethod;
@ -1744,7 +1744,7 @@ public:
}; };
public: public:
BfTypeInstance* mElementType; BfType* mElementType;
BfBoxedType* mBoxedBaseType; BfBoxedType* mBoxedBaseType;
BoxedFlags mBoxedFlags; BoxedFlags mBoxedFlags;