mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-08 11:38:21 +02:00
Boxed struct ptr changes.
This commit is contained in:
parent
ad2542eba6
commit
5af6428bf4
20 changed files with 573 additions and 327 deletions
|
@ -1,12 +1,29 @@
|
|||
namespace System
|
||||
{
|
||||
struct Pointer
|
||||
[AlwaysInclude]
|
||||
struct Pointer : IHashable
|
||||
{
|
||||
void* mVal;
|
||||
|
||||
public int GetHashCode()
|
||||
{
|
||||
return (int)mVal;
|
||||
}
|
||||
|
||||
struct Pointer<T>
|
||||
[AlwaysInclude]
|
||||
Object GetBoxed()
|
||||
{
|
||||
return new box this;
|
||||
}
|
||||
}
|
||||
|
||||
struct Pointer<T> : IHashable
|
||||
{
|
||||
T* mVal;
|
||||
|
||||
public int GetHashCode()
|
||||
{
|
||||
return (int)mVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,6 +154,14 @@ namespace System.Reflection
|
|||
Type underlyingType = argType.UnderlyingType;
|
||||
if ((paramType.IsPrimitive) && (underlyingType.IsTypedPrimitive)) // Boxed primitive?
|
||||
underlyingType = underlyingType.UnderlyingType;
|
||||
|
||||
if (argType.IsBoxedStructPtr)
|
||||
{
|
||||
dataPtr = *(void**)dataPtr;
|
||||
handled = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!underlyingType.IsSubtypeOf(paramType))
|
||||
{
|
||||
if (underlyingType.IsGenericType)
|
||||
|
@ -175,6 +183,7 @@ namespace System.Reflection
|
|||
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
||||
if (!handled)
|
||||
{
|
||||
|
|
|
@ -213,6 +213,14 @@ namespace System
|
|||
}
|
||||
}
|
||||
|
||||
public bool IsPointer
|
||||
{
|
||||
get
|
||||
{
|
||||
return (mTypeFlags & (TypeFlags.Boxed | TypeFlags.Pointer)) == TypeFlags.Pointer;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsBoxed
|
||||
{
|
||||
get
|
||||
|
@ -221,6 +229,14 @@ namespace System
|
|||
}
|
||||
}
|
||||
|
||||
public bool IsBoxedStructPtr
|
||||
{
|
||||
get
|
||||
{
|
||||
return (mTypeFlags & (TypeFlags.Boxed | TypeFlags.Pointer)) == TypeFlags.Boxed | TypeFlags.Pointer;
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEnum
|
||||
{
|
||||
get
|
||||
|
|
|
@ -1358,12 +1358,11 @@ void BeIRCodeGen::HandleNextCmd()
|
|||
CMD_PARAM(BeValue*, val);
|
||||
CMD_PARAM(int, idx);
|
||||
|
||||
BF_ASSERT(val->GetType()->IsComposite());
|
||||
|
||||
auto extractValueInst = mBeModule->AllocInst<BeExtractValueInst>();
|
||||
extractValueInst->mAggVal = val;
|
||||
extractValueInst->mIdx = idx;
|
||||
|
||||
BF_ASSERT(val->GetType()->IsComposite());
|
||||
|
||||
SetResult(curId, extractValueInst);
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -2394,6 +2394,20 @@ void BeModule::Print(BeFunction* func)
|
|||
OutputDebugStr(ToString(func));
|
||||
}
|
||||
|
||||
void BeModule::PrintValue(BeValue* val)
|
||||
{
|
||||
BeDumpContext dumpCtx;
|
||||
dumpCtx.mModule = this;
|
||||
String str;
|
||||
dumpCtx.ToString(str, val);
|
||||
str += "\n";
|
||||
OutputDebugStr(str);
|
||||
|
||||
auto type = val->GetType();
|
||||
if (type != NULL)
|
||||
bpt(type);
|
||||
}
|
||||
|
||||
void BeModule::DoInlining(BeFunction* func)
|
||||
{
|
||||
//bool debugging = func->mName == "?Test@Program@bf@@CAXXZ";
|
||||
|
@ -3139,8 +3153,8 @@ BeGEPInst* BeModule::CreateGEP(BeValue* ptr, BeValue* idx0, BeValue* idx1)
|
|||
inst->mIdx1 = idx1;
|
||||
AddInst(inst);
|
||||
|
||||
BF_ASSERT(ptr->GetType()->IsPointer());
|
||||
#ifdef _DEBUG
|
||||
BF_ASSERT(ptr->GetType()->IsPointer());
|
||||
inst->GetType();
|
||||
#endif
|
||||
|
||||
|
|
|
@ -2109,6 +2109,7 @@ public:
|
|||
String ToString(BeFunction* func = NULL);
|
||||
void Print();
|
||||
void Print(BeFunction* func);
|
||||
void PrintValue(BeValue* val);
|
||||
|
||||
void DoInlining(BeFunction* func);
|
||||
void DoInlining();
|
||||
|
|
|
@ -2427,12 +2427,6 @@ public:
|
|||
BfTokenNode* mRefToken;
|
||||
}; BF_AST_DECL(BfRefTypeRef, BfElementedTypeRef);
|
||||
|
||||
class BfBoxedTypeRef : public BfElementedTypeRef
|
||||
{
|
||||
public:
|
||||
BF_AST_TYPE(BfBoxedTypeRef, BfElementedTypeRef);
|
||||
}; BF_AST_DECL(BfBoxedTypeRef, BfElementedTypeRef);
|
||||
|
||||
class BfParamsExpression : public BfExpression
|
||||
{
|
||||
public:
|
||||
|
|
|
@ -1394,7 +1394,7 @@ void BfAutoComplete::CheckIdentifier(BfIdentifierNode* identifierNode, bool isIn
|
|||
"delegate", "extern", "enum", "explicit", "extension", "function",
|
||||
"interface", "in", "internal", "mixin", "namespace", "new",
|
||||
"operator", "out", "override", "params", "private", "protected", "public", "readonly", "ref", "rettype", "return",
|
||||
"sealed", "static", "struct", "this", "typealias",
|
||||
"scope", "sealed", "static", "struct", "this", "typealias",
|
||||
"using", "virtual", "volatile", "T", "where"
|
||||
};
|
||||
for (int i = 0; i < sizeof(tokens)/sizeof(char*); i++)
|
||||
|
|
|
@ -397,6 +397,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
|
|||
mInlineAttributeTypeDef = NULL;
|
||||
mInternalTypeDef = NULL;
|
||||
mIPrintableTypeDef = NULL;
|
||||
mIHashableTypeDef = NULL;
|
||||
mLinkNameAttributeTypeDef = NULL;
|
||||
mMethodRefTypeDef = NULL;
|
||||
mNullableTypeDef = NULL;
|
||||
|
@ -422,6 +423,9 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
|
|||
mTypeTypeDef = NULL;
|
||||
mUnboundAttributeTypeDef = NULL;
|
||||
mValueTypeTypeDef = NULL;
|
||||
mObsoleteAttributeTypeDef = NULL;
|
||||
mErrorAttributeTypeDef = NULL;
|
||||
mWarnAttributeTypeDef = NULL;
|
||||
|
||||
mLastAutocompleteModule = NULL;
|
||||
}
|
||||
|
@ -4826,6 +4830,9 @@ void BfCompiler::PopulateReified()
|
|||
|
||||
void BfCompiler::HotCommit()
|
||||
{
|
||||
if (mHotState == NULL)
|
||||
return;
|
||||
|
||||
mHotState->mCommittedHotCompileIdx = mOptions.mHotCompileIdx;
|
||||
|
||||
for (auto type : mContext->mResolvedTypes)
|
||||
|
@ -5808,6 +5815,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
|
|||
mInlineAttributeTypeDef = _GetRequiredType("System.InlineAttribute");
|
||||
mInternalTypeDef = _GetRequiredType("System.Internal");
|
||||
mIPrintableTypeDef = _GetRequiredType("System.IPrintable");
|
||||
mIHashableTypeDef = _GetRequiredType("System.IHashable");
|
||||
mLinkNameAttributeTypeDef = _GetRequiredType("System.LinkNameAttribute");
|
||||
mMethodRefTypeDef = _GetRequiredType("System.MethodReference", 1);
|
||||
mNullableTypeDef = _GetRequiredType("System.Nullable");
|
||||
|
@ -5834,6 +5842,9 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
|
|||
mTypeTypeDef = _GetRequiredType("System.Type");
|
||||
mUnboundAttributeTypeDef = _GetRequiredType("System.UnboundAttribute");
|
||||
mValueTypeTypeDef = _GetRequiredType("System.ValueType");
|
||||
mObsoleteAttributeTypeDef = _GetRequiredType("System.ObsoleteAttribute");
|
||||
mErrorAttributeTypeDef = _GetRequiredType("System.ErrorAttribute");
|
||||
mWarnAttributeTypeDef = _GetRequiredType("System.WarnAttribute");
|
||||
|
||||
for (int i = 0; i < BfTypeCode_Length; i++)
|
||||
mContext->mPrimitiveStructTypes[i] = NULL;
|
||||
|
|
|
@ -325,33 +325,30 @@ public:
|
|||
BfTypeDef* mArray3TypeDef;
|
||||
BfTypeDef* mArray4TypeDef;
|
||||
BfTypeDef* mSpanTypeDef;
|
||||
BfTypeDef* mAttributeTypeDef;
|
||||
BfTypeDef* mAttributeUsageAttributeTypeDef;
|
||||
|
||||
BfTypeDef* mBfObjectTypeDef;
|
||||
BfTypeDef* mClassVDataTypeDef;
|
||||
BfTypeDef* mCLinkAttributeTypeDef;
|
||||
BfTypeDef* mCReprAttributeTypeDef;
|
||||
BfTypeDef* mNoDiscardAttributeTypeDef;
|
||||
BfTypeDef* mDisableObjectAccessChecksAttributeTypeDef;
|
||||
|
||||
BfTypeDef* mDbgRawAllocDataTypeDef;
|
||||
BfTypeDef* mDeferredCallTypeDef;
|
||||
BfTypeDef* mDelegateTypeDef;
|
||||
BfTypeDef* mEnumTypeDef;
|
||||
BfTypeDef* mFriendAttributeTypeDef;
|
||||
BfTypeDef* mCheckedAttributeTypeDef;
|
||||
BfTypeDef* mUncheckedAttributeTypeDef;
|
||||
BfTypeDef* mStringTypeDef;
|
||||
BfTypeDef* mTypeTypeDef;
|
||||
BfTypeDef* mValueTypeTypeDef;
|
||||
BfTypeDef* mFunctionTypeDef;
|
||||
BfTypeDef* mGCTypeDef;
|
||||
BfTypeDef* mGenericIEnumerableTypeDef;
|
||||
BfTypeDef* mGenericIEnumeratorTypeDef;
|
||||
BfTypeDef* mGenericIRefEnumeratorTypeDef;
|
||||
BfTypeDef* mInlineAttributeTypeDef;
|
||||
|
||||
BfTypeDef* mInternalTypeDef;
|
||||
BfTypeDef* mIPrintableTypeDef;
|
||||
BfTypeDef* mLinkNameAttributeTypeDef;
|
||||
BfTypeDef* mIHashableTypeDef;
|
||||
|
||||
BfTypeDef* mMethodRefTypeDef;
|
||||
BfTypeDef* mNullableTypeDef;
|
||||
BfTypeDef* mOrderedAttributeTypeDef;
|
||||
|
||||
BfTypeDef* mPointerTTypeDef;
|
||||
BfTypeDef* mPointerTypeDef;
|
||||
BfTypeDef* mReflectArrayType;
|
||||
|
@ -364,16 +361,30 @@ public:
|
|||
BfTypeDef* mReflectSpecializedGenericType;
|
||||
BfTypeDef* mReflectTypeInstanceTypeDef;
|
||||
BfTypeDef* mReflectUnspecializedGenericType;
|
||||
|
||||
BfTypeDef* mSizedArrayTypeDef;
|
||||
BfTypeDef* mAttributeTypeDef;
|
||||
BfTypeDef* mAttributeUsageAttributeTypeDef;
|
||||
BfTypeDef* mLinkNameAttributeTypeDef;
|
||||
BfTypeDef* mOrderedAttributeTypeDef;
|
||||
BfTypeDef* mInlineAttributeTypeDef;
|
||||
BfTypeDef* mCLinkAttributeTypeDef;
|
||||
BfTypeDef* mCReprAttributeTypeDef;
|
||||
BfTypeDef* mNoDiscardAttributeTypeDef;
|
||||
BfTypeDef* mDisableObjectAccessChecksAttributeTypeDef;
|
||||
BfTypeDef* mFriendAttributeTypeDef;
|
||||
BfTypeDef* mCheckedAttributeTypeDef;
|
||||
BfTypeDef* mUncheckedAttributeTypeDef;
|
||||
BfTypeDef* mSkipAccessCheckAttributeTypeDef;
|
||||
BfTypeDef* mStaticInitAfterAttributeTypeDef;
|
||||
BfTypeDef* mStaticInitPriorityAttributeTypeDef;
|
||||
BfTypeDef* mStringTypeDef;
|
||||
BfTypeDef* mTestAttributeTypeDef;
|
||||
BfTypeDef* mThreadStaticAttributeTypeDef;
|
||||
BfTypeDef* mTypeTypeDef;
|
||||
BfTypeDef* mUnboundAttributeTypeDef;
|
||||
BfTypeDef* mValueTypeTypeDef;
|
||||
BfTypeDef* mObsoleteAttributeTypeDef;
|
||||
BfTypeDef* mErrorAttributeTypeDef;
|
||||
BfTypeDef* mWarnAttributeTypeDef;
|
||||
|
||||
|
||||
int mCurTypeId;
|
||||
int mTypeInitCount;
|
||||
|
|
|
@ -88,6 +88,7 @@ BfContext::~BfContext()
|
|||
int numTypesDeleted = 0;
|
||||
for (auto type : mResolvedTypes)
|
||||
{
|
||||
//_CrtCheckMemory();
|
||||
delete type;
|
||||
}
|
||||
|
||||
|
@ -930,6 +931,11 @@ void BfContext::RebuildType(BfType* type, bool deleteOnDemandTypes, bool rebuild
|
|||
typeInst->mIsSplattable = false;
|
||||
typeInst->mHasPackingHoles = false;
|
||||
typeInst->mWantsGCMarking = false;
|
||||
if (typeInst->mTypeInfoEx != NULL)
|
||||
{
|
||||
delete typeInst->mTypeInfoEx;
|
||||
typeInst->mTypeInfoEx = NULL;
|
||||
}
|
||||
|
||||
if (typeInst->IsGenericTypeInstance())
|
||||
{
|
||||
|
@ -2082,6 +2088,9 @@ void BfContext::GenerateModuleName_Type(BfType* type, String& name)
|
|||
if (type->IsBoxed())
|
||||
{
|
||||
auto boxedType = (BfBoxedType*)type;
|
||||
if (boxedType->IsBoxedStructPtr())
|
||||
name += "BOXPTR_";
|
||||
else
|
||||
name += "BOX_";
|
||||
GenerateModuleName_Type(boxedType->mElementType, name);
|
||||
return;
|
||||
|
|
|
@ -1730,6 +1730,8 @@ String BfIRBuilder::GetDebugTypeName(BfTypeInstance* typeInstance, bool includeO
|
|||
{
|
||||
BfBoxedType* boxedType = (BfBoxedType*)typeInstance;
|
||||
typeName = mModule->TypeToString(boxedType->mElementType, (BfTypeNameFlags)(BfTypeNameFlag_ResolveGenericParamNames | BfTypeNameFlag_AddGlobalContainerName));
|
||||
if (boxedType->IsBoxedStructPtr())
|
||||
typeName += "*";
|
||||
typeName = "Box<" + typeName + ">";
|
||||
}
|
||||
else if (includeOuterTypeName)
|
||||
|
@ -2547,7 +2549,7 @@ void BfIRBuilder::CreateDbgTypeDefinition(BfType* type)
|
|||
}
|
||||
else if (type->IsBoxed())
|
||||
{
|
||||
auto underlyingType = typeInstance->GetUnderlyingType();
|
||||
auto underlyingType = ((BfBoxedType*)type)->GetModifiedElementType();
|
||||
if (!underlyingType->IsValuelessType())
|
||||
{
|
||||
auto fieldInstance = &typeInstance->mFieldInstances.back();
|
||||
|
@ -2705,9 +2707,14 @@ void BfIRBuilder::CreateTypeDefinition(BfType* type, bool forceDefine)
|
|||
if (typeInstance->IsBoxed())
|
||||
{
|
||||
auto boxedType = (BfBoxedType*)typeInstance;
|
||||
if (!boxedType->mElementType->IsValuelessType())
|
||||
BF_ASSERT(!boxedType->mFieldInstances.IsEmpty());
|
||||
|
||||
auto& fieldInst = boxedType->mFieldInstances.back();
|
||||
auto elementType = fieldInst.mResolvedType;
|
||||
|
||||
if (!elementType->IsValuelessType())
|
||||
{
|
||||
irFieldTypes.push_back(MapTypeInst(boxedType->mElementType, boxedType->mElementType->IsValueType() ? BfIRPopulateType_Eventually_Full : BfIRPopulateType_Declaration));
|
||||
irFieldTypes.push_back(MapType(elementType, elementType->IsValueType() ? BfIRPopulateType_Eventually_Full : BfIRPopulateType_Declaration));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -331,7 +331,7 @@ void BfGNUMangler::MangleTypeInst(MangleContext& mangleContext, StringImpl& name
|
|||
auto boxedType = (BfBoxedType*)typeInst;
|
||||
name += "N3BoxI";
|
||||
mangleContext.mSubstituteList.push_back(NameSubstitute(BfGNUMangler::NameSubstitute::Kind_None, NULL)); // Insert entry for 'Box'
|
||||
Mangle(mangleContext, name, boxedType->mElementType, postfixTypeInstance);
|
||||
Mangle(mangleContext, name, boxedType->GetModifiedElementType(), postfixTypeInstance);
|
||||
name += "E";
|
||||
mangleContext.mSubstituteList.push_back(NameSubstitute(BfGNUMangler::NameSubstitute::Kind_None, NULL)); // Insert entry for 'Box<T>'
|
||||
if (isEndOpen != NULL)
|
||||
|
@ -1158,7 +1158,7 @@ bool BfMSMangler::FindOrCreateNameSub(MangleContext& mangleContext, StringImpl&
|
|||
auto boxedType = (BfBoxedType*)newNameSub.mTypeInst;
|
||||
name += "?$Box@";
|
||||
BfTypeVector typeVec;
|
||||
typeVec.push_back(boxedType->mElementType);
|
||||
typeVec.push_back(boxedType->GetModifiedElementType());
|
||||
AddGenericArgs(mangleContext, name, typeVec);
|
||||
name += '@';
|
||||
}
|
||||
|
|
|
@ -1130,7 +1130,7 @@ void BfModule::EnsureIRBuilder(bool dbgVerifyCodeGen)
|
|||
// code as we walk the AST
|
||||
//mBfIRBuilder->mDbgVerifyCodeGen = true;
|
||||
if (
|
||||
(mModuleName == "-")
|
||||
(mModuleName == "Program")
|
||||
//|| (mModuleName == "System_Internal")
|
||||
//|| (mModuleName == "vdata")
|
||||
//|| (mModuleName == "Hey_Dude_Bro_TestClass")
|
||||
|
@ -1583,6 +1583,17 @@ int BfModule::GetStringPoolIdx(BfIRValue constantStr, BfIRConstHolder* constHold
|
|||
return -1;
|
||||
}
|
||||
|
||||
String* BfModule::GetStringPoolString(BfIRValue constantStr, BfIRConstHolder * constHolder)
|
||||
{
|
||||
int strId = GetStringPoolIdx(constantStr, constHolder);
|
||||
if (strId != -1)
|
||||
{
|
||||
auto& entry = mContext->mStringObjectIdMap[strId];
|
||||
return &entry.mString;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BfIRValue BfModule::GetStringCharPtr(int stringId)
|
||||
{
|
||||
BfIRValue* irValue = NULL;
|
||||
|
@ -4264,10 +4275,6 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
|
||||
BfTypeInstance* typeInstance = type->ToTypeInstance();
|
||||
|
||||
// BfType* typeInstanceType = ResolveTypeDef(mCompiler->mReflectTypeInstanceTypeDef, BfPopulateType_Identity);
|
||||
// mBfIRBuilder->PopulateType(typeInstanceType, BfIRPopulateType_Full_ForceDefinition);
|
||||
// PopulateType(typeInstanceType);
|
||||
|
||||
BfType* typeInstanceType = ResolveTypeDef(mCompiler->mReflectTypeInstanceTypeDef);
|
||||
mBfIRBuilder->PopulateType(typeInstanceType, BfIRPopulateType_Full_ForceDefinition);
|
||||
|
||||
|
@ -4379,7 +4386,11 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
if (type->IsStruct())
|
||||
typeFlags |= BfTypeFlags_Struct;
|
||||
if (type->IsBoxed())
|
||||
{
|
||||
typeFlags |= BfTypeFlags_Boxed;
|
||||
if (((BfBoxedType*)type)->IsBoxedStructPtr())
|
||||
typeFlags |= BfTypeFlags_Pointer;
|
||||
}
|
||||
if (type->IsPrimitiveType())
|
||||
typeFlags |= BfTypeFlags_Primitive;
|
||||
if (type->IsTypedPrimitive())
|
||||
|
@ -4573,10 +4584,11 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
{
|
||||
if (interfaceEntry.mInterfaceType->mSlotNum >= 0)
|
||||
{
|
||||
if (dynCastData[interfaceEntry.mInterfaceType->mSlotNum + 1] == 0)
|
||||
dynCastData[interfaceEntry.mInterfaceType->mSlotNum + 1] = interfaceEntry.mInterfaceType->mTypeId;
|
||||
}
|
||||
}
|
||||
checkTypeInst = checkTypeInst->mBaseType;
|
||||
checkTypeInst = checkTypeInst->GetImplBaseType();
|
||||
}
|
||||
|
||||
if (mSystem->mPtrSize == 8)
|
||||
|
@ -4633,6 +4645,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
Dictionary<BfTypeInstance*, _InterfaceMatchEntry> interfaceMap;
|
||||
auto checkTypeInst = typeInstance;
|
||||
|
||||
bool forceInterfaceSet = false;
|
||||
while (checkTypeInst != NULL)
|
||||
{
|
||||
for (auto&& interfaceEntry : checkTypeInst->mInterfaces)
|
||||
|
@ -4648,6 +4661,11 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
auto prevEntry = matchEntry->mEntry;
|
||||
bool isBetter = TypeIsSubTypeOf(checkTypeInst, matchEntry->mEntrySource);
|
||||
bool isWorse = TypeIsSubTypeOf(matchEntry->mEntrySource, checkTypeInst);
|
||||
if (forceInterfaceSet)
|
||||
{
|
||||
isBetter = true;
|
||||
isWorse = false;
|
||||
}
|
||||
if (isBetter == isWorse)
|
||||
CompareDeclTypes(interfaceEntry.mDeclaringType, prevEntry->mDeclaringType, isBetter, isWorse);
|
||||
if (isBetter == isWorse)
|
||||
|
@ -4675,7 +4693,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
}
|
||||
}
|
||||
|
||||
checkTypeInst = checkTypeInst->mBaseType;
|
||||
checkTypeInst = checkTypeInst->GetImplBaseType();
|
||||
}
|
||||
|
||||
for (auto interfacePair : interfaceMap)
|
||||
|
@ -4701,7 +4719,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
while (checkTypeInst != NULL)
|
||||
{
|
||||
origVirtTypeStack.push_back(checkTypeInst);
|
||||
checkTypeInst = checkTypeInst->mBaseType;
|
||||
checkTypeInst = checkTypeInst->GetImplBaseType();
|
||||
}
|
||||
|
||||
Array<BfVirtualMethodEntry> origVTable;
|
||||
|
@ -4860,14 +4878,6 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
makeEmpty = true;
|
||||
|
||||
int endVirtualIdx = interfaceEntry->mStartVirtualIdx + interfaceEntry->mInterfaceType->mVirtualMethodTableSize;
|
||||
// for (int methodIdx = 0; methodIdx < (int)interfaceEntry->mInterfaceType->mMethodInstanceGroups.size(); methodIdx++)
|
||||
// {
|
||||
// BfMethodInstance* ifaceMethodInstance = interfaceEntry->mInterfaceType->mMethodInstanceGroups[methodIdx].mDefault;
|
||||
// if ((ifaceMethodInstance == NULL) || (ifaceMethodInstance->mVirtualTableIdx == -1))
|
||||
// continue;
|
||||
// endVirtualIdx = BF_MAX(endVirtualIdx, interfaceEntry->mStartVirtualIdx + ifaceMethodInstance->mVirtualTableIdx);
|
||||
// }
|
||||
|
||||
bool useExt = endVirtualIdx > ifaceMethodExtStart;
|
||||
|
||||
for (int methodIdx = 0; methodIdx < (int)interfaceEntry->mInterfaceType->mMethodInstanceGroups.size(); methodIdx++)
|
||||
|
@ -4894,7 +4904,6 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
BF_ASSERT(methodInstance->mIsReified);
|
||||
// This doesn't work because we may have FOREIGN methods from implicit interface methods
|
||||
//auto moduleMethodInst = GetMethodInstanceAtIdx(methodRef.mTypeInstance, methodRef.mMethodNum);
|
||||
BfMethodInstance* methodInstance = methodRef;
|
||||
auto moduleMethodInst = ReferenceExternalMethodInstance(methodInstance);
|
||||
auto funcPtr = mBfIRBuilder->CreateBitCast(moduleMethodInst.mFunc, voidPtrIRType);
|
||||
pushValue = funcPtr;
|
||||
|
@ -4906,8 +4915,6 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
}
|
||||
|
||||
int idx = interfaceEntry->mStartVirtualIdx + ifaceMethodInstance->mVirtualTableIdx;
|
||||
// if (!useExt)
|
||||
// vData[iFaceMethodStartIdx + idx] = pushValue;
|
||||
if (idx < ifaceMethodExtStart)
|
||||
{
|
||||
BF_ASSERT(iFaceMethodStartIdx + idx < (int)vData.size());
|
||||
|
@ -4924,6 +4931,45 @@ BfIRValue BfModule::CreateTypeData(BfType* type, Dictionary<int, int>& usedStrin
|
|||
}
|
||||
}
|
||||
|
||||
if (typeInstance->IsBoxed())
|
||||
{
|
||||
BfBoxedType* boxedType = (BfBoxedType*)typeInstance;
|
||||
if (boxedType->IsBoxedStructPtr())
|
||||
{
|
||||
// Force override of GetHashCode so we use the pointer address as the hash code
|
||||
checkTypeInst = CreateBoxedType(ResolveTypeDef(mCompiler->mPointerTypeDef));
|
||||
|
||||
// Force override of GetHashCode so we use the pointer address as the hash code
|
||||
for (auto& checkIFace : checkTypeInst->mInterfaces)
|
||||
{
|
||||
for (int methodIdx = 0; methodIdx < (int)checkIFace.mInterfaceType->mMethodInstanceGroups.size(); methodIdx++)
|
||||
{
|
||||
BfIRValue pushValue;
|
||||
|
||||
BfMethodInstance* ifaceMethodInstance = checkIFace.mInterfaceType->mMethodInstanceGroups[methodIdx].mDefault;
|
||||
if ((ifaceMethodInstance == NULL) || (ifaceMethodInstance->mVirtualTableIdx == -1))
|
||||
continue;
|
||||
|
||||
if ((!ifaceMethodInstance->mIsReified) || (!ifaceMethodInstance->mMethodInstanceGroup->IsImplemented()))
|
||||
continue;
|
||||
|
||||
auto& methodRef = checkTypeInst->mInterfaceMethodTable[checkIFace.mStartInterfaceTableIdx + methodIdx].mMethodRef;
|
||||
|
||||
auto methodInstance = (BfMethodInstance*)methodRef;
|
||||
BF_ASSERT(methodInstance->mIsReified);
|
||||
// This doesn't work because we may have FOREIGN methods from implicit interface methods
|
||||
//auto moduleMethodInst = GetMethodInstanceAtIdx(methodRef.mTypeInstance, methodRef.mMethodNum);
|
||||
auto moduleMethodInst = ReferenceExternalMethodInstance(methodInstance);
|
||||
auto funcPtr = mBfIRBuilder->CreateBitCast(moduleMethodInst.mFunc, voidPtrIRType);
|
||||
|
||||
int idx = checkIFace.mStartVirtualIdx + ifaceMethodInstance->mVirtualTableIdx;
|
||||
vData[iFaceMethodStartIdx + idx] = funcPtr;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((needsVData) && (!typeInstance->mTypeDef->mIsStatic))
|
||||
{
|
||||
BfIRValue ifaceMethodExtVar;
|
||||
|
@ -6541,7 +6587,15 @@ bool BfModule::CheckGenericConstraints(const BfGenericParamSource& genericParamS
|
|||
|
||||
BfTypeInstance* typeConstraintInst = convCheckConstraint->ToTypeInstance();
|
||||
|
||||
bool implementsInterface = CanImplicitlyCast(checkArgType, convCheckConstraint);
|
||||
bool implementsInterface = false;
|
||||
if (origCheckArgType != checkArgType)
|
||||
{
|
||||
implementsInterface = CanImplicitlyCast(origCheckArgType, convCheckConstraint);
|
||||
}
|
||||
|
||||
if (!implementsInterface)
|
||||
implementsInterface = CanImplicitlyCast(checkArgType, convCheckConstraint);
|
||||
|
||||
if ((!implementsInterface) && (origCheckArgType->IsWrappableType()))
|
||||
{
|
||||
BfTypeInstance* wrappedStructType = GetWrappedStructType(origCheckArgType, false);
|
||||
|
@ -8228,23 +8282,40 @@ BfTypedValue BfModule::BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
|||
return BfTypedValue(phi, resultType);
|
||||
}
|
||||
|
||||
if (fromStructTypeInstance == NULL)
|
||||
{
|
||||
auto primType = (BfPrimitiveType*) typedVal.mType;
|
||||
fromStructTypeInstance = GetWrappedStructType(typedVal.mType);
|
||||
}
|
||||
if (fromStructTypeInstance == NULL)
|
||||
return BfTypedValue();
|
||||
bool alreadyCheckedCast = false;
|
||||
|
||||
BfTypeInstance* toTypeInstance = NULL;
|
||||
if (toType != NULL)
|
||||
toTypeInstance = toType->ToTypeInstance();
|
||||
|
||||
// Need to box it
|
||||
bool isBoxedType = (fromStructTypeInstance != NULL) && (toType->IsBoxed()) && (CreateBoxedType(fromStructTypeInstance) == toType);
|
||||
|
||||
if ((toType == NULL) || (toType == mContext->mBfObjectType) || (isBoxedType) || (TypeIsSubTypeOf(fromStructTypeInstance, toTypeInstance)))
|
||||
bool isStructPtr = typedVal.mType->IsStructPtr();
|
||||
if (fromStructTypeInstance == NULL)
|
||||
{
|
||||
auto boxedType = CreateBoxedType(fromStructTypeInstance);
|
||||
auto primType = (BfPrimitiveType*)typedVal.mType;
|
||||
fromStructTypeInstance = GetWrappedStructType(typedVal.mType);
|
||||
|
||||
if (isStructPtr)
|
||||
{
|
||||
if ((toTypeInstance != NULL) && (TypeIsSubTypeOf(fromStructTypeInstance, toTypeInstance)))
|
||||
alreadyCheckedCast = true;
|
||||
|
||||
fromStructTypeInstance = typedVal.mType->GetUnderlyingType()->ToTypeInstance();
|
||||
}
|
||||
}
|
||||
if (fromStructTypeInstance == NULL)
|
||||
return BfTypedValue();
|
||||
|
||||
// Need to box it
|
||||
auto boxedType = CreateBoxedType(typedVal.mType);
|
||||
bool isBoxedType = (fromStructTypeInstance != NULL) && (toType->IsBoxed()) && (boxedType == toType);
|
||||
|
||||
if ((toType == NULL) || (toType == mContext->mBfObjectType) || (isBoxedType) || (alreadyCheckedCast) || (TypeIsSubTypeOf(fromStructTypeInstance, toTypeInstance)))
|
||||
{
|
||||
if (typedVal.mType->IsPointer())
|
||||
{
|
||||
NOP;
|
||||
}
|
||||
|
||||
mBfIRBuilder->PopulateType(boxedType);
|
||||
AddDependency(boxedType, mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
|
||||
auto allocaInst = AllocFromType(boxedType, allocTarget, BfIRValue(), BfIRValue(), 0, callDtor ? BfAllocFlags_None : BfAllocFlags_NoDtorCall);
|
||||
|
@ -8264,7 +8335,7 @@ BfTypedValue BfModule::BoxValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
|
|||
typedVal = LoadValue(typedVal);
|
||||
auto valPtr = mBfIRBuilder->CreateInBoundsGEP(allocaInst, 0, 1);
|
||||
|
||||
if (typedVal.mType != fromStructTypeInstance)
|
||||
if ((typedVal.mType != fromStructTypeInstance) && (!isStructPtr))
|
||||
{
|
||||
auto ptrType = CreatePointerType(typedVal.mType);
|
||||
valPtr = mBfIRBuilder->CreateBitCast(valPtr, mBfIRBuilder->MapType(ptrType));
|
||||
|
@ -16573,6 +16644,12 @@ void BfModule::ProcessMethod(BfMethodInstance* methodInstance, bool isInlineDup)
|
|||
{
|
||||
BfIRValue thisValue = mBfIRBuilder->CreateInBoundsGEP(mCurMethodState->mLocals[0]->mValue, 0, 1);
|
||||
BfTypedValue innerVal(thisValue, innerType, true);
|
||||
if (boxedType->IsBoxedStructPtr())
|
||||
{
|
||||
innerVal = LoadValue(innerVal);
|
||||
innerVal = BfTypedValue(innerVal.mValue, innerType, true);
|
||||
}
|
||||
|
||||
exprEvaluator.PushThis(NULL, innerVal, innerMethodInstance.mMethodInstance, innerParams);
|
||||
}
|
||||
|
||||
|
|
|
@ -1388,6 +1388,7 @@ public:
|
|||
BfIRValue CreateStringObjectValue(const StringImpl& str, int stringId, bool define);
|
||||
BfIRValue CreateStringCharPtr(const StringImpl& str, int stringId, bool define);
|
||||
int GetStringPoolIdx(BfIRValue constantStr, BfIRConstHolder* constHolder = NULL);
|
||||
String* GetStringPoolString(BfIRValue constantStr, BfIRConstHolder* constHolder = NULL);
|
||||
BfIRValue GetStringCharPtr(int stringId);
|
||||
BfIRValue GetStringCharPtr(BfIRValue strValue);
|
||||
BfIRValue GetStringCharPtr(const StringImpl& str);
|
||||
|
|
|
@ -1749,11 +1749,6 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
if (baseType != NULL)
|
||||
defaultBaseTypeInst = baseType->ToTypeInstance();
|
||||
|
||||
if (typeInstance->mTypeId == 260)
|
||||
{
|
||||
NOP;
|
||||
}
|
||||
|
||||
BfTypeReference* baseTypeRef = NULL;
|
||||
if ((typeDef->mIsDelegate) && (!typeInstance->IsClosure()))
|
||||
{
|
||||
|
@ -1902,6 +1897,18 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
|
||||
if (resolvedTypeRef->IsBoxed())
|
||||
{
|
||||
if ((baseType != NULL) && (baseType->IsStruct()))
|
||||
{
|
||||
BfBoxedType* boxedType = (BfBoxedType*)resolvedTypeRef;
|
||||
BfType* modifiedBaseType = baseType;
|
||||
if (boxedType->IsBoxedStructPtr())
|
||||
modifiedBaseType = CreatePointerType(modifiedBaseType);
|
||||
boxedType->mBoxedBaseType = CreateBoxedType(modifiedBaseType);
|
||||
|
||||
PopulateType(boxedType->mBoxedBaseType);
|
||||
AddDependency(boxedType->mBoxedBaseType, typeInstance, BfDependencyMap::DependencyFlag_DerivedFrom);
|
||||
}
|
||||
|
||||
baseType = mContext->mBfObjectType;
|
||||
}
|
||||
|
||||
|
@ -2097,16 +2104,18 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
if (resolvedTypeRef->IsBoxed())
|
||||
{
|
||||
BfBoxedType* boxedType = (BfBoxedType*)resolvedTypeRef;
|
||||
BfTypeInstance* innerType = boxedType->mElementType->ToTypeInstance();
|
||||
BfType* innerType = boxedType->mElementType;
|
||||
if (boxedType->IsBoxedStructPtr())
|
||||
innerType = CreatePointerType(innerType);
|
||||
if (innerType->IsIncomplete())
|
||||
PopulateType(innerType, BfPopulateType_Data);
|
||||
|
||||
auto baseType = typeInstance->mBaseType;
|
||||
dataPos = baseType->mInstSize;
|
||||
int alignSize = std::max(innerType->mInstAlign, baseType->mInstAlign);
|
||||
int alignSize = BF_MAX(innerType->mAlign, baseType->mInstAlign);
|
||||
if (alignSize > 1)
|
||||
dataPos = (dataPos + (alignSize - 1)) & ~(alignSize - 1);
|
||||
int dataSize = innerType->mInstSize;
|
||||
int dataSize = innerType->mSize;
|
||||
|
||||
typeInstance->mFieldInstances.push_back(BfFieldInstance());
|
||||
BfFieldInstance* fieldInstance = &typeInstance->mFieldInstances.back();
|
||||
|
@ -2946,25 +2955,47 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
BfLogSysM("Setting underlying type %p %d\n", typeInstance, underlyingTypeDeferred);
|
||||
}
|
||||
|
||||
if (underlyingTypeDeferred)
|
||||
if (typeInstance->IsEnum())
|
||||
{
|
||||
int64 min = 0;
|
||||
int64 max = 0;
|
||||
|
||||
bool isFirst = false;
|
||||
|
||||
if (typeInstance->mTypeInfoEx == NULL)
|
||||
typeInstance->mTypeInfoEx = new BfTypeInfoEx();
|
||||
|
||||
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
||||
{
|
||||
auto fieldInstance = &fieldInstanceRef;
|
||||
auto fieldDef = fieldInstance->GetFieldDef();
|
||||
if ((fieldDef != NULL) && (fieldDef->IsEnumCaseEntry()))
|
||||
{
|
||||
auto constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx);
|
||||
BF_ASSERT(constant->mTypeCode == BfTypeCode_Int64);
|
||||
if (fieldInstance->mConstIdx == -1)
|
||||
continue;
|
||||
|
||||
auto constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx);
|
||||
BF_ASSERT((constant->mTypeCode == BfTypeCode_Int64) || (!underlyingTypeDeferred));
|
||||
|
||||
if (isFirst)
|
||||
{
|
||||
min = constant->mInt64;
|
||||
max = constant->mInt64;
|
||||
isFirst = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
min = BF_MIN(constant->mInt64, min);
|
||||
max = BF_MAX(constant->mInt64, max);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typeInstance->mTypeInfoEx->mMinValue = min;
|
||||
typeInstance->mTypeInfoEx->mMaxValue = max;
|
||||
|
||||
if (underlyingTypeDeferred)
|
||||
{
|
||||
BfTypeCode typeCode;
|
||||
|
||||
if ((min >= -0x80) && (max <= 0x7F))
|
||||
|
@ -3001,6 +3032,8 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
fieldInstance->mResolvedType = underlyingType;
|
||||
fieldInstance->mDataSize = underlyingType->mSize;
|
||||
|
||||
typeInstance->mTypeInfoEx->mUnderlyingType = underlyingType;
|
||||
|
||||
typeInstance->mSize = underlyingType->mSize;
|
||||
typeInstance->mAlign = underlyingType->mAlign;
|
||||
typeInstance->mInstSize = underlyingType->mSize;
|
||||
|
@ -3008,6 +3041,11 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
|
||||
typeInstance->mRebuildFlags = (BfTypeRebuildFlags)(typeInstance->mRebuildFlags & ~BfTypeRebuildFlag_UnderlyingTypeDeferred);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BF_ASSERT(!underlyingTypeDeferred);
|
||||
}
|
||||
|
||||
if ((typeInstance->IsPayloadEnum()) && (!typeInstance->IsBoxed()))
|
||||
{
|
||||
|
@ -3104,33 +3142,8 @@ bool BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
|||
}
|
||||
}
|
||||
|
||||
//TODO: We moved this to much earlier in InitType
|
||||
// This allows us to properly deleted a dependent generic type if a typeGenericArg gets deleted.
|
||||
//...
|
||||
// Add generic dependencies if needed
|
||||
// auto genericTypeInstance = typeInstance->ToGenericTypeInstance();
|
||||
// if (genericTypeInstance != NULL)
|
||||
// {
|
||||
// for (auto genericType : genericTypeInstance->mTypeGenericArguments)
|
||||
// {
|
||||
// if (genericType->IsPrimitiveType())
|
||||
// genericType = GetWrappedStructType(genericType);
|
||||
// if (genericType != NULL)
|
||||
// {
|
||||
// AddDependency(genericType, genericTypeInstance, BfDependencyMap::DependencyFlag_TypeGenericArg);
|
||||
// BfLogSysM("Adding generic dependency of %p for type %p\n", genericTypeInstance, genericTypeInstance);
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// if (typeInstance->IsSpecializedType())
|
||||
// {
|
||||
// // This ensures we rebuild the unspecialized type whenever the specialized type rebuilds. This is important
|
||||
// // for generic type binding
|
||||
// auto unspecializedTypeInstance = GetUnspecializedTypeInstance(typeInstance);
|
||||
// BF_ASSERT(!unspecializedTypeInstance->IsUnspecializedTypeVariation());
|
||||
// mContext->mScratchModule->AddDependency(typeInstance, unspecializedTypeInstance, BfDependencyMap::DependencyFlag_UnspecializedType);
|
||||
// }
|
||||
// }
|
||||
if (typeInstance == mContext->mBfObjectType)
|
||||
typeInstance->mHasBeenInstantiated = true;
|
||||
|
||||
if (populateType == BfPopulateType_Data)
|
||||
return true;
|
||||
|
@ -3181,16 +3194,16 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
|||
}
|
||||
|
||||
int newIntefaceStartIdx = 0;
|
||||
auto baseType = typeInstance->mBaseType;
|
||||
if (baseType != NULL)
|
||||
auto implBaseType = typeInstance->GetImplBaseType();
|
||||
if (implBaseType != NULL)
|
||||
{
|
||||
auto baseTypeInst = baseType->ToTypeInstance();
|
||||
if (baseType->IsIncomplete())
|
||||
PopulateType(baseType, BfPopulateType_Full_Force);
|
||||
auto baseTypeInst = implBaseType->ToTypeInstance();
|
||||
if (implBaseType->IsIncomplete())
|
||||
PopulateType(implBaseType, BfPopulateType_Full_Force);
|
||||
|
||||
typeInstance->mInterfaceMethodTable = baseTypeInst->mInterfaceMethodTable;
|
||||
typeInstance->mVirtualMethodTable = baseType->mVirtualMethodTable;
|
||||
typeInstance->mVirtualMethodTableSize = baseType->mVirtualMethodTableSize;
|
||||
typeInstance->mVirtualMethodTable = implBaseType->mVirtualMethodTable;
|
||||
typeInstance->mVirtualMethodTableSize = implBaseType->mVirtualMethodTableSize;
|
||||
if ((!mCompiler->IsHotCompile()) && (!mCompiler->mPassInstance->HasFailed()) && ((mCompiler->mResolvePassData == NULL) || (mCompiler->mResolvePassData->mAutoComplete == NULL)))
|
||||
{
|
||||
BF_ASSERT(typeInstance->mVirtualMethodTable.size() == typeInstance->mVirtualMethodTableSize);
|
||||
|
@ -3231,7 +3244,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
|||
{
|
||||
AddDependency(interfaceEntry.mInterfaceType, typeInstance, BfDependencyMap::DependencyFlag_ImplementsInterface);
|
||||
}
|
||||
checkTypeInstance = checkTypeInstance->mBaseType;
|
||||
checkTypeInstance = checkTypeInstance->GetImplBaseType();
|
||||
}
|
||||
|
||||
//for (auto& intefaceInst : typeInstance->mInterfaces)
|
||||
|
@ -3241,11 +3254,16 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
|||
BF_ASSERT(typeInstance->mInterfaceMethodTable.size() == 1);
|
||||
}
|
||||
|
||||
if (typeInstance->mTypeDef == mCompiler->mPointerTypeDef)
|
||||
{
|
||||
NOP;
|
||||
}
|
||||
|
||||
// Slot interfaces method blocks in vtable
|
||||
{
|
||||
int ifaceVirtIdx = 0;
|
||||
std::unordered_map<BfTypeInstance*, BfTypeInterfaceEntry*> interfaceMap;
|
||||
BfTypeInstance* checkType = typeInstance->mBaseType;
|
||||
BfTypeInstance* checkType = typeInstance->GetImplBaseType();
|
||||
while (checkType != NULL)
|
||||
{
|
||||
for (auto&& ifaceEntry : checkType->mInterfaces)
|
||||
|
@ -3253,7 +3271,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
|||
interfaceMap[ifaceEntry.mInterfaceType] = &ifaceEntry;
|
||||
ifaceVirtIdx = std::max(ifaceVirtIdx, ifaceEntry.mStartVirtualIdx + ifaceEntry.mInterfaceType->mVirtualMethodTableSize);
|
||||
}
|
||||
checkType = checkType->mBaseType;
|
||||
checkType = checkType->GetImplBaseType();
|
||||
}
|
||||
|
||||
for (int iFaceIdx = 0; iFaceIdx < (int)typeInstance->mInterfaces.size(); iFaceIdx++)
|
||||
|
@ -3279,12 +3297,12 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
|||
typeInstance->mNeedsMethodProcessing = false;
|
||||
typeInstance->mTypeIncomplete = false;
|
||||
|
||||
auto checkBaseType = typeInstance->mBaseType;
|
||||
auto checkBaseType = typeInstance->GetImplBaseType();
|
||||
while (checkBaseType != NULL)
|
||||
{
|
||||
PopulateType(checkBaseType, BfPopulateType_Full_Force);
|
||||
BF_ASSERT((!checkBaseType->IsIncomplete()) || (checkBaseType->mTypeFailed));
|
||||
checkBaseType = checkBaseType->mBaseType;
|
||||
checkBaseType = checkBaseType->GetImplBaseType();
|
||||
}
|
||||
|
||||
if ((mCompiler->mOptions.mHasVDataExtender) && (!typeInstance->IsInterface()))
|
||||
|
@ -3733,8 +3751,8 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
|||
BF_ASSERT(mCompiler->mOptions.mHasVDataExtender);
|
||||
if (methodRef.mTypeInstance == typeInstance)
|
||||
{
|
||||
if (typeInstance->mBaseType != NULL)
|
||||
BF_ASSERT(methodIdx == (int)typeInstance->mBaseType->mVirtualMethodTableSize);
|
||||
if (typeInstance->GetImplBaseType() != NULL)
|
||||
BF_ASSERT(methodIdx == (int)typeInstance->GetImplBaseType()->mVirtualMethodTableSize);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -3782,7 +3800,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
|||
{
|
||||
// Attempt to find matching entries in base types
|
||||
ambiguityContext.mIsReslotting = true;
|
||||
auto checkType = typeInstance->mBaseType;
|
||||
auto checkType = typeInstance->GetImplBaseType();
|
||||
while (checkType != NULL)
|
||||
{
|
||||
for (auto& methodGroup : checkType->mMethodInstanceGroups)
|
||||
|
@ -3798,7 +3816,7 @@ void BfModule::DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance)
|
|||
}
|
||||
}
|
||||
}
|
||||
checkType = checkType->mBaseType;
|
||||
checkType = checkType->GetImplBaseType();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4626,8 +4644,10 @@ BfTypeInstance* BfModule::GetPrimitiveStructType(BfTypeCode typeCode)
|
|||
|
||||
BfBoxedType* BfModule::CreateBoxedType(BfType* resolvedTypeRef)
|
||||
{
|
||||
if (resolvedTypeRef->IsPointer())
|
||||
resolvedTypeRef = ((BfPointerType*)resolvedTypeRef)->mElementType;
|
||||
bool isStructPtr = false;
|
||||
|
||||
// if (resolvedTypeRef->IsPointer())
|
||||
// resolvedTypeRef = ((BfPointerType*)resolvedTypeRef)->mElementType;
|
||||
if (resolvedTypeRef->IsPrimitiveType())
|
||||
{
|
||||
auto primType = (BfPrimitiveType*)resolvedTypeRef;
|
||||
|
@ -4641,10 +4661,18 @@ BfBoxedType* BfModule::CreateBoxedType(BfType* resolvedTypeRef)
|
|||
else if (resolvedTypeRef->IsPointer())
|
||||
{
|
||||
BfPointerType* pointerType = (BfPointerType*)resolvedTypeRef;
|
||||
if (pointerType->mElementType->IsStruct())
|
||||
{
|
||||
resolvedTypeRef = pointerType->mElementType;
|
||||
isStructPtr = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
BfTypeVector typeVector;
|
||||
typeVector.Add(pointerType->mElementType);
|
||||
resolvedTypeRef = ResolveTypeDef(mCompiler->mPointerTTypeDef, typeVector, BfPopulateType_Data)->ToTypeInstance();
|
||||
}
|
||||
}
|
||||
else if (resolvedTypeRef->IsMethodRef())
|
||||
{
|
||||
BfMethodRefType* methodRefType = (BfMethodRefType*)resolvedTypeRef;
|
||||
|
@ -4670,6 +4698,7 @@ BfBoxedType* BfModule::CreateBoxedType(BfType* resolvedTypeRef)
|
|||
boxedType->mContext = mContext;
|
||||
boxedType->mElementType = typeInst;
|
||||
boxedType->mTypeDef = boxedType->mElementType->mTypeDef;
|
||||
boxedType->mBoxedFlags = isStructPtr ? BfBoxedType::BoxedFlags_StructPtr : BfBoxedType::BoxedFlags_None;
|
||||
auto resolvedBoxedType = ResolveType(boxedType);
|
||||
if (resolvedBoxedType != boxedType)
|
||||
mContext->mBoxedTypePool.GiveBack(boxedType);
|
||||
|
@ -6904,7 +6933,6 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
auto outerType = typeDef->mOuterType;
|
||||
BF_ASSERT(!outerType->mIsPartial);
|
||||
if (TypeHasParent(mCurTypeInstance->mTypeDef, outerType))
|
||||
|
||||
{
|
||||
BfType* checkCurType = mCurTypeInstance;
|
||||
if (checkCurType->IsBoxed())
|
||||
|
@ -6975,24 +7003,6 @@ BfType* BfModule::ResolveTypeRef(BfTypeReference* typeRef, BfPopulateType popula
|
|||
InitType(typeInst, populateType);
|
||||
return ResolveTypeResult(typeRef, typeInst, populateType, resolveFlags);
|
||||
}
|
||||
else if (auto boxedTypeRef = BfNodeDynCast<BfBoxedTypeRef>(typeRef))
|
||||
{
|
||||
BfBoxedType* boxedType = new BfBoxedType();
|
||||
auto innerType = ResolveTypeRef(boxedTypeRef->mElementType, BfPopulateType_Declaration, BfResolveTypeRefFlag_AllowGenericParamConstValue);
|
||||
if ((innerType == NULL) || (!innerType->IsStruct()))
|
||||
{
|
||||
Fail("Invalid box target", boxedTypeRef->mElementType);
|
||||
delete boxedType;
|
||||
mContext->mResolvedTypes.RemoveEntry(resolvedEntry);
|
||||
return ResolveTypeResult(typeRef, NULL, populateType, resolveFlags);
|
||||
}
|
||||
boxedType->mElementType = innerType->ToTypeInstance();
|
||||
boxedType->mTypeDef = boxedType->mElementType->mTypeDef;
|
||||
resolvedEntry->mValue = boxedType;
|
||||
BF_ASSERT(BfResolvedTypeSet::Hash(boxedType, &lookupCtx) == resolvedEntry->mHash);
|
||||
InitType(boxedType, populateType);
|
||||
return ResolveTypeResult(typeRef, boxedType, populateType, resolveFlags);
|
||||
}
|
||||
else if (auto arrayTypeRef = BfNodeDynCast<BfArrayTypeRef>(typeRef))
|
||||
{
|
||||
if (arrayTypeRef->mDimensions > 4)
|
||||
|
@ -10059,13 +10069,24 @@ bool BfModule::TypeIsSubTypeOf(BfTypeInstance* srcType, BfTypeInstance* wantType
|
|||
return true;
|
||||
}
|
||||
}
|
||||
checkType = checkType->mBaseType;
|
||||
checkType = checkType->GetImplBaseType();
|
||||
if ((checkType != NULL) && (checkType->mDefineState < BfTypeDefineState_HasInterfaces))
|
||||
{
|
||||
PopulateType(checkType, BfPopulateType_Interfaces);
|
||||
}
|
||||
}
|
||||
|
||||
if (srcType->IsTypedPrimitive())
|
||||
{
|
||||
BfType* underlyingType = srcType->GetUnderlyingType();
|
||||
if (underlyingType->IsWrappableType())
|
||||
{
|
||||
BfTypeInstance* wrappedType = GetWrappedStructType(underlyingType);
|
||||
if ((wrappedType != NULL) && (wrappedType != srcType))
|
||||
return TypeIsSubTypeOf(wrappedType, wantType, checkAccessibility);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -10243,9 +10264,11 @@ void BfModule::DoTypeToString(StringImpl& str, BfType* resolvedType, BfTypeNameF
|
|||
|
||||
if (resolvedType->IsBoxed())
|
||||
{
|
||||
auto boxedeType = (BfBoxedType*)resolvedType;
|
||||
auto boxedType = (BfBoxedType*)resolvedType;
|
||||
str += "boxed ";
|
||||
DoTypeToString(str, boxedeType->mElementType, typeNameFlags, genericMethodNameOverrides);
|
||||
DoTypeToString(str, boxedType->mElementType, typeNameFlags, genericMethodNameOverrides);
|
||||
if (boxedType->mBoxedFlags == BfBoxedType::BoxedFlags_StructPtr)
|
||||
str += "*";
|
||||
return;
|
||||
}
|
||||
else if ((resolvedType->IsArray()) && ((typeNameFlags & BfTypeNameFlag_UseArrayImplType) == 0))
|
||||
|
|
|
@ -1087,6 +1087,7 @@ BfMethodInstanceGroup::~BfMethodInstanceGroup()
|
|||
|
||||
BfTypeInstance::~BfTypeInstance()
|
||||
{
|
||||
delete mTypeInfoEx;
|
||||
delete mCustomAttributes;
|
||||
delete mAttributeData;
|
||||
for (auto methodInst : mInternalMethods)
|
||||
|
@ -1622,17 +1623,25 @@ BfType* BfTypeInstance::GetUnderlyingType()
|
|||
if (!mIsTypedPrimitive)
|
||||
return NULL;
|
||||
|
||||
if (mTypeInfoEx == NULL)
|
||||
mTypeInfoEx = new BfTypeInfoEx();
|
||||
if (mTypeInfoEx->mUnderlyingType != NULL)
|
||||
return mTypeInfoEx->mUnderlyingType;
|
||||
|
||||
auto checkTypeInst = this;
|
||||
while (checkTypeInst != NULL)
|
||||
{
|
||||
if (!checkTypeInst->mFieldInstances.empty())
|
||||
return checkTypeInst->mFieldInstances.back().mResolvedType;
|
||||
{
|
||||
mTypeInfoEx->mUnderlyingType = checkTypeInst->mFieldInstances.back().mResolvedType;
|
||||
return mTypeInfoEx->mUnderlyingType;
|
||||
}
|
||||
checkTypeInst = checkTypeInst->mBaseType;
|
||||
if (checkTypeInst->IsIncomplete())
|
||||
mModule->PopulateType(checkTypeInst, BfPopulateType_Data);
|
||||
}
|
||||
BF_FATAL("Failed");
|
||||
return NULL;
|
||||
return mTypeInfoEx->mUnderlyingType;
|
||||
}
|
||||
|
||||
bool BfTypeInstance::IsValuelessType()
|
||||
|
@ -1857,6 +1866,15 @@ void BfTupleType::Finish()
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BfType* BfBoxedType::GetModifiedElementType()
|
||||
{
|
||||
if ((mBoxedFlags & BoxedFlags_StructPtr) != 0)
|
||||
return mModule->CreatePointerType(mElementType);
|
||||
return mElementType;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int BfArrayType::GetLengthBitCount()
|
||||
{
|
||||
if (mBaseType == NULL)
|
||||
|
@ -2461,11 +2479,6 @@ int BfResolvedTypeSet::Hash(BfTypeReference* typeRef, LookupContext* ctx, BfHash
|
|||
hashVal = ((hashVal ^ (Hash(nullableType->mElementType, ctx))) << 5) - hashVal;
|
||||
return hashVal;
|
||||
}
|
||||
else if (auto boxedType = BfNodeDynCastExact<BfBoxedTypeRef>(typeRef))
|
||||
{
|
||||
int elemHash = Hash(boxedType->mElementType, ctx) ^ HASH_VAL_BOXED;
|
||||
return (elemHash << 5) - elemHash;
|
||||
}
|
||||
else if (auto refType = BfNodeDynCastExact<BfRefTypeRef>(typeRef))
|
||||
{
|
||||
if ((flags & BfHashFlag_AllowRef) != 0)
|
||||
|
@ -2654,8 +2667,10 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfType* rhs, LookupContext* ctx)
|
|||
{
|
||||
if (!rhs->IsBoxed())
|
||||
return false;
|
||||
BfBoxedType* lhsBoxedType = (BfBoxedType*) lhs;
|
||||
BfBoxedType* rhsBoxedType = (BfBoxedType*) rhs;
|
||||
BfBoxedType* lhsBoxedType = (BfBoxedType*)lhs;
|
||||
BfBoxedType* rhsBoxedType = (BfBoxedType*)rhs;
|
||||
if (lhsBoxedType->mBoxedFlags != rhsBoxedType->mBoxedFlags)
|
||||
return false;
|
||||
return Equals(lhsBoxedType->mElementType, rhsBoxedType->mElementType, ctx);
|
||||
}
|
||||
else if (lhs->IsArray())
|
||||
|
@ -3050,11 +3065,7 @@ bool BfResolvedTypeSet::Equals(BfType* lhs, BfTypeReference* rhs, LookupContext*
|
|||
|
||||
if (lhs->IsBoxed())
|
||||
{
|
||||
auto rhsBoxedTypeRef = BfNodeDynCastExact<BfBoxedTypeRef>(rhs);
|
||||
if (rhsBoxedTypeRef == NULL)
|
||||
return false;
|
||||
BfBoxedType* lhsBoxedType = (BfBoxedType*) lhs;
|
||||
return Equals(lhsBoxedType->mElementType, rhsBoxedTypeRef->mElementType, ctx);
|
||||
}
|
||||
else if (lhs->IsArray())
|
||||
{
|
||||
|
@ -3701,8 +3712,6 @@ String BfTypeUtils::TypeToString(BfTypeReference* typeRef)
|
|||
|
||||
if (auto ptrType = BfNodeDynCast<BfPointerTypeRef>(typeRef))
|
||||
return TypeToString(ptrType->mElementType) + "*";
|
||||
if (auto boxedType = BfNodeDynCast<BfBoxedTypeRef>(typeRef))
|
||||
return "boxed " + TypeToString(boxedType->mElementType);
|
||||
if (auto ptrType = BfNodeDynCast<BfArrayTypeRef>(typeRef))
|
||||
{
|
||||
String name = TypeToString(ptrType->mElementType) + "[";
|
||||
|
|
|
@ -450,6 +450,7 @@ public:
|
|||
virtual bool IsTypedPrimitive() { return false; }
|
||||
virtual bool IsComposite() { return IsStruct(); }
|
||||
virtual bool IsStruct() { return false; }
|
||||
virtual bool IsStructPtr() { return false; }
|
||||
virtual bool IsUnion() { return false; }
|
||||
virtual bool IsStructOrStructPtr() { return false; }
|
||||
virtual bool IsObject() { return false; }
|
||||
|
@ -494,6 +495,7 @@ public:
|
|||
virtual bool WantsGCMarking() { return false; }
|
||||
virtual BfTypeCode GetLoweredType() { return BfTypeCode_None; }
|
||||
virtual BfType* GetUnderlyingType() { return NULL; }
|
||||
virtual bool HasWrappedRepresentation() { return IsWrappableType(); }
|
||||
virtual bool IsTypeMemberIncluded(BfTypeDef* declaringTypeDef, BfTypeDef* activeTypeDef = NULL, BfModule* module = NULL) { return true; } // May be 'false' only for generic extensions with constraints
|
||||
virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfTypeDef* activeTypeDef) { return true; }
|
||||
virtual bool IsTypeMemberAccessible(BfTypeDef* declaringTypeDef, BfProject* curProject) { return true; }
|
||||
|
@ -1451,6 +1453,21 @@ public:
|
|||
Array<BfTypeInstance*> mStaticTypes;
|
||||
};
|
||||
|
||||
class BfTypeInfoEx
|
||||
{
|
||||
public:
|
||||
BfType* mUnderlyingType;
|
||||
int64 mMinValue;
|
||||
int64 mMaxValue;
|
||||
|
||||
BfTypeInfoEx()
|
||||
{
|
||||
mUnderlyingType = NULL;
|
||||
mMinValue = 0;
|
||||
mMaxValue = 0;
|
||||
}
|
||||
};
|
||||
|
||||
// Instance of struct or class
|
||||
class BfTypeInstance : public BfDependedType
|
||||
{
|
||||
|
@ -1465,6 +1482,7 @@ public:
|
|||
BfTypeInstance* mBaseType;
|
||||
BfCustomAttributes* mCustomAttributes;
|
||||
BfAttributeData* mAttributeData;
|
||||
BfTypeInfoEx* mTypeInfoEx;
|
||||
|
||||
Array<BfTypeInterfaceEntry> mInterfaces;
|
||||
Array<BfTypeInterfaceMethodEntry> mInterfaceMethodTable;
|
||||
|
@ -1528,6 +1546,7 @@ public:
|
|||
mBaseType = NULL;
|
||||
mCustomAttributes = NULL;
|
||||
mAttributeData = NULL;
|
||||
mTypeInfoEx = NULL;
|
||||
//mClassVData = NULL;
|
||||
mVirtualMethodTableSize = 0;
|
||||
mHotTypeData = NULL;
|
||||
|
@ -1566,6 +1585,7 @@ public:
|
|||
virtual BfTypeInstance* ToTypeInstance() override { return this; }
|
||||
virtual bool IsDependentOnUnderlyingType() override { return true; }
|
||||
virtual BfPrimitiveType* ToPrimitiveType() override { return GetUnderlyingType()->ToPrimitiveType(); }
|
||||
virtual bool HasWrappedRepresentation() { return IsTypedPrimitive(); }
|
||||
|
||||
int GetEndingInstanceAlignment() { if (mInstSize % mInstAlign == 0) return mInstAlign; return mInstSize % mInstAlign; }
|
||||
virtual bool HasTypeFailed() override { return mTypeFailed; }
|
||||
|
@ -1602,6 +1622,8 @@ public:
|
|||
virtual bool WantsGCMarking() override;
|
||||
virtual BfTypeCode GetLoweredType() override;
|
||||
|
||||
virtual BfTypeInstance* GetImplBaseType() { return mBaseType; }
|
||||
|
||||
virtual bool IsIRFuncUsed(BfIRFunction func);
|
||||
|
||||
void CalcHotVirtualData(/*Val128& vtHash, */Array<int>* ifaceMapping);
|
||||
|
@ -1626,9 +1648,25 @@ public:
|
|||
class BfBoxedType : public BfTypeInstance
|
||||
{
|
||||
public:
|
||||
BfTypeInstance* mElementType;
|
||||
enum BoxedFlags
|
||||
{
|
||||
BoxedFlags_None = 0,
|
||||
BoxedFlags_StructPtr = 1
|
||||
};
|
||||
|
||||
public:
|
||||
BfTypeInstance* mElementType;
|
||||
BfBoxedType* mBoxedBaseType;
|
||||
BoxedFlags mBoxedFlags;
|
||||
|
||||
public:
|
||||
BfBoxedType()
|
||||
{
|
||||
mElementType = NULL;
|
||||
mBoxedBaseType = NULL;
|
||||
mBoxedFlags = BoxedFlags_None;
|
||||
}
|
||||
|
||||
virtual bool IsBoxed() override { return true; }
|
||||
|
||||
virtual bool IsValueType() override { return false; }
|
||||
|
@ -1645,6 +1683,15 @@ public:
|
|||
virtual bool IsSpecializedType() override { return !mElementType->IsUnspecializedType(); }
|
||||
virtual bool IsUnspecializedType() override { return mElementType->IsUnspecializedType(); }
|
||||
virtual bool IsUnspecializedTypeVariation() override { return mElementType->IsUnspecializedTypeVariation(); }
|
||||
|
||||
virtual BfTypeInstance* GetImplBaseType() { return (mBoxedBaseType != NULL) ? mBoxedBaseType : mBaseType; }
|
||||
|
||||
bool IsBoxedStructPtr()
|
||||
{
|
||||
return (mBoxedFlags & BoxedFlags_StructPtr) != 0;
|
||||
}
|
||||
|
||||
BfType* GetModifiedElementType();
|
||||
};
|
||||
|
||||
class BfGenericExtensionEntry
|
||||
|
@ -1862,6 +1909,7 @@ public:
|
|||
virtual bool IsReified() { return mElementType->IsReified(); }
|
||||
virtual bool IsPointer() override { return true; }
|
||||
virtual bool IsIntPtrable() override { return true; }
|
||||
virtual bool IsStructPtr() override { return mElementType->IsStruct(); }
|
||||
virtual bool IsStructOrStructPtr() override { return mElementType->IsStruct(); }
|
||||
virtual bool IsValueTypeOrValueTypePtr() override { return mElementType->IsValueType(); }
|
||||
virtual bool IsDependentOnUnderlyingType() override { return true; }
|
||||
|
@ -2174,7 +2222,7 @@ public:
|
|||
}
|
||||
|
||||
mCount++;
|
||||
Entry* entry = new Entry();
|
||||
Entry* entry = (Entry*)BfResolvedTypeSetFuncs::Allocate(sizeof(Entry), alignof(Entry));
|
||||
entry->mValue = NULL;
|
||||
// if (mHashHeads[bucket] != NULL)
|
||||
// mHashHeads[bucket]->mPrev = entry;
|
||||
|
|
|
@ -582,25 +582,7 @@ BOOL WINAPI DllMain(
|
|||
DWORD dwReason,
|
||||
LPVOID lpreserved)
|
||||
{
|
||||
//::MessageBoxA(NULL, "A", "B", MB_OK);
|
||||
|
||||
// MemReporter memReporter;
|
||||
// memReporter.mShowInKB = false;
|
||||
// {
|
||||
// memReporter.BeginSection("A");
|
||||
// {
|
||||
// memReporter.BeginSection("B");
|
||||
// memReporter.Add(10);
|
||||
//
|
||||
// memReporter.Add("C", 1);
|
||||
// memReporter.Add("D", 2);
|
||||
//
|
||||
// memReporter.EndSection();
|
||||
// }
|
||||
// memReporter.EndSection();
|
||||
// }
|
||||
//
|
||||
// memReporter.Report();
|
||||
|
||||
if (dwReason == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
|
@ -641,57 +623,9 @@ static _CrtMemState gStartMemCheckpoint;
|
|||
#endif
|
||||
BF_EXPORT void BF_CALLTYPE Debugger_Create()
|
||||
{
|
||||
String outStr = BfDemangler::Demangle(
|
||||
"??0?$_String_alloc@U?$_String_base_types@DV?$allocator@D@std@@@std@@@std@@QEAA@AEBV?$allocator@D@1@@Z"
|
||||
//"?_Tidy@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAX_N_K@Z"
|
||||
//"?gamma@Class1@@2PAY04NA"
|
||||
//"?alpha@@3HA"
|
||||
//"?Fis_i@myclass@@SAHH@Z"
|
||||
//"??$?0AEBV?$allocator@D@std@@$$V@?$_Compressed_pair@U?$_Wrap_alloc@V?$allocator@D@std@@@std@@V?$_String_val@U?$_Simple_types@D@std@@@2@$00@std@@QEAA@U_One_then_variadic_args_t@1@AEBV?$allocator@D@1@@Z"
|
||||
|
||||
//"??0?$map@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@IU?$less@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@2@V?$allocator@U?$pair@$$CBV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@I@std@@@2@@std@@QEAA@XZ"
|
||||
//"??4?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAAAEAV01@PEBD@Z"
|
||||
//"??0?$allocator@_W@std@@QEAA@XZ"
|
||||
//"??0?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QEAA@XZ"
|
||||
, DbgLanguage_C);
|
||||
|
||||
/*{
|
||||
|
||||
struct TestStruct
|
||||
{
|
||||
TestStruct* mNext;
|
||||
int mInt;
|
||||
|
||||
TestStruct(int i)
|
||||
{
|
||||
mNext = NULL;
|
||||
mInt = i;
|
||||
}
|
||||
};
|
||||
|
||||
TestStruct tsArr[5] = { 1, 2, 3, 4, 5 };
|
||||
SLIList<TestStruct*> sliList;
|
||||
|
||||
sliList.PushBack(&tsArr[0]);
|
||||
//sliList.PushBack(&tsArr[1]);
|
||||
//sliList.PushBack(&tsArr[2]);
|
||||
|
||||
auto itr = sliList.begin();
|
||||
auto* val = *itr;
|
||||
//++itr;
|
||||
//val = *itr;
|
||||
//++itr;
|
||||
//val = *itr;
|
||||
sliList.erase(itr);
|
||||
bool isEnd = itr == sliList.end();
|
||||
}*/
|
||||
|
||||
String str = StrFormat("%d:%@:%l@", 123, (intptr)0x1234567890LL, 0xABCDEF7890LL);
|
||||
//String str = StrFormat("%l@", "Yo");
|
||||
|
||||
//TODO: Very slow, remove
|
||||
//_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_ALWAYS_DF);
|
||||
|
||||
//_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_CHECK_EVERY_16_DF);
|
||||
//TODO: _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF /*| _CRTDBG_CHECK_EVERY_16_DF*/);
|
||||
//_CrtSetAllocHook(BfAllocHook);
|
||||
|
||||
|
|
|
@ -9,10 +9,9 @@ namespace Tests
|
|||
int Get() mut;
|
||||
}
|
||||
|
||||
struct Struct : IFace
|
||||
struct StructA : IFace
|
||||
{
|
||||
public int mA = 100;
|
||||
public int mB = 200;
|
||||
|
||||
public int Get() mut
|
||||
{
|
||||
|
@ -21,20 +20,87 @@ namespace Tests
|
|||
}
|
||||
}
|
||||
|
||||
struct StructB : StructA, IHashable
|
||||
{
|
||||
public int mB = 200;
|
||||
|
||||
public int GetHashCode()
|
||||
{
|
||||
return mB;
|
||||
}
|
||||
}
|
||||
|
||||
struct StructC : StructB
|
||||
{
|
||||
public int mC = 300;
|
||||
}
|
||||
|
||||
public static int GetFromIFace<T>(mut T val) where T : IFace
|
||||
{
|
||||
return val.Get();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public static void TestBasics()
|
||||
{
|
||||
Struct val0 = .();
|
||||
Object obj0 = val0;
|
||||
StructA valA = .();
|
||||
Object obj0 = valA;
|
||||
IFace iface0 = (IFace)obj0;
|
||||
Test.Assert(GetFromIFace(mut valA) == 1100);
|
||||
Test.Assert(iface0.Get() == 1100);
|
||||
Test.Assert(val0.mA == 100); // This should copy values
|
||||
Test.Assert(GetFromIFace(iface0) == 2100);
|
||||
Test.Assert(valA.mA == 1100); // This should copy values
|
||||
|
||||
/*Struct val1 = .();
|
||||
Object obj1 = (Object)(ref val1);
|
||||
IFace iface1 = (IFace)obj1;
|
||||
StructB valB = .();
|
||||
IFace iface1 = valB;
|
||||
Test.Assert(GetFromIFace(mut valB) == 1100);
|
||||
Test.Assert(iface1.Get() == 1100);
|
||||
Test.Assert(val1.mA == 1100); // This should reference values*/
|
||||
Test.Assert(GetFromIFace(iface1) == 2100);
|
||||
Test.Assert(valB.mA == 1100); // This should copy values
|
||||
}
|
||||
|
||||
[Test]
|
||||
public static void TestPtr()
|
||||
{
|
||||
StructA* valA = scope .();
|
||||
Object obj0 = valA;
|
||||
IFace iface0 = (IFace)obj0;
|
||||
Test.Assert(GetFromIFace(mut valA) == 1100);
|
||||
Test.Assert(iface0.Get() == 2100);
|
||||
Test.Assert(GetFromIFace(iface0) == 3100);
|
||||
Test.Assert(valA.mA == 3100); // This should copy values
|
||||
|
||||
StructB* valB = scope .();
|
||||
IFace iface1 = valB;
|
||||
Test.Assert(GetFromIFace(mut valB) == 1100);
|
||||
Test.Assert(iface1.Get() == 2100);
|
||||
Test.Assert(GetFromIFace(iface1) == 3100);
|
||||
Test.Assert(valB.mA == 3100); // This should copy values
|
||||
}
|
||||
|
||||
public static int GetHash<T>(T val) where T : IHashable
|
||||
{
|
||||
return val.GetHashCode();
|
||||
}
|
||||
|
||||
[Test]
|
||||
public static void TestPtrHash()
|
||||
{
|
||||
StructA* valA = scope .();
|
||||
StructB* valB = scope .();
|
||||
StructC* valC = scope .();
|
||||
|
||||
IHashable ihA = valA;
|
||||
IHashable ihB = valB;
|
||||
IHashable ihC = valC;
|
||||
|
||||
Test.Assert(ihA.GetHashCode() == (int)valA);
|
||||
Test.Assert(ihB.GetHashCode() == (int)valB);
|
||||
Test.Assert(ihC.GetHashCode() == (int)valC);
|
||||
|
||||
Test.Assert(GetHash(ihA) == (int)valA);
|
||||
Test.Assert(GetHash(ihB) == (int)valB);
|
||||
Test.Assert(GetHash(ihC) == (int)valC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue