| 5034 | } |
| 5035 | |
| 5036 | void BfModule::CreateDynamicCastMethod() |
| 5037 | { |
| 5038 | auto objType = mContext->mBfObjectType; |
| 5039 | |
| 5040 | if ((mCompiler->mIsResolveOnly) || (!mIsReified)) |
| 5041 | { |
| 5042 | // The main reason to punt on this method for ResolveOnly is because types can be created |
| 5043 | // and destroyed quickly during autocomplete and the typeId creep can generate lots of |
| 5044 | // entries in the LLVM ConstantInt pool, primarily from the FindSubTypes call. We can |
| 5045 | // remove this punt when we recycle typeId's |
| 5046 | mBfIRBuilder->CreateRet(mBfIRBuilder->CreateConstNull(mBfIRBuilder->MapTypeInstPtr(objType))); |
| 5047 | mCurMethodState->mHadReturn = true; |
| 5048 | return; |
| 5049 | } |
| 5050 | |
| 5051 | bool isInterfacePass = mCurMethodInstance->mMethodDef->mName == BF_METHODNAME_DYNAMICCAST_INTERFACE; |
| 5052 | |
| 5053 | auto func = mCurMethodState->mIRFunction; |
| 5054 | auto thisValue = mBfIRBuilder->GetArgument(0); |
| 5055 | auto typeIdValue = mBfIRBuilder->GetArgument(1); |
| 5056 | |
| 5057 | auto intPtrType = GetPrimitiveType(BfTypeCode_IntPtr); |
| 5058 | auto int32Type = GetPrimitiveType(BfTypeCode_Int32); |
| 5059 | typeIdValue = CastToValue(NULL, BfTypedValue(typeIdValue, intPtrType), int32Type, (BfCastFlags)(BfCastFlags_Explicit | BfCastFlags_SilentFail)); |
| 5060 | |
| 5061 | auto thisObject = mBfIRBuilder->CreateBitCast(thisValue, mBfIRBuilder->MapType(objType)); |
| 5062 | |
| 5063 | auto trueBB = mBfIRBuilder->CreateBlock("check.true"); |
| 5064 | //auto falseBB = mBfIRBuilder->CreateBlock("check.false"); |
| 5065 | auto exitBB = mBfIRBuilder->CreateBlock("exit"); |
| 5066 | |
| 5067 | SizedArray<int, 8> typeMatches; |
| 5068 | SizedArray<BfTypeInstance*, 8> exChecks; |
| 5069 | FindSubTypes(mCurTypeInstance, &typeMatches, &exChecks, isInterfacePass); |
| 5070 | |
| 5071 | if ((mCurTypeInstance->IsGenericTypeInstance()) && (!mCurTypeInstance->IsUnspecializedType())) |
| 5072 | { |
| 5073 | // Add 'unbound' type id to cast list so things like "List<int> is List<>" work |
| 5074 | auto genericTypeInst = mCurTypeInstance->mTypeDef; |
| 5075 | BfTypeVector genericArgs; |
| 5076 | for (int i = 0; i < (int) genericTypeInst->mGenericParamDefs.size(); i++) |
| 5077 | genericArgs.push_back(GetGenericParamType(BfGenericParamKind_Type, i)); |
| 5078 | auto unboundType = ResolveTypeDef(mCurTypeInstance->mTypeDef->GetDefinition(), genericArgs, BfPopulateType_Declaration); |
| 5079 | typeMatches.push_back(unboundType->mTypeId); |
| 5080 | } |
| 5081 | |
| 5082 | if (mCurTypeInstance->IsBoxed()) |
| 5083 | { |
| 5084 | BfBoxedType* boxedType = (BfBoxedType*)mCurTypeInstance; |
| 5085 | BfTypeInstance* innerType = boxedType->mElementType->ToTypeInstance(); |
| 5086 | |
| 5087 | FindSubTypes(innerType, &typeMatches, &exChecks, isInterfacePass); |
| 5088 | |
| 5089 | if (innerType->IsTypedPrimitive()) |
| 5090 | { |
| 5091 | auto underlyingType = innerType->GetUnderlyingType(); |
| 5092 | typeMatches.push_back(underlyingType->mTypeId); |
| 5093 | } |
nothing calls this directly
no test coverage detected