1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-10 12:32:20 +02:00

Added reflected TypeDeclaration support for comptime

This commit is contained in:
Brian Fiete 2025-01-14 10:16:46 -08:00
parent 89651c4a76
commit e30972d3af
10 changed files with 753 additions and 250 deletions

View file

@ -474,6 +474,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly)
mStringTypeDef = NULL;
mStringViewTypeDef = NULL;
mThreadStaticAttributeTypeDef = NULL;
mTypeTypeDeclDef = NULL;
mTypeTypeDef = NULL;
mUnboundAttributeTypeDef = NULL;
mValueTypeTypeDef = NULL;
@ -7326,6 +7327,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory)
mStringViewTypeDef = _GetRequiredType("System.StringView");
mTestAttributeTypeDef = _GetRequiredType("System.TestAttribute");
mThreadStaticAttributeTypeDef = _GetRequiredType("System.ThreadStaticAttribute");
mTypeTypeDeclDef = _GetRequiredType("System.TypeDeclaration");
mTypeTypeDef = _GetRequiredType("System.Type");
mUnboundAttributeTypeDef = _GetRequiredType("System.UnboundAttribute");
mValueTypeTypeDef = _GetRequiredType("System.ValueType");

View file

@ -376,6 +376,7 @@ public:
BfTypeDef* mEnumTypeDef;
BfTypeDef* mStringTypeDef;
BfTypeDef* mStringViewTypeDef;
BfTypeDef* mTypeTypeDeclDef;
BfTypeDef* mTypeTypeDef;
BfTypeDef* mValueTypeTypeDef;
BfTypeDef* mResultTypeDef;

View file

