From 8def1d45228bc3ea860ce157cd77fc13d6d57199 Mon Sep 17 00:00:00 2001 From: Brian Fiete Date: Mon, 14 Sep 2020 06:54:49 -0700 Subject: [PATCH] Reflection changes - interface info, boxed type --- BeefLibs/corlib/src/Reflection/MethodInfo.bf | 129 ++++++++++++--- BeefLibs/corlib/src/Type.bf | 45 ++++-- IDE/mintest/minlib/src/System/Type.bf | 36 ++++- IDEHelper/Compiler/BfCompiler.cpp | 11 +- IDEHelper/Compiler/BfCompiler.h | 1 + IDEHelper/Compiler/BfModule.cpp | 155 +++++++++++++++---- IDEHelper/Compiler/BfModule.h | 8 +- IDEHelper/Compiler/BfModuleTypeUtils.cpp | 48 +++--- IDEHelper/Compiler/BfResolvedTypeUtils.h | 8 +- IDEHelper/Compiler/BfStmtEvaluator.cpp | 2 +- IDEHelper/Compiler/BfSystem.h | 15 +- 11 files changed, 350 insertions(+), 108 deletions(-) diff --git a/BeefLibs/corlib/src/Reflection/MethodInfo.bf b/BeefLibs/corlib/src/Reflection/MethodInfo.bf index 499aa0cf..28274ae0 100644 --- a/BeefLibs/corlib/src/Reflection/MethodInfo.bf +++ b/BeefLibs/corlib/src/Reflection/MethodInfo.bf @@ -251,6 +251,8 @@ namespace System.Reflection } } + void* funcPtr = null; + int ifaceOffset = -1; if (mMethodData.mFlags.HasFlag(.Static)) { if (target.HasValue) @@ -260,9 +262,45 @@ namespace System.Reflection { if (!target.HasValue) return .Err(.TargetExpected); + var thisType = mTypeInstance; + if (mTypeInstance.IsInterface) + { + if (target.IsObject) + { + var targetObject = target.Get(); + thisType = targetObject.GetType() as TypeInstance; + if (thisType == null) + return .Err(.InvalidTarget); + } + else + { + TypeInstance.InterfaceData* interfaceData = null; + var checkType = thisType; + CheckLoop: while (checkType != null) + { + for (int ifaceIdx < checkType.[Friend]mInterfaceCount) + { + if (checkType.[Friend]mInterfaceDataPtr[ifaceIdx].mInterfaceType == mTypeInstance.TypeId) + { + interfaceData = &checkType.[Friend]mInterfaceDataPtr[ifaceIdx]; + break CheckLoop; + } + } - bool splatThis = mTypeInstance.IsSplattable && !mMethodData.mFlags.HasFlag(.Mutating); - AddArg!::(-1, ref target, &target, mTypeInstance, splatThis); + checkType = checkType.BaseType; + } + + if (interfaceData == null) + return .Err(.InvalidTarget); + + //funcPtr = *(thisType.[Friend]mInterfaceMethodTable + mMethodData.mVirtualIdx); + } + + ifaceOffset = mTypeInstance.[Friend]mMemberDataOffset; + } + + bool splatThis = thisType.IsSplattable && !mMethodData.mFlags.HasFlag(.Mutating); + AddArg!::(-1, ref target, &target.[Friend]mData, thisType, splatThis); } if (args.Length != mMethodData.mParamCount) @@ -288,7 +326,7 @@ namespace System.Reflection { let paramData = ref mMethodData.mParamData[@arg.Index]; let argType = Type.[Friend]GetType(paramData.mType); - AddArg!::(@arg.Index, ref arg, &arg, argType, paramData.mParamFlags.HasFlag(.Splat)); + AddArg!::(@arg.Index, ref arg, &arg.[Friend]mData, argType, paramData.mParamFlags.HasFlag(.Splat)); } FFICaller caller = .(); @@ -303,24 +341,32 @@ namespace System.Reflection return .Err(.FFIError); } - void* funcPtr = mMethodData.mFuncPtr; - if (mMethodData.mFlags.HasFlag(.Virtual)) + if (funcPtr == null) { - Object objTarget = target.Get(); - + funcPtr = mMethodData.mFuncPtr; + if (mMethodData.mFlags.HasFlag(.Virtual)) + { + Object objTarget = target.Get(); + #if BF_ENABLE_OBJECT_DEBUG_FLAGS - void* classVData = (void*)(objTarget.[Friend]mClassVData & ~0xFF); + void* classVData = (void*)(objTarget.[Friend]mClassVData & ~0xFF); #else - void* classVData = objTarget.[Friend]mClassVData; + void* classVData = objTarget.[Friend]mClassVData; #endif - if (mMethodData.mVirtualIdx >= 0x100000) - { - void* extAddr = (void*)*((int*)classVData + (mMethodData.mVirtualIdx>>20 - 1)); - funcPtr = (void*)*((int*)extAddr + (mMethodData.mVirtualIdx & 0xFFFFF)); - } - else - { - funcPtr = (void*)*(int*)((uint8*)classVData + mMethodData.mVirtualIdx); + if (ifaceOffset >= 0) + { + void* ifaceVirtualTable = *(void**)((uint8*)classVData + ifaceOffset); + funcPtr = (void*)*(int*)((uint8*)ifaceVirtualTable + mMethodData.mVirtualIdx); + } + else if (mMethodData.mVirtualIdx >= 0x100000) + { + void* extAddr = (void*)*((int*)classVData + (mMethodData.mVirtualIdx>>20 - 1)); + funcPtr = (void*)*((int*)extAddr + (mMethodData.mVirtualIdx & 0xFFFFF)); + } + else + { + funcPtr = (void*)*(int*)((uint8*)classVData + mMethodData.mVirtualIdx); + } } } @@ -549,6 +595,9 @@ namespace System.Reflection } } + void* funcPtr = mMethodData.mFuncPtr; + int virtualOffset = 0; + int ifaceOffset = -1; if (mMethodData.mFlags.HasFlag(.Static)) { if (target != null) @@ -559,8 +608,38 @@ namespace System.Reflection if (target == null) return .Err(.TargetExpected); - bool splatThis = mTypeInstance.IsSplattable && !mMethodData.mFlags.HasFlag(.Mutating); - AddArg!::(-1, target, &target, mTypeInstance, splatThis); + var thisType = mTypeInstance; + if (mTypeInstance.IsInterface) + { + thisType = target.[Friend]RawGetType() as TypeInstance; + if (thisType == null) + return .Err(.InvalidTarget); + + ifaceOffset = mTypeInstance.[Friend]mMemberDataOffset; + + /*TypeInstance.InterfaceData* interfaceData = null; + var checkType = thisType; + CheckLoop: while (checkType != null) + { + for (int ifaceIdx < checkType.[Friend]mInterfaceCount) + { + if (checkType.[Friend]mInterfaceDataPtr[ifaceIdx].mInterfaceType == mTypeInstance.TypeId) + { + interfaceData = &checkType.[Friend]mInterfaceDataPtr[ifaceIdx]; + break CheckLoop; + } + } + + checkType = checkType.BaseType; + } + + if (interfaceData == null) + return .Err(.InvalidTarget); + virtualOffset = interfaceData.mStartVirtualIdx * sizeof(int);*/ + } + + bool splatThis = thisType.IsSplattable && !mMethodData.mFlags.HasFlag(.Mutating); + AddArg!::(-1, target, &target, thisType, splatThis); } if (args.Count != mMethodData.mParamCount) @@ -601,7 +680,6 @@ namespace System.Reflection return .Err(.FFIError); } - void* funcPtr = mMethodData.mFuncPtr; if (mMethodData.mFlags.HasFlag(.Virtual)) { #if BF_ENABLE_OBJECT_DEBUG_FLAGS @@ -609,14 +687,19 @@ namespace System.Reflection #else void* classVData = target.[Friend]mClassVData; #endif - if (mMethodData.mVirtualIdx >= 0x100000) + if (ifaceOffset >= 0) + { + void* ifaceVirtualTable = *(void**)((uint8*)classVData + ifaceOffset); + funcPtr = (void*)*(int*)((uint8*)ifaceVirtualTable + mMethodData.mVirtualIdx + virtualOffset); + } + else if (mMethodData.mVirtualIdx >= 0x100000) { void* extAddr = (void*)*((int*)classVData + (mMethodData.mVirtualIdx>>20 - 1)); - funcPtr = (void*)*((int*)extAddr + (mMethodData.mVirtualIdx & 0xFFFFF)); + funcPtr = (void*)*((int*)extAddr + (mMethodData.mVirtualIdx & 0xFFFFF) + virtualOffset); } else { - funcPtr = (void*)*(int*)((uint8*)classVData + mMethodData.mVirtualIdx); + funcPtr = (void*)*(int*)((uint8*)classVData + mMethodData.mVirtualIdx + virtualOffset); } } diff --git a/BeefLibs/corlib/src/Type.bf b/BeefLibs/corlib/src/Type.bf index e3ddd6b0..25b53d7e 100644 --- a/BeefLibs/corlib/src/Type.bf +++ b/BeefLibs/corlib/src/Type.bf @@ -22,6 +22,7 @@ namespace System protected int32 mSize; protected TypeId mTypeId; + protected TypeId mBoxedType; protected TypeFlags mTypeFlags; protected int32 mMemberDataOffset; protected TypeCode mTypeCode; @@ -198,6 +199,14 @@ namespace System } } + public bool IsInterface + { + get + { + return (mTypeFlags & TypeFlags.Interface) != 0; + } + } + public bool IsValueType { get @@ -630,6 +639,7 @@ namespace System.Reflection public TypeId mReturnType; public int16 mParamCount; public MethodFlags mFlags; + public int32 mMethodIdx; public int32 mVirtualIdx; public int32 mCustomAttributesIdx; } @@ -650,6 +660,13 @@ namespace System.Reflection public int32 mDefaultIdx; } + public struct InterfaceData + { + public TypeId mInterfaceType; + public int32 mStartInterfaceTableIdx; + public int32 mStartVirtualIdx; + } + ClassVData* mTypeClassVData; String mName; String mNamespace; @@ -658,7 +675,7 @@ namespace System.Reflection int32 mCustomAttributesIdx; TypeId mBaseType; TypeId mUnderlyingType; - TypeId mOuterType; + TypeId mOuterType; int32 mInheritanceId; int32 mInheritanceCount; @@ -668,11 +685,12 @@ namespace System.Reflection int16 mPropertyDataCount; int16 mFieldDataCount; - void* mInterfaceDataPtr; - MethodData* mMethodDataPtr; - void* mPropertyDataPtr; - FieldData* mFieldDataPtr; - void** mCustomAttrDataPtr; + InterfaceData* mInterfaceDataPtr; + void** mInterfaceMethodTable; + MethodData* mMethodDataPtr; + void* mPropertyDataPtr; + FieldData* mFieldDataPtr; + void** mCustomAttrDataPtr; public override int32 InstanceSize { @@ -1035,13 +1053,14 @@ namespace System.Reflection Boxed = 0x0010, Pointer = 0x0020, Struct = 0x0040, - Primitive = 0x0080, - TypedPrimitive = 0x0100, - Tuple = 0x0200, - Nullable = 0x0400, - SizedArray = 0x0800, - Splattable = 0x1000, - Union = 0x2000, + Interface = 0x0080, + Primitive = 0x0100, + TypedPrimitive = 0x0200, + Tuple = 0x0400, + Nullable = 0x0800, + SizedArray = 0x1000, + Splattable = 0x2000, + Union = 0x4000, // WantsMark = 0x8000, Delegate = 0x10000, diff --git a/IDE/mintest/minlib/src/System/Type.bf b/IDE/mintest/minlib/src/System/Type.bf index 013f573f..adaeaa01 100644 --- a/IDE/mintest/minlib/src/System/Type.bf +++ b/IDE/mintest/minlib/src/System/Type.bf @@ -22,6 +22,7 @@ namespace System protected int32 mSize; protected TypeId mTypeId; + protected TypeId mBoxedType; protected TypeFlags mTypeFlags; protected int32 mMemberDataOffset; protected TypeCode mTypeCode; @@ -462,7 +463,6 @@ namespace System public virtual Type GetBaseType() { - //return mBaseType; return null; } @@ -475,6 +475,11 @@ namespace System return type == this; } + public virtual bool CheckInterface(Type interfaceType) + { + return false; + } + public virtual Result GetField(String fieldName) { return .Err; @@ -598,6 +603,7 @@ namespace System.Reflection public int16 mParamCount; public MethodFlags mFlags; public int32 mVirtualIdx; + public int32 mMethodIdx; public int32 mCustomAttributesIdx; } @@ -617,6 +623,13 @@ namespace System.Reflection public int32 mDefaultIdx; } + public struct InterfaceData + { + public TypeId mInterfaceType; + public int32 mStartInterfaceTableIdx; + public int32 mStartVirtualIdx; + } + ClassVData* mTypeClassVData; String mName; String mNamespace; @@ -625,7 +638,7 @@ namespace System.Reflection int32 mCustomAttributesIdx; TypeId mBaseType; TypeId mUnderlyingType; - TypeId mOuterType; + TypeId mOuterType; int32 mInheritanceId; int32 mInheritanceCount; @@ -635,7 +648,8 @@ namespace System.Reflection int16 mPropertyDataCount; int16 mFieldDataCount; - void* mInterfaceDataPtr; + InterfaceData* mInterfaceDataPtr; + void** mInterfaceMethodTable; MethodData* mMethodDataPtr; void* mPropertyDataPtr; FieldData* mFieldDataPtr; @@ -697,6 +711,11 @@ namespace System.Reflection } } + public override Type GetBaseType() + { + return Type.[Friend]GetType(mBaseType); + } + public override bool IsSubtypeOf(Type checkBaseType) { TypeInstance curType = this; @@ -710,6 +729,17 @@ namespace System.Reflection } } + public override bool CheckInterface(Type interfaceType) + { + for (int i < mInterfaceCount) + if (mInterfaceDataPtr[i].mInterfaceType == interfaceType.TypeId) + return true; + let baseType = GetBaseType(); + if (baseType != null) + return baseType.CheckInterface(interfaceType); + return false; + } + public override void GetFullName(String strBuffer) { if (mTypeFlags.HasFlag(TypeFlags.Tuple)) diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 1fd1a860..7e5f635d 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -418,6 +418,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) mReflectFieldSplatDataDef = NULL; mReflectMethodDataDef = NULL; mReflectParamDataDef = NULL; + mReflectInterfaceDataDef = NULL; mReflectPointerType = NULL; mReflectRefType = NULL; mReflectSizedArrayType = NULL; @@ -1422,7 +1423,7 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule) if (bfModule->mBfIRBuilder->DbgHasInfo()) { auto dbgArrayType = bfModule->mBfIRBuilder->DbgCreateArrayType(stringList.size() * mSystem->mPtrSize * 8, mSystem->mPtrSize * 8, bfModule->mBfIRBuilder->DbgGetType(stringPtrType), (int)stringList.size()); - bfModule->mBfIRBuilder->DbgCreateGlobalVariable(bfModule->mDICompileUnit, stringsVariableName, stringsVariableName, NULL, 0, dbgArrayType, false, stringArrayVar); + bfModule->mBfIRBuilder->DbgCreateGlobalVariable(bfModule->mDICompileUnit, stringsVariableName, stringsVariableName, BfIRMDNode(), 0, dbgArrayType, false, stringArrayVar); } } @@ -1450,7 +1451,7 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule) if (bfModule->mBfIRBuilder->DbgHasInfo()) { auto dbgArrayType = bfModule->mBfIRBuilder->DbgCreateArrayType(stringList.size() * mSystem->mPtrSize * 8, mSystem->mPtrSize * 8, bfModule->mBfIRBuilder->DbgGetType(stringPtrType), (int)stringList.size()); - bfModule->mBfIRBuilder->DbgCreateGlobalVariable(bfModule->mDICompileUnit, stringsVariableName, stringsVariableName, NULL, 0, dbgArrayType, false, stringArrayVar); + bfModule->mBfIRBuilder->DbgCreateGlobalVariable(bfModule->mDICompileUnit, stringsVariableName, stringsVariableName, BfIRMDNode(), 0, dbgArrayType, false, stringArrayVar); } } @@ -1974,7 +1975,7 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule) String name = "__BFTLS_EXTRA"; auto irVal = bfModule->mBfIRBuilder->CreateGlobalVariable(irArrType, false, BfIRLinkageType_External, bfModule->mBfIRBuilder->CreateConstStructZero(irArrType), name, true); BfIRMDNode dbgArrayType = bfModule->mBfIRBuilder->DbgCreateArrayType(dataSize * 8, 8, bfModule->mBfIRBuilder->DbgGetType(int8Type), dataSize); - bfModule->mBfIRBuilder->DbgCreateGlobalVariable(bfModule->mDICompileUnit, name, name, NULL, 0, dbgArrayType, false, irVal); + bfModule->mBfIRBuilder->DbgCreateGlobalVariable(bfModule->mDICompileUnit, name, name, BfIRMDNode(), 0, dbgArrayType, false, irVal); } if (isPosixDynLib) @@ -2740,7 +2741,8 @@ void BfCompiler::GenerateSlotNums() auto typeInstance = type->ToTypeInstance(); if ((typeInstance->mSlotNum <= 0) || (!isHotCompile)) { - if (mContext->mReferencedIFaceSlots.Contains(typeInstance)) + if ((mContext->mReferencedIFaceSlots.Contains(typeInstance)) || + (typeInstance->mHasBeenInstantiated) || (typeInstance->mIncludeAllMethods)) { if (typeInstance->mSlotNum == -2) typeInstance->mSlotNum = -1; @@ -6326,6 +6328,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) mReflectFieldSplatDataDef = _GetRequiredType("System.Reflection.TypeInstance.FieldSplatData"); mReflectMethodDataDef = _GetRequiredType("System.Reflection.TypeInstance.MethodData"); mReflectParamDataDef = _GetRequiredType("System.Reflection.TypeInstance.ParamData"); + mReflectInterfaceDataDef = _GetRequiredType("System.Reflection.TypeInstance.InterfaceData"); mReflectPointerType = _GetRequiredType("System.Reflection.PointerType"); mReflectRefType = _GetRequiredType("System.Reflection.RefType"); mReflectSizedArrayType = _GetRequiredType("System.Reflection.SizedArrayType"); diff --git a/IDEHelper/Compiler/BfCompiler.h b/IDEHelper/Compiler/BfCompiler.h index 89d2f801..0ec7a1d3 100644 --- a/IDEHelper/Compiler/BfCompiler.h +++ b/IDEHelper/Compiler/BfCompiler.h @@ -368,6 +368,7 @@ public: BfTypeDef* mReflectFieldSplatDataDef; BfTypeDef* mReflectMethodDataDef; BfTypeDef* mReflectParamDataDef; + BfTypeDef* mReflectInterfaceDataDef; BfTypeDef* mReflectPointerType; BfTypeDef* mReflectRefType; BfTypeDef* mReflectSizedArrayType; diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 89a3d588..71b4dbbe 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -1097,7 +1097,7 @@ void BfModule::EnsureIRBuilder(bool dbgVerifyCodeGen) // code as we walk the AST //mBfIRBuilder->mDbgVerifyCodeGen = true; if ( - (mModuleName == "BeefTest_TestProgram") + (mModuleName == "-") //|| (mModuleName == "BeefTest2_ClearColorValue") //|| (mModuleName == "Tests_FuncRefs") ) @@ -4819,6 +4819,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin } if (type->IsStruct()) typeFlags |= BfTypeFlags_Struct; + if (type->IsInterface()) + typeFlags |= BfTypeFlags_Interface; if (type->IsBoxed()) { typeFlags |= BfTypeFlags_Boxed; @@ -4846,8 +4848,13 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin if (type->WantsGCMarking()) typeFlags |= BfTypeFlags_WantsMarking; + int virtSlotIdx = -1; + if ((typeInstance != NULL) && (typeInstance->mSlotNum >= 0)) + virtSlotIdx = typeInstance->mSlotNum + 1 + mCompiler->GetDynCastVDataCount(); int memberDataOffset = 0; - if (typeInstance != NULL) + if (type->IsInterface()) + memberDataOffset = virtSlotIdx * mSystem->mPtrSize; + else if (typeInstance != NULL) { for (auto& fieldInstance : typeInstance->mFieldInstances) { @@ -4858,11 +4865,21 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin } } } + + int boxedTypeId = 0; + if (type->IsValueType()) + { + auto boxedType = CreateBoxedType(type, false); + if ((boxedType != NULL) && (boxedType->mIsReified)) + boxedTypeId = boxedType->mTypeId; + } + SizedArray typeDataParams = { objectData, GetConstValue(type->mSize, intType), // mSize GetConstValue(type->mTypeId, typeIdType), // mTypeId + GetConstValue(boxedTypeId, typeIdType), // mBoxedType GetConstValue(typeFlags, intType), // mTypeFlags GetConstValue(memberDataOffset, intType), // mMemberDataOffset GetConstValue(typeCode, byteType), // mTypeCode @@ -4975,20 +4992,18 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin } } } - + SizedArray vData; BfIRValue classVDataVar; String classVDataName; if (typeInstance->mSlotNum >= 0) { - // For interfaces we ONLY emit the slot num - int virtSlotIdx = typeInstance->mSlotNum + 1 + mCompiler->GetDynCastVDataCount(); - + // For interfaces we ONLY emit the slot num StringT<128> slotVarName; BfMangler::MangleStaticFieldName(slotVarName, mCompiler->GetMangleKind(), typeInstance, "sBfSlotOfs"); auto intType = GetPrimitiveType(BfTypeCode_Int32); auto slotNumVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapType(intType), true, BfIRLinkageType_External, - GetConstValue32(virtSlotIdx), slotVarName); + GetConstValue32(virtSlotIdx), slotVarName); } else if ((typeInstance->IsObject()) && (!typeInstance->IsUnspecializedType()) && (needsVData)) { @@ -6212,7 +6227,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin methodFlags = (MethodFlags)(methodFlags | MethodFlags_Public); if (methodDef->mIsStatic) methodFlags = (MethodFlags)(methodFlags | MethodFlags_Static); - if (methodDef->mIsVirtual) + if ((methodDef->mIsVirtual) || (moduleMethodInstance.mMethodInstance->mVirtualTableIdx != -1)) methodFlags = (MethodFlags)(methodFlags | MethodFlags_Virtual); if (methodDef->mCallingConvention == BfCallingConvention_Fastcall) methodFlags = (MethodFlags)(methodFlags | MethodFlags_FastCall); @@ -6279,27 +6294,35 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin if (defaultMethod->mVirtualTableIdx != -1) { int vDataIdx = -1; - vDataIdx = 1 + mCompiler->GetDynCastVDataCount() + mCompiler->mMaxInterfaceSlots; - if ((mCompiler->mOptions.mHasVDataExtender) && (mCompiler->IsHotCompile())) - { - auto typeInst = defaultMethod->mMethodInstanceGroup->mOwner; - int extMethodIdx = (defaultMethod->mVirtualTableIdx - typeInst->GetImplBaseVTableSize()) - typeInst->GetOrigSelfVTableSize(); - if (extMethodIdx >= 0) - { - // Extension? - int vExtOfs = typeInst->GetOrigImplBaseVTableSize(); - vDataVal = ((vDataIdx + vExtOfs + 1) << 20) | (extMethodIdx); - } - else - { - // Map this new virtual index back to the original index - vDataIdx += (defaultMethod->mVirtualTableIdx - typeInst->GetImplBaseVTableSize()) + typeInst->GetOrigImplBaseVTableSize(); - } + if (type->IsInterface()) + { + vDataIdx = defaultMethod->mVirtualTableIdx; } else { - vDataIdx += defaultMethod->mVirtualTableIdx; + vDataIdx = 1 + mCompiler->GetDynCastVDataCount() + mCompiler->mMaxInterfaceSlots; + if ((mCompiler->mOptions.mHasVDataExtender) && (mCompiler->IsHotCompile())) + { + auto typeInst = defaultMethod->mMethodInstanceGroup->mOwner; + + int extMethodIdx = (defaultMethod->mVirtualTableIdx - typeInst->GetImplBaseVTableSize()) - typeInst->GetOrigSelfVTableSize(); + if (extMethodIdx >= 0) + { + // Extension? + int vExtOfs = typeInst->GetOrigImplBaseVTableSize(); + vDataVal = ((vDataIdx + vExtOfs + 1) << 20) | (extMethodIdx); + } + else + { + // Map this new virtual index back to the original index + vDataIdx += (defaultMethod->mVirtualTableIdx - typeInst->GetImplBaseVTableSize()) + typeInst->GetOrigImplBaseVTableSize(); + } + } + else + { + vDataIdx += defaultMethod->mVirtualTableIdx; + } } if (vDataVal == -1) vDataVal = vDataIdx * mSystem->mPtrSize; @@ -6314,6 +6337,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin GetConstValue(defaultMethod->mReturnType->mTypeId, typeIdType), GetConstValue((int)paramVals.size(), shortType), GetConstValue(methodFlags, shortType), + GetConstValue(methodIdx, intType), GetConstValue(vDataVal, intType), GetConstValue(customAttrIdx, intType), }; @@ -6336,6 +6360,72 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin ///// + int interfaceCount = 0; + BfIRValue interfaceDataPtr; + BfType* reflectInterfaceDataType = ResolveTypeDef(mCompiler->mReflectInterfaceDataDef); + BfIRType interfaceDataPtrType = mBfIRBuilder->GetPointerTo(mBfIRBuilder->MapType(reflectInterfaceDataType)); + if (typeInstance->mInterfaces.IsEmpty()) + interfaceDataPtr = mBfIRBuilder->CreateConstNull(interfaceDataPtrType); + else + { + SizedArray interfaces; + for (auto& interface : typeInstance->mInterfaces) + { + SizedArray interfaceDataVals = + { + emptyValueType, + GetConstValue(interface.mInterfaceType->mTypeId, typeIdType), + GetConstValue(interface.mStartInterfaceTableIdx, intType), + GetConstValue(interface.mStartVirtualIdx, intType), + }; + + auto interfaceData = mBfIRBuilder->CreateConstStruct(mBfIRBuilder->MapTypeInst(reflectInterfaceDataType->ToTypeInstance(), BfIRPopulateType_Full), interfaceDataVals); + interfaces.push_back(interfaceData); + } + + BfIRType interfaceDataArrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(reflectInterfaceDataType, BfIRPopulateType_Full), (int)interfaces.size()); + BfIRValue interfaceDataConst = mBfIRBuilder->CreateConstArray(interfaceDataArrayType, interfaces); + BfIRValue interfaceDataArray = mBfIRBuilder->CreateGlobalVariable(interfaceDataArrayType, true, BfIRLinkageType_Internal, + interfaceDataConst, "interfaces." + typeDataName); + interfaceDataPtr = mBfIRBuilder->CreateBitCast(interfaceDataArray, interfaceDataPtrType); + interfaceCount = (int)interfaces.size(); + } + + BfIRValue interfaceMethodTable; + if ((!typeInstance->IsInterface()) && (typeInstance->mIsReified) && (!typeInstance->IsUnspecializedType()) + && (!typeInstance->mInterfaceMethodTable.IsEmpty())) + { + SizedArray methods; + for (auto& methodEntry : typeInstance->mInterfaceMethodTable) + { + BfIRValue funcVal = voidPtrNull; + if (!methodEntry.mMethodRef.IsNull()) + { + BfMethodInstance* methodInstance = methodEntry.mMethodRef; + if ((methodInstance->mIsReified) && (methodInstance->mMethodInstanceGroup->IsImplemented()) && (!methodInstance->mIsUnspecialized)) + { + auto moduleMethodInstance = ReferenceExternalMethodInstance(methodInstance); + if (moduleMethodInstance.mFunc) + funcVal = mBfIRBuilder->CreateBitCast(moduleMethodInstance.mFunc, voidPtrIRType); + } + } + methods.Add(funcVal); + } + + while ((!methods.IsEmpty()) && (methods.back() == voidPtrNull)) + methods.pop_back(); + + BfIRType methodDataArrayType = mBfIRBuilder->GetSizedArrayType(mBfIRBuilder->MapType(voidPtrType, BfIRPopulateType_Full), (int)methods.size()); + BfIRValue methodDataConst = mBfIRBuilder->CreateConstArray(methodDataArrayType, methods); + BfIRValue methodDataArray = mBfIRBuilder->CreateGlobalVariable(methodDataArrayType, true, BfIRLinkageType_Internal, + methodDataConst, "imethods." + typeDataName); + interfaceMethodTable = mBfIRBuilder->CreateBitCast(methodDataArray, voidPtrPtrIRType); + } + else + interfaceMethodTable = mBfIRBuilder->CreateConstNull(voidPtrPtrIRType); + + ///// + int underlyingType = 0; if ((typeInstance->IsTypedPrimitive()) || (typeInstance->IsBoxed())) { @@ -6348,6 +6438,8 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin { outerTypeId = outerType->mTypeId; } + + // BfIRValue customAttrDataPtr; if (customAttrs.size() > 0) @@ -6375,17 +6467,18 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin GetConstValue(typeCustomAttrIdx, intType), // mCustomAttributes GetConstValue(baseTypeId, typeIdType), // mBaseType GetConstValue(underlyingType, typeIdType), // mUnderlyingType - GetConstValue(outerTypeId, typeIdType), // mOuterType + GetConstValue(outerTypeId, typeIdType), // mOuterType GetConstValue(typeInstance->mInheritanceId, intType), // mInheritanceId GetConstValue(typeInstance->mInheritanceCount, intType), // mInheritanceCount GetConstValue(typeInstance->mSlotNum, byteType), // mInterfaceSlot - GetConstValue(0, byteType), // mInterfaceCount + GetConstValue(interfaceCount, byteType), // mInterfaceCount GetConstValue((int)methodTypes.size(), shortType), // mMethodDataCount GetConstValue(0, shortType), // mPropertyDataCount GetConstValue((int)fieldTypes.size(), shortType), // mFieldDataCount - voidPtrNull, // mInterfaceDataPtr + interfaceDataPtr, // mInterfaceDataPtr + interfaceMethodTable, // mInterfaceMethodTable methodDataPtr, // mMethodDataPtr voidPtrNull, // mPropertyDataPtr fieldDataPtr, // mFieldDataPtr @@ -6470,7 +6563,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin if (mBfIRBuilder->DbgHasInfo()) { - mBfIRBuilder->DbgCreateGlobalVariable(mDICompileUnit, typeDataName, typeDataName, NULL, 0, mBfIRBuilder->DbgGetTypeInst(typeInstanceType->ToTypeInstance()), false, typeDataVar); + mBfIRBuilder->DbgCreateGlobalVariable(mDICompileUnit, typeDataName, typeDataName, BfIRMDNode(), 0, mBfIRBuilder->DbgGetTypeInst(typeInstanceType->ToTypeInstance()), false, typeDataVar); } } else @@ -6502,7 +6595,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary& usedStrin BfType* classVDataType = ResolveTypeDef(mCompiler->mClassVDataTypeDef); BfIRMDNode arrayType = mBfIRBuilder->DbgCreateArrayType(vData.size() * mSystem->mPtrSize * 8, mSystem->mPtrSize * 8, mBfIRBuilder->DbgGetType(voidPtrType), vData.size()); - mBfIRBuilder->DbgCreateGlobalVariable(mDICompileUnit, classVDataName, classVDataName, NULL, 0, arrayType, false, classVDataVar); + mBfIRBuilder->DbgCreateGlobalVariable(mDICompileUnit, classVDataName, classVDataName, BfIRMDNode(), 0, arrayType, false, classVDataVar); } } @@ -17337,7 +17430,7 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup) defLine + 1, diFuncType, false, true, llvm::dwarf::DW_VIRTUALITY_none, 0, - nullptr, flags, IsOptimized(), llvmFunction, genericArgs, genericConstValueArgs); + BfIRMDNode(), flags, IsOptimized(), llvmFunction, genericArgs, genericConstValueArgs); } } diff --git a/IDEHelper/Compiler/BfModule.h b/IDEHelper/Compiler/BfModule.h index 6ec7c04d..e6f0a238 100644 --- a/IDEHelper/Compiler/BfModule.h +++ b/IDEHelper/Compiler/BfModule.h @@ -1646,7 +1646,7 @@ public: BfPointerType* CreatePointerType(BfType* resolvedType); BfPointerType* CreatePointerType(BfTypeReference* typeRef); BfConstExprValueType* CreateConstExprValueType(const BfTypedValue& typedValue); - BfBoxedType* CreateBoxedType(BfType* resolvedTypeRef); + BfBoxedType* CreateBoxedType(BfType* resolvedTypeRef, bool allowCreate = true); BfTypeInstance* CreateTupleType(const BfTypeVector& fieldTypes, const Array& fieldNames, bool allowVar = false); BfTypeInstance* SantizeTupleType(BfTypeInstance* tupleType); BfRefType* CreateRefType(BfType* resolvedTypeRef, BfRefType::RefKind refKind = BfRefType::RefKind_Ref); @@ -1662,7 +1662,7 @@ public: void FixIntUnknown(BfTypedValue& lhs, BfTypedValue& rhs); bool TypeEquals(BfTypedValue& val, BfType* type); BfTypeDef* ResolveGenericInstanceDef(BfGenericInstanceTypeRef* genericTypeRef, BfType** outType = NULL, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None); - BfType* ResolveType(BfType* lookupType, BfPopulateType populateType = BfPopulateType_Data); + BfType* ResolveType(BfType* lookupType, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None); void ResolveGenericParamConstraints(BfGenericParamInstance* genericParamInstance, bool isUnspecialized); String GenericParamSourceToString(const BfGenericParamSource& genericParamSource); bool CheckGenericConstraints(const BfGenericParamSource& genericParamSource, BfType* checkArgType, BfAstNode* checkArgTypeRef, BfGenericParamInstance* genericParamInst, BfTypeVector* methodGenericArgs = NULL, BfError** errorOut = NULL); @@ -1718,8 +1718,8 @@ public: BfType* ResolveTypeRefAllowUnboundGenerics(BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, bool resolveGenericParam = true); BfType* ResolveTypeRef(BfAstNode* astNode, const BfSizedArray* genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0); //BfType* ResolveTypeRef(BfIdentifierNode* identifier, const BfSizedArray& genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = (BfResolveTypeRefFlags)0); - BfType* ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType = BfPopulateType_Data); - BfType* ResolveTypeDef(BfTypeDef* typeDef, const BfTypeVector& genericArgs, BfPopulateType populateType = BfPopulateType_Data); + BfType* ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None); + BfType* ResolveTypeDef(BfTypeDef* typeDef, const BfTypeVector& genericArgs, BfPopulateType populateType = BfPopulateType_Data, BfResolveTypeRefFlags resolveFlags = BfResolveTypeRefFlag_None); BfType* ResolveInnerType(BfType* outerType, BfTypeReference* typeRef, BfPopulateType populateType = BfPopulateType_Data, bool ignoreErrors = false, int numGenericArgs = 0); BfType* ResolveInnerType(BfType* outerType, BfIdentifierNode* identifier, BfPopulateType populateType = BfPopulateType_Data, bool ignoreErrors = false); BfTypeDef* GetCombinedPartialTypeDef(BfTypeDef* type); diff --git a/IDEHelper/Compiler/BfModuleTypeUtils.cpp b/IDEHelper/Compiler/BfModuleTypeUtils.cpp index ebcdf861..8b0082ad 100644 --- a/IDEHelper/Compiler/BfModuleTypeUtils.cpp +++ b/IDEHelper/Compiler/BfModuleTypeUtils.cpp @@ -5349,19 +5349,18 @@ BfTypeInstance* BfModule::GetPrimitiveStructType(BfTypeCode typeCode) return typeInst; } -BfBoxedType* BfModule::CreateBoxedType(BfType* resolvedTypeRef) -{ +BfBoxedType* BfModule::CreateBoxedType(BfType* resolvedTypeRef, bool allowCreate) +{ bool isStructPtr = false; + BfPopulateType populateType = allowCreate ? BfPopulateType_Data : BfPopulateType_Identity; + BfResolveTypeRefFlags resolveFlags = allowCreate ? BfResolveTypeRefFlag_None : BfResolveTypeRefFlag_NoCreate; if (resolvedTypeRef->IsPrimitiveType()) { auto primType = (BfPrimitiveType*)resolvedTypeRef; resolvedTypeRef = GetPrimitiveStructType(primType->mTypeDef->mTypeCode); - if (resolvedTypeRef == NULL) - { - BFMODULE_FATAL(this, "Unable to find primitive type"); + if (resolvedTypeRef == NULL) return NULL; - } } else if (resolvedTypeRef->IsPointer()) { @@ -5375,7 +5374,9 @@ BfBoxedType* BfModule::CreateBoxedType(BfType* resolvedTypeRef) { BfTypeVector typeVector; typeVector.Add(pointerType->mElementType); - resolvedTypeRef = ResolveTypeDef(mCompiler->mPointerTTypeDef, typeVector, BfPopulateType_Data)->ToTypeInstance(); + resolvedTypeRef = ResolveTypeDef(mCompiler->mPointerTTypeDef, typeVector, populateType, resolveFlags); + if (resolvedTypeRef == NULL) + return NULL; } } else if (resolvedTypeRef->IsMethodRef()) @@ -5383,7 +5384,9 @@ BfBoxedType* BfModule::CreateBoxedType(BfType* resolvedTypeRef) BfMethodRefType* methodRefType = (BfMethodRefType*)resolvedTypeRef; BfTypeVector typeVector; typeVector.Add(methodRefType); - resolvedTypeRef = ResolveTypeDef(mCompiler->mMethodRefTypeDef, typeVector, BfPopulateType_Data)->ToTypeInstance(); + resolvedTypeRef = ResolveTypeDef(mCompiler->mMethodRefTypeDef, typeVector, populateType, resolveFlags); + if (resolvedTypeRef == NULL) + return NULL; } else if (resolvedTypeRef->IsSizedArray()) { @@ -5392,7 +5395,9 @@ BfBoxedType* BfModule::CreateBoxedType(BfType* resolvedTypeRef) typeVector.Add(sizedArrayType->mElementType); auto sizeValue = BfTypedValue(GetConstValue(sizedArrayType->mElementCount), GetPrimitiveType(BfTypeCode_IntPtr)); typeVector.Add(CreateConstExprValueType(sizeValue)); - resolvedTypeRef = ResolveTypeDef(mCompiler->mSizedArrayTypeDef, typeVector, BfPopulateType_Data)->ToTypeInstance(); + resolvedTypeRef = ResolveTypeDef(mCompiler->mSizedArrayTypeDef, typeVector, populateType, resolveFlags); + if (resolvedTypeRef == NULL) + return NULL; } BfTypeInstance* typeInst = resolvedTypeRef->ToTypeInstance(); @@ -5407,7 +5412,7 @@ BfBoxedType* BfModule::CreateBoxedType(BfType* resolvedTypeRef) else boxedType->mTypeDef = mCompiler->mValueTypeTypeDef; boxedType->mBoxedFlags = isStructPtr ? BfBoxedType::BoxedFlags_StructPtr : BfBoxedType::BoxedFlags_None; - auto resolvedBoxedType = ResolveType(boxedType); + auto resolvedBoxedType = ResolveType(boxedType, populateType, resolveFlags); if (resolvedBoxedType != boxedType) mContext->mBoxedTypePool.GiveBack(boxedType); return (BfBoxedType*)resolvedBoxedType; @@ -5549,7 +5554,7 @@ BfPointerType* BfModule::CreatePointerType(BfTypeReference* typeRef) return CreatePointerType(resolvedTypeRef); } -BfType* BfModule::ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType) +BfType* BfModule::ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags) { //BF_ASSERT(typeDef->mTypeCode != BfTypeCode_Extension); BF_ASSERT(!typeDef->mIsPartial || typeDef->mIsCombinedPartial); @@ -5558,7 +5563,7 @@ BfType* BfModule::ResolveTypeDef(BfTypeDef* typeDef, BfPopulateType populateType BF_ASSERT((typeDef->mOuterType == NULL) || (typeDef->mOuterType->mDefState != BfTypeDef::DefState_Deleted)); if (typeDef->mGenericParamDefs.size() != 0) - return ResolveTypeDef(typeDef, BfTypeVector(), populateType); + return ResolveTypeDef(typeDef, BfTypeVector(), populateType, resolveFlags); auto typeDefTypeRef = mContext->mTypeDefTypeRefPool.Get(); typeDefTypeRef->mTypeDef = typeDef; @@ -5856,10 +5861,10 @@ bool BfModule::IsInnerType(BfTypeDef* checkInnerType, BfTypeDef* checkOuterType) } } -BfType* BfModule::ResolveTypeDef(BfTypeDef* typeDef, const BfTypeVector& genericArgs, BfPopulateType populateType) +BfType* BfModule::ResolveTypeDef(BfTypeDef* typeDef, const BfTypeVector& genericArgs, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags) { if (typeDef->mGenericParamDefs.size() == 0) - return ResolveTypeDef(typeDef, populateType); + return ResolveTypeDef(typeDef, populateType, resolveFlags); if ((typeDef == mCompiler->mArray1TypeDef) || (typeDef == mCompiler->mArray2TypeDef)) { @@ -5892,7 +5897,7 @@ BfType* BfModule::ResolveTypeDef(BfTypeDef* typeDef, const BfTypeVector& generic } } - auto resolvedType = ResolveType(arrayInstType, populateType); + auto resolvedType = ResolveType(arrayInstType, populateType, resolveFlags); if (resolvedType != arrayInstType) { delete arrayInstType->mGenericTypeInfo; @@ -5960,7 +5965,7 @@ BfType* BfModule::ResolveTypeDef(BfTypeDef* typeDef, const BfTypeVector& generic // } // else { - resolvedType = ResolveType(genericInstType, populateType); + resolvedType = ResolveType(genericInstType, populateType, resolveFlags); } @@ -6546,19 +6551,24 @@ BfType* BfModule::ResolveGenericType(BfType* unspecializedType, BfTypeVector* ty return unspecializedType; } -BfType* BfModule::ResolveType(BfType* lookupType, BfPopulateType populateType) +BfType* BfModule::ResolveType(BfType* lookupType, BfPopulateType populateType, BfResolveTypeRefFlags resolveFlags) { BfResolvedTypeSet::LookupContext lookupCtx; - lookupCtx.mModule = this; + lookupCtx.mModule = this; + lookupCtx.mResolveFlags = resolveFlags; BfResolvedTypeSet::Entry* resolvedEntry = NULL; bool inserted = mContext->mResolvedTypes.Insert(lookupType, &lookupCtx, &resolvedEntry); + + if (resolvedEntry == NULL) + return NULL; + if (!inserted) { auto resolvedTypeRef = resolvedEntry->mValue; PopulateType(resolvedTypeRef, populateType); return resolvedTypeRef; } - + if (lookupType->IsGenericTypeInstance()) CheckUnspecializedGenericType((BfTypeInstance*)lookupType, populateType); diff --git a/IDEHelper/Compiler/BfResolvedTypeUtils.h b/IDEHelper/Compiler/BfResolvedTypeUtils.h index 856d1305..51a58fa5 100644 --- a/IDEHelper/Compiler/BfResolvedTypeUtils.h +++ b/IDEHelper/Compiler/BfResolvedTypeUtils.h @@ -630,8 +630,7 @@ public: public: BfDeferredMethodCallData() - { - mDeferDIType = NULL; + { mAlign = 0; mSize = 0; mMethodId = 0; @@ -2351,7 +2350,7 @@ public: BfTypeDef* mRootTypeDef; BfTypeInstance* mRootOuterTypeInstance; BfType* mResolvedType; - BfResolveTypeRefFlags mResolveFlags; + BfResolveTypeRefFlags mResolveFlags; bool mFailed; public: @@ -2426,6 +2425,9 @@ public: BF_ASSERT(tryCount < 10); } + if ((ctx->mResolveFlags & BfResolveTypeRefFlag_NoCreate) != 0) + return false; + mCount++; Entry* entry = (Entry*)BfResolvedTypeSetFuncs::Allocate(sizeof(Entry), alignof(Entry)); entry->mValue = NULL; diff --git a/IDEHelper/Compiler/BfStmtEvaluator.cpp b/IDEHelper/Compiler/BfStmtEvaluator.cpp index 0cc8ad0c..abc420c2 100644 --- a/IDEHelper/Compiler/BfStmtEvaluator.cpp +++ b/IDEHelper/Compiler/BfStmtEvaluator.cpp @@ -457,7 +457,7 @@ bool BfModule::AddDeferredCallEntry(BfDeferredCallEntry* deferredCallEntry, BfSc } else { - BfIRMDNode diForwardDecl = NULL; + BfIRMDNode diForwardDecl; SizedArray diFieldTypes; if ((mBfIRBuilder->DbgHasInfo()) && (mHasFullDebugInfo)) { diff --git a/IDEHelper/Compiler/BfSystem.h b/IDEHelper/Compiler/BfSystem.h index 7a097117..bdec8988 100644 --- a/IDEHelper/Compiler/BfSystem.h +++ b/IDEHelper/Compiler/BfSystem.h @@ -170,13 +170,14 @@ enum BfTypeFlags BfTypeFlags_Boxed = 0x0010, BfTypeFlags_Pointer = 0x0020, BfTypeFlags_Struct = 0x0040, - BfTypeFlags_Primitive = 0x0080, - BfTypeFlags_TypedPrimitive = 0x0100, - BfTypeFlags_Tuple = 0x0200, - BfTypeFlags_Nullable = 0x0400, - BfTypeFlags_SizedArray = 0x0800, - BfTypeFlags_Splattable = 0x1000, - BfTypeFlags_Union = 0x2000, + BfTypeFlags_Interface = 0x0080, + BfTypeFlags_Primitive = 0x0100, + BfTypeFlags_TypedPrimitive = 0x0200, + BfTypeFlags_Tuple = 0x0400, + BfTypeFlags_Nullable = 0x0800, + BfTypeFlags_SizedArray = 0x1000, + BfTypeFlags_Splattable = 0x2000, + BfTypeFlags_Union = 0x4000, // BfTypeFlags_WantsMarking = 0x8000, BfTypeFlags_Delegate = 0x10000,