@ -12005,7 +12005,9 @@ bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifie
}
mModule->AddDependency(type, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
mModule->PopulateType(type);
// We want to try to avoid triggering OnTypeInit for basic info
mModule->PopulateType(type, BfPopulateType_Interfaces_Direct);
auto typeInstance = type->ToTypeInstance();
auto _BoolResult = [&](bool val)
@ -12072,214 +12074,220 @@ bool BfExprEvaluator::LookupTypeProp(BfTypeOfExpression* typeOfExpr, BfIdentifie
auto genericTypeInst = type->ToGenericTypeInstance();
_Int32Result((genericTypeInst != NULL) ? (int)genericTypeInst->mGenericTypeInfo->mTypeGenericArguments.size() : 0);
}
else if (memberName == "Size")
_Int32Result(type->mSize);
else if (memberName == "Align")
_Int32Result(type->mAlign);
else if (memberName == "Stride")
_Int32Result(type->GetStride());
else if (memberName == "InstanceSize")
_Int32Result((typeInstance != NULL) ? typeInstance->mInstSize : type->mSize);
else if (memberName == "InstanceAlign")
_Int32Result((typeInstance != NULL) ? typeInstance->mInstAlign : type->mSize);
else if (memberName == "InstanceStride")
_Int32Result((typeInstance != NULL) ? typeInstance->GetInstStride() : type->GetStride());
else if (memberName == "UnderlyingType")
else
{
bool handled = false;
// We need full data
mModule->PopulateType(type, BfPopulateType_Data);
auto typeType = mModule->ResolveTypeDef(mModule->mCompiler->mTypeTypeDef);
if (type->IsGenericParam())
if (memberName == "Size")
_Int32Result(type->mSize);
else if (memberName == "Align")
_Int32Result(type->mAlign);
else if (memberName == "Stride")
_Int32Result(type->GetStride());
else if (memberName == "InstanceSize")
_Int32Result((typeInstance != NULL) ? typeInstance->mInstSize : type->mSize);
else if (memberName == "InstanceAlign")
_Int32Result((typeInstance != NULL) ? typeInstance->mInstAlign : type->mSize);
else if (memberName == "InstanceStride")
_Int32Result((typeInstance != NULL) ? typeInstance->GetInstStride() : type->GetStride());
else if (memberName == "UnderlyingType")
{
auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)type);
if (genericParamInstance->IsEnum())
bool handled = false;
auto typeType = mModule->ResolveTypeDef(mModule->mCompiler->mTypeTypeDef);
if (type->IsGenericParam())
{
handled = true;
mResult = BfTypedValue(mModule->mBfIRBuilder->GetUndefConstValue(mModule->mBfIRBuilder->MapType(typeType)), typeType);
}
}
else if (type->IsEnum())
{
if (type->IsDataIncomplete())
mModule->PopulateType(type);
auto underlyingType = type->GetUnderlyingType();
if (underlyingType != NULL)
{
handled = true;
mModule->AddDependency(underlyingType, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
mResult = BfTypedValue(mModule->CreateTypeDataRef(underlyingType), typeType);
}
}
if (!handled)
mResult = BfTypedValue(mModule->CreateTypeDataRef(mModule->GetPrimitiveType(BfTypeCode_None)), typeType);
}
else if (memberName == "BitSize")
{
auto int32Type = mModule->GetPrimitiveType(BfTypeCode_Int32);
BfType* checkType = type;
if (checkType->IsTypedPrimitive())
checkType = checkType->GetUnderlyingType();
if (checkType->IsGenericParam())
{
mResult = mModule->GetDefaultTypedValue(int32Type, false, Beefy::BfDefaultValueKind_Undef);
return true;
}
if ((typeInstance != NULL) && (typeInstance->IsEnum()))
{
if (typeInstance->mTypeInfoEx != NULL)
{
int64 minValue = typeInstance->mTypeInfoEx->mMinValue;
if (minValue < 0)
minValue = ~minValue;
int64 maxValue = typeInstance->mTypeInfoEx->mMaxValue;
if (maxValue < 0)
maxValue = ~maxValue;
uint64 value = (uint64)minValue | (uint64)maxValue;
int bitCount = 1;
if (typeInstance->mTypeInfoEx->mMinValue < 0)
bitCount++;
while (value >>= 1)
bitCount++;
mModule->AddDependency(typeInstance, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, bitCount), int32Type);
return true;
}
}
int bitSize = checkType->mSize * 8;
if (checkType->GetTypeCode() == BfTypeCode_Boolean)
bitSize = 1;
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, bitSize), int32Type);
return true;
}
else if ((memberName == "MinValue") || (memberName == "MaxValue"))
{
bool isMin = memberName == "MinValue";
bool isBitSize = memberName == "BitSize";
BfType* checkType = type;
if (checkType->IsTypedPrimitive())
checkType = checkType->GetUnderlyingType();
if (checkType->IsGenericParam())
{
bool foundMatch = false;
auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)checkType);
if (((genericParamInstance->mGenericParamFlags & BfGenericParamFlag_Enum) != 0) ||
((genericParamInstance->mTypeConstraint != NULL) && (genericParamInstance->mTypeConstraint->IsInstanceOf(mModule->mCompiler->mEnumTypeDef))))
foundMatch = true;
else
{
for (auto constraint : genericParamInstance->mInterfaceConstraints)
auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)type);
if (genericParamInstance->IsEnum())
{
if (constraint->IsInstanceOf(mModule->mCompiler->mIIntegerTypeDef))
foundMatch = true;
handled = true;
mResult = BfTypedValue(mModule->mBfIRBuilder->GetUndefConstValue(mModule->mBfIRBuilder->MapType(typeType)), typeType);
}
}
else if (type->IsEnum())
{
if (type->IsDataIncomplete())
mModule->PopulateType(type);
auto underlyingType = type->GetUnderlyingType();
if (underlyingType != NULL)
{
handled = true;
mModule->AddDependency(underlyingType, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ExprTypeReference);
mResult = BfTypedValue(mModule->CreateTypeDataRef(underlyingType), typeType);
}
}
if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized) && (mModule->mCurMethodInstance->mMethodInfoEx != NULL))
{
for (int genericParamIdx = (int)mModule->mCurMethodInstance->mMethodInfoEx->mMethodGenericArguments.size();
genericParamIdx < mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
{
genericParamInstance = mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
if (genericParamInstance->mExternType == type)
{
if (((genericParamInstance->mGenericParamFlags & BfGenericParamFlag_Enum) != 0) ||
((genericParamInstance->mTypeConstraint != NULL) && (genericParamInstance->mTypeConstraint->IsInstanceOf(mModule->mCompiler->mEnumTypeDef))))
foundMatch = true;
}
}
}
if (!handled)
mResult = BfTypedValue(mModule->CreateTypeDataRef(mModule->GetPrimitiveType(BfTypeCode_None)), typeType);
}
else if (memberName == "BitSize")
{
auto int32Type = mModule->GetPrimitiveType(BfTypeCode_Int32);
if (foundMatch)
BfType* checkType = type;
if (checkType->IsTypedPrimitive())
checkType = checkType->GetUnderlyingType();
if (checkType->IsGenericParam())
{
mResult = mModule->GetDefaultTypedValue(type, false, Beefy::BfDefaultValueKind_Undef);
mResult = mModule->GetDefaultTypedValue(int32Type, false, Beefy::BfDefaultValueKind_Undef);
return true;
}
}
if (checkType->IsPrimitiveType())
{
auto primType = (BfPrimitiveType*)checkType;
if ((typeInstance != NULL) && (typeInstance->IsEnum()))
{
if (typeInstance->mTypeInfoEx != NULL)
{
int64 minValue = typeInstance->mTypeInfoEx->mMinValue;
if (minValue < 0)
minValue = ~minValue;
int64 maxValue = typeInstance->mTypeInfoEx->mMaxValue;
if (maxValue < 0)
maxValue = ~maxValue;
uint64 value = (uint64)minValue | (uint64)maxValue;
int bitCount = 1;
if (typeInstance->mTypeInfoEx->mMinValue < 0)
bitCount++;
while (value >>= 1)
bitCount++;
mModule->AddDependency(typeInstance, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)typeInstance->mTypeInfoEx->mMinValue : (uint64)typeInstance->mTypeInfoEx->mMaxValue), typeInstance);
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, bitCount), int32Type);
return true;
}
}
int bitSize = checkType->mSize * 8;
if (checkType->GetTypeCode() == BfTypeCode_Boolean)
bitSize = 1;
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(BfTypeCode_Int32, bitSize), int32Type);
return true;
}
else if ((memberName == "MinValue") || (memberName == "MaxValue"))
{
bool isMin = memberName == "MinValue";
bool isBitSize = memberName == "BitSize";
BfType* checkType = type;
if (checkType->IsTypedPrimitive())
checkType = checkType->GetUnderlyingType();
if (checkType->IsGenericParam())
{
bool foundMatch = false;
auto genericParamInstance = mModule->GetGenericParamInstance((BfGenericParamType*)checkType);
if (((genericParamInstance->mGenericParamFlags & BfGenericParamFlag_Enum) != 0) ||
((genericParamInstance->mTypeConstraint != NULL) && (genericParamInstance->mTypeConstraint->IsInstanceOf(mModule->mCompiler->mEnumTypeDef))))
foundMatch = true;
else
{
for (auto constraint : genericParamInstance->mInterfaceConstraints)
{
if (constraint->IsInstanceOf(mModule->mCompiler->mIIntegerTypeDef))
foundMatch = true;
}
}
if ((mModule->mCurMethodInstance != NULL) && (mModule->mCurMethodInstance->mIsUnspecialized) && (mModule->mCurMethodInstance->mMethodInfoEx != NULL))
{
for (int genericParamIdx = (int)mModule->mCurMethodInstance->mMethodInfoEx->mMethodGenericArguments.size();
genericParamIdx < mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams.size(); genericParamIdx++)
{
genericParamInstance = mModule->mCurMethodInstance->mMethodInfoEx->mGenericParams[genericParamIdx];
if (genericParamInstance->mExternType == type)
{
if (((genericParamInstance->mGenericParamFlags & BfGenericParamFlag_Enum) != 0) ||
((genericParamInstance->mTypeConstraint != NULL) && (genericParamInstance->mTypeConstraint->IsInstanceOf(mModule->mCompiler->mEnumTypeDef))))
foundMatch = true;
}
}
}
if (foundMatch)
{
mResult = mModule->GetDefaultTypedValue(type, false, Beefy::BfDefaultValueKind_Undef);
return true;
}
}
if (checkType->IsPrimitiveType())
{
auto primType = (BfPrimitiveType*)checkType;
if ((typeInstance != NULL) && (typeInstance->IsEnum()))
{
if (typeInstance->mTypeInfoEx != NULL)
{
mModule->AddDependency(typeInstance, mModule->mCurTypeInstance, BfDependencyMap::DependencyFlag_ReadFields);
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)typeInstance->mTypeInfoEx->mMinValue : (uint64)typeInstance->mTypeInfoEx->mMaxValue), typeInstance);
return true;
}
}
else
{
switch (primType->mTypeDef->mTypeCode)
{
case BfTypeCode_Int8:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? -0x80 : 0x7F), primType);
return true;
case BfTypeCode_Int16:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? -0x8000 : 0x7FFF), primType);
return true;
case BfTypeCode_Int32:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)-0x80000000LL : 0x7FFFFFFF), primType);
return true;
case BfTypeCode_Int64:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)-0x8000000000000000LL : (uint64)0x7FFFFFFFFFFFFFFFLL), primType);
return true;
case BfTypeCode_UInt8:
case BfTypeCode_Char8:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : 0xFF), primType);
return true;
case BfTypeCode_UInt16:
case BfTypeCode_Char16:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : 0xFFFF), primType);
return true;
case BfTypeCode_UInt32:
case BfTypeCode_Char32:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : (uint64)0xFFFFFFFFLL), primType);
return true;
case BfTypeCode_UInt64:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : (uint64)0xFFFFFFFFFFFFFFFFLL), primType);
return true;
case BfTypeCode_IntPtr:
if (mModule->mSystem->mPtrSize == 8)
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)-0x8000000000000000LL : (uint64)0x7FFFFFFFFFFFFFFFLL), primType);
else
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)-0x80000000LL : 0x7FFFFFFF), primType);
return true;
case BfTypeCode_UIntPtr:
if (mModule->mSystem->mPtrSize == 8)
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : (uint64)0xFFFFFFFFFFFFFFFFLL), primType);
else
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : (uint64)0xFFFFFFFFLL), primType);
return true;
default: break;
}
}
}
if (type->IsEnum())
{
mModule->Fail(StrFormat("'MinValue' cannot be used on enum with payload '%s'", mModule->TypeToString(type).c_str()), propName);
}
else
{
switch (primType->mTypeDef->mTypeCode)
{
case BfTypeCode_Int8:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? -0x80 : 0x7F), primType);
return true;
case BfTypeCode_Int16:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? -0x8000 : 0x7FFF), primType);
return true;
case BfTypeCode_Int32:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)-0x80000000LL : 0x7FFFFFFF), primType);
return true;
case BfTypeCode_Int64:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)-0x8000000000000000LL : (uint64)0x7FFFFFFFFFFFFFFFLL), primType);
return true;
case BfTypeCode_UInt8:
case BfTypeCode_Char8:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : 0xFF), primType);
return true;
case BfTypeCode_UInt16:
case BfTypeCode_Char16:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : 0xFFFF), primType);
return true;
case BfTypeCode_UInt32:
case BfTypeCode_Char32:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : (uint64)0xFFFFFFFFLL), primType);
return true;
case BfTypeCode_UInt64:
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : (uint64)0xFFFFFFFFFFFFFFFFLL), primType);
return true;
case BfTypeCode_IntPtr:
if (mModule->mSystem->mPtrSize == 8)
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)-0x8000000000000000LL : (uint64)0x7FFFFFFFFFFFFFFFLL), primType);
else
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? (uint64)-0x80000000LL : 0x7FFFFFFF), primType);
return true;
case BfTypeCode_UIntPtr:
if (mModule->mSystem->mPtrSize == 8)
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : (uint64)0xFFFFFFFFFFFFFFFFLL), primType);
else
mResult = BfTypedValue(mModule->mBfIRBuilder->CreateConst(primType->mTypeDef->mTypeCode, isMin ? 0 : (uint64)0xFFFFFFFFLL), primType);
return true;
default: break;
}
mModule->Fail(StrFormat("'%s' cannot be used on type '%s'", memberName.c_str(), mModule->TypeToString(type).c_str()), propName);
}
}
if (type->IsEnum())
{
mModule->Fail(StrFormat("'MinValue' cannot be used on enum with payload '%s'", mModule->TypeToString(type).c_str()), propName);
}
else
{
mModule->Fail(StrFormat("'%s' cannot be used on type '%s'", memberName.c_str(), mModule->TypeToString(type).c_str()), propName);
}
return false;
}
else
return false;
if ((type->IsGenericParam()) && (!mModule->mIsComptimeModule))
{

View file

@ -6004,29 +6004,13 @@ void BfModule::CreateSlotOfs(BfTypeInstance* typeInstance)
GetConstValue32(virtSlotIdx), slotVarName);
}
BfIRValue BfModule::CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, bool forceReflectFields, bool needsTypeData, bool needsTypeNames, bool needsVData)
BfIRValue BfModule::GetTypeTypeData(BfType* type, BfCreateTypeDataContext& ctx, bool needsTypeData, bool wantsTypeDecl, bool needsTypeNames, int& typeFlags, int& typeCode)
{
if ((IsHotCompile()) && (!type->mDirty))
return BfIRValue();
BfIRValue* irValuePtr = NULL;
if (mTypeDataRefs.TryGetValue(type, &irValuePtr))
{
return *irValuePtr;
}
BfTypeInstance* typeInstance = type->ToTypeInstance();
BfType* typeInstanceType = ResolveTypeDef(mCompiler->mReflectTypeInstanceTypeDef);
mBfIRBuilder->PopulateType(typeInstanceType, BfIRPopulateType_Full_ForceDefinition);
if (typeInstanceType == NULL)
{
AssertErrorState();
return BfIRValue();
}
BfIRValue typeTypeData;
int typeFlags = 0;
BfIRValue typeTypeData;
if (needsTypeData)
{
BfTypeInstance* typeInstanceTypeInstance = typeInstanceType->ToTypeInstance();
@ -6069,10 +6053,15 @@ BfIRValue BfModule::CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, b
else
typeDataSource = mContext->mBfTypeType;
if (wantsTypeDecl)
{
typeDataSource = ResolveTypeDef(mCompiler->mTypeTypeDeclDef)->ToTypeInstance();
}
if ((!mTypeDataRefs.ContainsKey(typeDataSource)) && (typeDataSource != type) && (!mIsComptimeModule))
{
CreateTypeData(typeDataSource, ctx, false, true, needsTypeNames, true);
}
}
typeTypeData = CreateClassVDataGlobal(typeDataSource);
@ -6084,40 +6073,6 @@ BfIRValue BfModule::CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, b
typeTypeData = mBfIRBuilder->CreateConstNull();
}
BfType* longType = GetPrimitiveType(BfTypeCode_Int64);
BfType* intType = GetPrimitiveType(BfTypeCode_Int32);
BfType* intPtrType = GetPrimitiveType(BfTypeCode_IntPtr);
BfType* shortType = GetPrimitiveType(BfTypeCode_Int16);
BfType* byteType = GetPrimitiveType(BfTypeCode_Int8);
BfType* typeIdType = intType;
auto voidPtrType = GetPrimitiveType(BfTypeCode_NullPtr);
auto voidPtrIRType = mBfIRBuilder->MapType(voidPtrType);
auto voidPtrPtrIRType = mBfIRBuilder->GetPointerTo(voidPtrIRType);
auto voidPtrNull = GetDefaultValue(voidPtrType);
SizedArray<BfIRValue, 4> typeValueParams;
GetConstClassValueParam(typeTypeData, typeValueParams);
FixConstValueParams(mContext->mBfObjectType, typeValueParams);
BfIRValue objectData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(mContext->mBfObjectType, BfIRPopulateType_Full), typeValueParams);
StringT<512> typeDataName;
if ((typeInstance != NULL) && (!typeInstance->IsTypeAlias()))
{
BfMangler::MangleStaticFieldName(typeDataName, mCompiler->GetMangleKind(), typeInstance, "sBfTypeData");
if (typeInstance->mTypeDef->IsGlobalsContainer())
typeDataName += "`G`" + typeInstance->mTypeDef->mProject->mName;
}
else
{
typeDataName += "sBfTypeData.";
BfMangler::Mangle(typeDataName, mCompiler->GetMangleKind(), type, mContext->mScratchModule);
}
int typeCode = BfTypeCode_None;
if (typeInstance != NULL)
{
BF_ASSERT((type->mDefineState >= BfTypeDefineState_DefinedAndMethodsSlotted) || mIsComptimeModule);
@ -6181,7 +6136,7 @@ BfIRValue BfModule::CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, b
typeFlags |= BfTypeFlags_Delegate;
if (type->IsFunction())
typeFlags |= BfTypeFlags_Function;
if ((type->mDefineState != BfTypeDefineState_CETypeInit) && (type->WantsGCMarking()))
if ((!wantsTypeDecl) && (type->mDefineState != BfTypeDefineState_CETypeInit) && (type->WantsGCMarking()))
typeFlags |= BfTypeFlags_WantsMarking;
if ((typeInstance != NULL) && (typeInstance->mTypeDef->mIsStatic))
@ -6189,6 +6144,115 @@ BfIRValue BfModule::CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, b
if ((typeInstance != NULL) && (typeInstance->mTypeDef->mIsAbstract))
typeFlags |= BfTypeFlags_Abstract;
return typeTypeData;
}
BfIRValue BfModule::CreateTypeDeclData(BfType* type)
{
auto typeDeclType = ResolveTypeDef(mCompiler->mTypeTypeDeclDef)->ToTypeInstance();
int typeCode = 0;
int typeFlags = 0;
BfCreateTypeDataContext createTypeDataCtx;
BfIRValue typeTypeData = GetTypeTypeData(type, createTypeDataCtx, true, true, true, typeFlags, typeCode);
SizedArray<BfIRValue, 4> typeValueParams;
GetConstClassValueParam(typeTypeData, typeValueParams);
BfType* longType = GetPrimitiveType(BfTypeCode_Int64);
BfType* intType = GetPrimitiveType(BfTypeCode_Int32);
BfType* intPtrType = GetPrimitiveType(BfTypeCode_IntPtr);
BfType* shortType = GetPrimitiveType(BfTypeCode_Int16);
BfType* byteType = GetPrimitiveType(BfTypeCode_Int8);
BfType* typeIdType = intType;
auto typeInst = type->ToTypeInstance();
auto outerType = GetOuterType(type);
BfType* baseType = NULL;
if (typeInst != NULL)
baseType = typeInst->mBaseType;
BfIRValue objectData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(mContext->mBfObjectType, BfIRPopulateType_Full), typeValueParams);
SizedArray<BfIRValue, 9> typeDataParams =
{
objectData,
GetConstValue(type->mTypeId, typeIdType), // mTypeId
GetConstValue((baseType != NULL) ? baseType->mTypeId : 0, typeIdType), // mBaseTypeId
GetConstValue((outerType != NULL) ? outerType->mTypeId : 0, typeIdType), // mOuterTypeId
GetConstValue(typeFlags, intType), // mTypeFlags
GetConstValue(typeCode, byteType), // mTypeCode
};
FixConstValueParams(typeDeclType, typeDataParams);
auto typeData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(typeDeclType, BfIRPopulateType_Full), typeDataParams);
String typeDataName = StrFormat("sBfTypeDeclData.%d", type->mTypeId);
BfIRValue typeDataVar = mBfIRBuilder->CreateGlobalVariable(mBfIRBuilder->MapTypeInst(typeDeclType), true,
BfIRLinkageType_External, typeData, typeDataName);
mBfIRBuilder->GlobalVar_SetAlignment(typeDataVar, mSystem->mPtrSize);
return typeDataVar;
}
BfIRValue BfModule::CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, bool forceReflectFields, bool needsTypeData, bool needsTypeNames, bool needsVData)
{
if ((IsHotCompile()) && (!type->mDirty))
return BfIRValue();
BfIRValue* irValuePtr = NULL;
if (mTypeDataRefs.TryGetValue(type, &irValuePtr))
{
return *irValuePtr;
}
BfTypeInstance* typeInstance = type->ToTypeInstance();
BfType* typeInstanceType = ResolveTypeDef(mCompiler->mReflectTypeInstanceTypeDef);
mBfIRBuilder->PopulateType(typeInstanceType, BfIRPopulateType_Full_ForceDefinition);
if (typeInstanceType == NULL)
{
AssertErrorState();
return BfIRValue();
}
int typeCode = BfTypeCode_None;
int typeFlags = 0;
BfIRValue typeTypeData = GetTypeTypeData(type, ctx, needsTypeData, false, needsTypeNames, typeFlags, typeCode);
BfType* longType = GetPrimitiveType(BfTypeCode_Int64);
BfType* intType = GetPrimitiveType(BfTypeCode_Int32);
BfType* intPtrType = GetPrimitiveType(BfTypeCode_IntPtr);
BfType* shortType = GetPrimitiveType(BfTypeCode_Int16);
BfType* byteType = GetPrimitiveType(BfTypeCode_Int8);
BfType* typeIdType = intType;
auto voidPtrType = GetPrimitiveType(BfTypeCode_NullPtr);
auto voidPtrIRType = mBfIRBuilder->MapType(voidPtrType);
auto voidPtrPtrIRType = mBfIRBuilder->GetPointerTo(voidPtrIRType);
auto voidPtrNull = GetDefaultValue(voidPtrType);
SizedArray<BfIRValue, 4> typeValueParams;
GetConstClassValueParam(typeTypeData, typeValueParams);
FixConstValueParams(mContext->mBfObjectType, typeValueParams);
BfIRValue objectData = mBfIRBuilder->CreateConstAgg_Value(mBfIRBuilder->MapTypeInst(mContext->mBfObjectType, BfIRPopulateType_Full), typeValueParams);
StringT<512> typeDataName;
if ((typeInstance != NULL) && (!typeInstance->IsTypeAlias()))
{
BfMangler::MangleStaticFieldName(typeDataName, mCompiler->GetMangleKind(), typeInstance, "sBfTypeData");
if (typeInstance->mTypeDef->IsGlobalsContainer())
typeDataName += "`G`" + typeInstance->mTypeDef->mProject->mName;
}
else
{
typeDataName += "sBfTypeData.";
BfMangler::Mangle(typeDataName, mCompiler->GetMangleKind(), type, mContext->mScratchModule);
}
int virtSlotIdx = -1;
if ((typeInstance != NULL) && (typeInstance->mSlotNum >= 0))
virtSlotIdx = typeInstance->mSlotNum + mCompiler->GetVDataPrefixDataCount() + mCompiler->GetDynCastVDataCount();

View file

@ -2093,6 +2093,8 @@ public:
void EncodeAttributeData(BfTypeInstance* typeInstance, BfType* argType, BfIRValue arg, SizedArrayImpl<uint8>& data, Dictionary<int, int>& usedStringIdMap);
BfIRValue CreateFieldData(BfFieldInstance* fieldInstance, int customAttrIdx);
void CreateSlotOfs(BfTypeInstance* typeInstance);
BfIRValue GetTypeTypeData(BfType* type, BfCreateTypeDataContext& ctx, bool needsTypeData, bool wantsTypeDecl, bool needsTypeNames, int& typeFlags, int& typeCode);
BfIRValue CreateTypeDeclData(BfType* type);
BfIRValue CreateTypeData(BfType* type, BfCreateTypeDataContext& ctx, bool forceReflectFields, bool needsTypeData, bool needsTypeNames, bool needsVData);
BfIRValue FixClassVData(BfIRValue value);

View file

@ -3878,6 +3878,53 @@ addr_ce CeContext::GetConstantData(BeConstant* constant)
return (addr_ce)(ptr - mMemory.mVals);
}
addr_ce CeContext::GetReflectTypeDecl(int typeId)
{
addr_ce* addrPtr = NULL;
if (!mReflectDeclMap.TryAdd(typeId, NULL, &addrPtr))
return *addrPtr;
auto ceModule = mCeMachine->mCeModule;
SetAndRestoreValue<bool> ignoreWrites(ceModule->mBfIRBuilder->mIgnoreWrites, false);
if (ceModule->mContext->mBfTypeType == NULL)
ceModule->mContext->ReflectInit();
if ((uintptr)typeId >= (uintptr)mCeMachine->mCeModule->mContext->mTypes.mSize)
return 0;
auto bfType = mCeMachine->mCeModule->mContext->mTypes[typeId];
if (bfType == NULL)
return 0;
if (bfType->mDefineState < BfTypeDefineState_HasInterfaces_Direct)
ceModule->PopulateType(bfType, BfPopulateType_Interfaces_Direct);
BfCreateTypeDataContext createTypeDataCtx;
auto irData = ceModule->CreateTypeDeclData(bfType);
BeValue* beValue = NULL;
if (auto constant = mCeMachine->mCeModule->mBfIRBuilder->GetConstant(irData))
{
if (constant->mConstType == BfConstType_BitCast)
{
auto bitcast = (BfConstantBitCast*)constant;
constant = mCeMachine->mCeModule->mBfIRBuilder->GetConstantById(bitcast->mTarget);
}
if (constant->mConstType == BfConstType_GlobalVar)
{
auto globalVar = (BfGlobalVar*)constant;
beValue = mCeMachine->mCeModule->mBfIRBuilder->mBeIRCodeGen->GetBeValue(globalVar->mStreamId);
}
}
if (auto constant = BeValueDynCast<BeConstant>(beValue))
*addrPtr = GetConstantData(constant);
// We need to 'get' again because we might have resized
return *addrPtr;
}
addr_ce CeContext::GetReflectType(int typeId)
{
addr_ce* addrPtr = NULL;
@ -3924,7 +3971,7 @@ addr_ce CeContext::GetReflectType(int typeId)
return *addrPtr;
}
addr_ce CeContext::GetReflectType(const String& typeName)
addr_ce CeContext::GetReflectType(const String& typeName, bool useDeclaration)
{
if (mCeMachine->mTempParser == NULL)
{
@ -3964,7 +4011,7 @@ addr_ce CeContext::GetReflectType(const String& typeName)
if (type == NULL)
return 0;
return GetReflectType(type->mTypeId);
return useDeclaration ? GetReflectTypeDecl(type->mTypeId) : GetReflectType(type->mTypeId);
}
int CeContext::GetTypeIdFromType(addr_ce typeAddr)
@ -6036,6 +6083,110 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
OutputDebugStrF("Debug Val: %lld %llX\n", intVal, intVal);
}
}
else if (checkFunction->mFunctionKind == CeFunctionKind_GetReflectTypeDeclById)
{
int32 typeId = *(int32*)((uint8*)stackPtr + ceModule->mSystem->mPtrSize);
auto reflectType = GetReflectTypeDecl(typeId);
_FixVariables();
CeSetAddrVal(stackPtr + 0, reflectType, ptrSize);
}
else if (checkFunction->mFunctionKind == CeFunctionKind_GetReflectTypeDeclByName)
{
addr_ce strViewPtr = *(addr_ce*)((uint8*)stackPtr + ptrSize);
String typeName;
if (!GetStringFromStringView(strViewPtr, typeName))
{
_Fail("Invalid StringView");
return false;
}
auto reflectType = GetReflectType(typeName, true);
_FixVariables();
CeSetAddrVal(stackPtr + 0, reflectType, ptrSize);
}
else if (checkFunction->mFunctionKind == CeFunctionKind_GetReflectNextTypeDecl)
{
int32 typeId = *(int32*)((uint8*)stackPtr + ceModule->mSystem->mPtrSize);
addr_ce reflectType = 0;
auto context = mCeMachine->mCeModule->mContext;
while (true)
{
typeId++;
if (typeId >= mCeMachine->mCeModule->mContext->mTypes.mSize)
break;
auto bfType = mCeMachine->mCeModule->mContext->mTypes[typeId];
if (bfType != NULL)
{
if (bfType->IsOnDemand())
continue;
if (bfType->IsBoxed())
continue;
if (bfType->IsArray())
continue;
if (bfType->IsNullable())
continue;
auto bfTypeInst = bfType->ToTypeInstance();
if (bfTypeInst == NULL)
continue;
if (bfTypeInst->mTypeDef->mTypeDeclaration == NULL)
continue;
if (bfTypeInst->IsGenericTypeInstance())
{
if (!bfTypeInst->IsUnspecializedType())
continue;
if (bfTypeInst->IsUnspecializedTypeVariation())
continue;
}
auto curProject = mCurModule->mProject;
auto declProject = bfTypeInst->mTypeDef->mProject;
if ((declProject != curProject) && (!curProject->HasDependency(declProject)))
continue;
reflectType = GetReflectTypeDecl(typeId);
if (reflectType != 0)
break;
}
}
_FixVariables();
CeSetAddrVal(stackPtr + 0, reflectType, ptrSize);
}
else if (checkFunction->mFunctionKind == CeFunctionKind_HasDeclaredMember)
{
int32 typeId = *(int32*)((uint8*)stackPtr + 1);
int32 memberKind = *(int32*)((uint8*)stackPtr + 1 + 4);
addr_ce strViewPtr = *(addr_ce*)((uint8*)stackPtr + 1 + 4 + 4);
bool hasMember;
String typeName;
if (!GetStringFromStringView(strViewPtr, typeName))
{
_Fail("Invalid StringView");
return false;
}
BfType* type = GetBfType(typeId);
if ((type != NULL) && (type->IsTypeInstance()))
{
auto typeInst = type->ToTypeInstance();
typeInst->mTypeDef->PopulateMemberSets();
if (memberKind == 0) // Field
hasMember = typeInst->mTypeDef->mFieldSet.ContainsWith((StringImpl&)typeName);
else if (memberKind == 1) // Method
hasMember = typeInst->mTypeDef->mMethodSet.ContainsWith((StringImpl&)typeName);
else if (memberKind == 2) // Property
hasMember = typeInst->mTypeDef->mPropertySet.ContainsWith((StringImpl&)typeName);
}
*(addr_ce*)(stackPtr + 0) = hasMember;
}
else if (checkFunction->mFunctionKind == CeFunctionKind_GetReflectType)
{
addr_ce objAddr = *(addr_ce*)((uint8*)stackPtr + ceModule->mSystem->mPtrSize);
@ -6062,7 +6213,7 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
_Fail("Invalid StringView");
return false;
}
auto reflectType = GetReflectType(typeName);
auto reflectType = GetReflectType(typeName, false);
_FixVariables();
CeSetAddrVal(stackPtr + 0, reflectType, ptrSize);
}
@ -6089,9 +6240,54 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCeMachine->mCeModule->mCurMethodInstance, mCallerMethodInstance);
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCeMachine->mCeModule->mCurTypeInstance, mCallerTypeInstance);
CeSetAddrVal(stackPtr + 0, GetString(mCeMachine->mCeModule->TypeToString(type)), ptrSize);
String typeName;
mCeMachine->mCeModule->DoTypeToString(typeName, type, BfTypeNameFlags_None);
CeSetAddrVal(stackPtr + 0, GetString(typeName), ptrSize);
_FixVariables();
}
else if (checkFunction->mFunctionKind == CeFunctionKind_TypeName_ToString)
{
int32 typeId = *(int32*)((uint8*)stackPtr + ptrSize);
BfType* type = GetBfType(typeId);
bool success = false;
if (type == NULL)
{
_Fail("Invalid type");
return false;
}
String str;
if (auto typeInst = type->ToTypeInstance())
str = typeInst->mTypeDef->mName->ToString();
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCeMachine->mCeModule->mCurMethodInstance, mCallerMethodInstance);
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCeMachine->mCeModule->mCurTypeInstance, mCallerTypeInstance);
CeSetAddrVal(stackPtr + 0, GetString(str), ptrSize);
_FixVariables();
}
else if (checkFunction->mFunctionKind == CeFunctionKind_Namespace_ToString)
{
int32 typeId = *(int32*)((uint8*)stackPtr + ptrSize);
BfType* type = GetBfType(typeId);
bool success = false;
if (type == NULL)
{
_Fail("Invalid type");
return false;
}
String str;
if (auto typeInst = type->ToTypeInstance())
typeInst->mTypeDef->mNamespace.ToString(str);
SetAndRestoreValue<BfMethodInstance*> prevMethodInstance(mCeMachine->mCeModule->mCurMethodInstance, mCallerMethodInstance);
SetAndRestoreValue<BfTypeInstance*> prevTypeInstance(mCeMachine->mCeModule->mCurTypeInstance, mCallerTypeInstance);
CeSetAddrVal(stackPtr + 0, GetString(str), ptrSize);
_FixVariables();
}
else if (checkFunction->mFunctionKind == CeFunctionKind_Type_GetCustomAttribute)
{
int32 typeId = *(int32*)((uint8*)stackPtr + 1);
@ -9650,7 +9846,23 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction)
}
else if (owner->IsInstanceOf(mCeModule->mCompiler->mTypeTypeDef))
{
if (methodDef->mName == "Comptime_GetTypeById")
if (methodDef->mName == "Comptime_GetTypeDeclarationById")
{
ceFunction->mFunctionKind = CeFunctionKind_GetReflectTypeDeclById;
}
if (methodDef->mName == "Comptime_GetTypeDeclarationByName")
{
ceFunction->mFunctionKind = CeFunctionKind_GetReflectTypeDeclByName;
}
else if (methodDef->mName == "Comptime_GetNextTypeDeclaration")
{
ceFunction->mFunctionKind = CeFunctionKind_GetReflectNextTypeDecl;
}
else if (methodDef->mName == "Comptime_Type_HasDeclaredMember")
{
ceFunction->mFunctionKind = CeFunctionKind_HasDeclaredMember;
}
else if (methodDef->mName == "Comptime_GetTypeById")
{
ceFunction->mFunctionKind = CeFunctionKind_GetReflectTypeById;
}
@ -9666,6 +9878,14 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction)
{
ceFunction->mFunctionKind = CeFunctionKind_Type_ToString;
}
else if (methodDef->mName == "Comptime_TypeName_ToString")
{
ceFunction->mFunctionKind = CeFunctionKind_TypeName_ToString;
}
else if (methodDef->mName == "Comptime_Namespace_ToString")
{
ceFunction->mFunctionKind = CeFunctionKind_Namespace_ToString;
}
else if (methodDef->mName == "Comptime_Type_GetCustomAttribute")
{
ceFunction->mFunctionKind = CeFunctionKind_Type_GetCustomAttribute;
@ -10259,7 +10479,8 @@ CeContext* CeMachine::AllocContext()
void CeMachine::ReleaseContext(CeContext* ceContext)
{
ceContext->mStringMap.Clear();
ceContext->mReflectMap.Clear();
ceContext->mReflectDeclMap.Clear();
ceContext->mReflectMap.Clear();
ceContext->mConstDataMap.Clear();
ceContext->mMemory.Clear();
if (ceContext->mMemory.mAllocSize > BF_CE_MAX_CARRYOVER_MEMORY)

View file

@ -428,12 +428,18 @@ enum CeFunctionKind
CeFunctionKind_DynCheckFailed,
CeFunctionKind_FatalError,
CeFunctionKind_DebugWrite,
CeFunctionKind_DebugWrite_Int,
CeFunctionKind_DebugWrite_Int,
CeFunctionKind_GetReflectTypeDeclById,
CeFunctionKind_GetReflectTypeDeclByName,
CeFunctionKind_GetReflectNextTypeDecl,
CeFunctionKind_HasDeclaredMember,
CeFunctionKind_GetReflectType,
CeFunctionKind_GetReflectTypeById,
CeFunctionKind_GetReflectTypeByName,
CeFunctionKind_GetReflectSpecializedType,
CeFunctionKind_Type_ToString,
CeFunctionKind_TypeName_ToString,
CeFunctionKind_Namespace_ToString,
CeFunctionKind_Type_GetCustomAttribute,
CeFunctionKind_Field_GetCustomAttribute,
CeFunctionKind_Method_GetCustomAttribute,
@ -1105,6 +1111,7 @@ public:
int mStackSize;
Dictionary<int, addr_ce> mStringMap;
Dictionary<int, addr_ce> mReflectMap;
Dictionary<int, addr_ce> mReflectDeclMap;
Dictionary<Val128, addr_ce> mConstDataMap;
HashSet<int> mStaticCtorExecSet;
Dictionary<String, CeStaticFieldInfo> mStaticFieldMap;
@ -1137,8 +1144,9 @@ public:
uint8* CeMalloc(int size);
bool CeFree(addr_ce addr);
addr_ce CeAllocArray(BfArrayType* arrayType, int count, addr_ce& elemsAddr);
addr_ce GetReflectTypeDecl(int typeId);
addr_ce GetReflectType(int typeId);
addr_ce GetReflectType(const String& typeName);
addr_ce GetReflectType(const String& typeName, bool useDeclaration);
int GetTypeIdFromType(addr_ce typeAddr);
addr_ce GetReflectSpecializedType(addr_ce unspecializedType, addr_ce typeArgsSpanAddr);
addr_ce GetString(int stringId);