mirror of
https://github.com/beefytech/Beef.git
synced 2025-06-10 04:22:20 +02:00
Predetermine enum discriminator during comptime
This commit is contained in:
parent
8807c1ea83
commit
326c33eaa1
4 changed files with 228 additions and 159 deletions
|
@ -1744,13 +1744,15 @@ public:
|
||||||
void FinishCEParseContext(BfAstNode* refNode, BfTypeInstance* typeInstance, BfCEParseContext* ceParseContext);
|
void FinishCEParseContext(BfAstNode* refNode, BfTypeInstance* typeInstance, BfCEParseContext* ceParseContext);
|
||||||
BfCEParseContext CEEmitParse(BfTypeInstance* typeInstance, const StringImpl& src);
|
BfCEParseContext CEEmitParse(BfTypeInstance* typeInstance, const StringImpl& src);
|
||||||
void UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, const StringImpl& ctxString, BfAstNode* refNode);
|
void UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, const StringImpl& ctxString, BfAstNode* refNode);
|
||||||
void HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCustomAttributes* customAttributes, HashSet<BfTypeInstance*> foundAttributes);
|
void HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCustomAttributes* customAttributes, HashSet<BfTypeInstance*> foundAttributes, bool underlyingTypeDeferred);
|
||||||
void CEMixin(BfAstNode* refNode, const StringImpl& src);
|
void CEMixin(BfAstNode* refNode, const StringImpl& src);
|
||||||
void ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind);
|
void ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInst, BfCEOnCompileKind onCompileKind, bool underlyingTypeDeferred);
|
||||||
void DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers);
|
void DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers, bool underlyingTypeDeferred);
|
||||||
void DoCEEmit(BfMethodInstance* methodInstance);
|
void DoCEEmit(BfMethodInstance* methodInstance);
|
||||||
void DoPopulateType_TypeAlias(BfTypeInstance* typeAlias);
|
void DoPopulateType_TypeAlias(BfTypeInstance* typeAlias);
|
||||||
void DoPopulateType_SetGenericDependencies(BfTypeInstance* genericTypeInstance);
|
void DoPopulateType_SetGenericDependencies(BfTypeInstance* genericTypeInstance);
|
||||||
|
void DoPopulateType_FinishEnum(BfTypeInstance* typeInstance, bool underlyingTypeDeferred, HashContext* dataMemberHashCtx, BfType* unionInnerType);
|
||||||
|
void DoPopulateType_CeCheckEnum(BfTypeInstance* typeInstance, bool underlyingTypeDeferred);
|
||||||
void DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data);
|
void DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType = BfPopulateType_Data);
|
||||||
static BfModule* GetModuleFor(BfType* type);
|
static BfModule* GetModuleFor(BfType* type);
|
||||||
void DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance);
|
void DoTypeInstanceMethodProcessing(BfTypeInstance* typeInstance);
|
||||||
|
|
|
@ -2136,7 +2136,7 @@ void BfModule::UpdateCEEmit(CeEmitContext* ceEmitContext, BfTypeInstance* typeIn
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCustomAttributes* customAttributes, HashSet<BfTypeInstance*> foundAttributes)
|
void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCustomAttributes* customAttributes, HashSet<BfTypeInstance*> foundAttributes, bool underlyingTypeDeferred)
|
||||||
{
|
{
|
||||||
BfTypeInstance* iComptimeTypeApply = NULL;
|
BfTypeInstance* iComptimeTypeApply = NULL;
|
||||||
for (auto& customAttribute : customAttributes->mAttributes)
|
for (auto& customAttribute : customAttributes->mAttributes)
|
||||||
|
@ -2170,6 +2170,7 @@ void BfModule::HandleCEAttributes(CeEmitContext* ceEmitContext, BfTypeInstance*
|
||||||
args.Add(attrVal);
|
args.Add(attrVal);
|
||||||
args.Add(mBfIRBuilder->CreateTypeOf(typeInstance));
|
args.Add(mBfIRBuilder->CreateTypeOf(typeInstance));
|
||||||
|
|
||||||
|
DoPopulateType_CeCheckEnum(typeInstance, underlyingTypeDeferred);
|
||||||
auto result = ceContext->Call(customAttribute.mRef, this, methodInstance, args, CeEvalFlags_None, NULL);
|
auto result = ceContext->Call(customAttribute.mRef, this, methodInstance, args, CeEvalFlags_None, NULL);
|
||||||
|
|
||||||
if (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotted)
|
if (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotted)
|
||||||
|
@ -2300,18 +2301,18 @@ void BfModule::CEMixin(BfAstNode* refNode, const StringImpl& code)
|
||||||
FinishCEParseContext(refNode, mCurTypeInstance, &ceParseContext);
|
FinishCEParseContext(refNode, mCurTypeInstance, &ceParseContext);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCEOnCompileKind onCompileKind)
|
void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance* typeInstance, BfCEOnCompileKind onCompileKind, bool underlyingTypeDeferred)
|
||||||
{
|
{
|
||||||
HashSet<BfTypeInstance*> foundAttributes;
|
HashSet<BfTypeInstance*> foundAttributes;
|
||||||
if (ceEmitContext != NULL)
|
if (ceEmitContext != NULL)
|
||||||
{
|
{
|
||||||
if (typeInstance->mCustomAttributes != NULL)
|
if (typeInstance->mCustomAttributes != NULL)
|
||||||
HandleCEAttributes(ceEmitContext, typeInstance, typeInstance->mCustomAttributes, foundAttributes);
|
HandleCEAttributes(ceEmitContext, typeInstance, typeInstance->mCustomAttributes, foundAttributes, underlyingTypeDeferred);
|
||||||
|
|
||||||
for (auto& fieldInstance : typeInstance->mFieldInstances)
|
for (auto& fieldInstance : typeInstance->mFieldInstances)
|
||||||
{
|
{
|
||||||
if (fieldInstance.mCustomAttributes != NULL)
|
if (fieldInstance.mCustomAttributes != NULL)
|
||||||
HandleCEAttributes(ceEmitContext, typeInstance, fieldInstance.mCustomAttributes, foundAttributes);
|
HandleCEAttributes(ceEmitContext, typeInstance, fieldInstance.mCustomAttributes, foundAttributes, underlyingTypeDeferred);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2353,7 +2354,7 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance*
|
||||||
if (onCompileAttribute == NULL)
|
if (onCompileAttribute == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
HandleCEAttributes(ceEmitContext, typeInstance, customAttributes, foundAttributes);
|
HandleCEAttributes(ceEmitContext, typeInstance, customAttributes, foundAttributes, underlyingTypeDeferred);
|
||||||
|
|
||||||
if (onCompileAttribute->mCtorArgs.size() < 1)
|
if (onCompileAttribute->mCtorArgs.size() < 1)
|
||||||
continue;
|
continue;
|
||||||
|
@ -2381,6 +2382,7 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance*
|
||||||
mCompiler->mCEMachine->mCurEmitContext = ceEmitContext;
|
mCompiler->mCEMachine->mCurEmitContext = ceEmitContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DoPopulateType_CeCheckEnum(typeInstance, underlyingTypeDeferred);
|
||||||
auto methodInstance = GetRawMethodInstanceAtIdx(typeInstance, methodDef->mIdx);
|
auto methodInstance = GetRawMethodInstanceAtIdx(typeInstance, methodDef->mIdx);
|
||||||
auto result = mCompiler->mCEMachine->Call(methodDef->GetRefNode(), this, methodInstance, {}, (CeEvalFlags)(CeEvalFlags_PersistantError | CeEvalFlags_DeferIfNotOnlyError), NULL);
|
auto result = mCompiler->mCEMachine->Call(methodDef->GetRefNode(), this, methodInstance, {}, (CeEvalFlags)(CeEvalFlags_PersistantError | CeEvalFlags_DeferIfNotOnlyError), NULL);
|
||||||
|
|
||||||
|
@ -2449,11 +2451,11 @@ void BfModule::ExecuteCEOnCompile(CeEmitContext* ceEmitContext, BfTypeInstance*
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
void BfModule::DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers)
|
void BfModule::DoCEEmit(BfTypeInstance* typeInstance, bool& hadNewMembers, bool underlyingTypeDeferred)
|
||||||
{
|
{
|
||||||
CeEmitContext ceEmitContext;
|
CeEmitContext ceEmitContext;
|
||||||
ceEmitContext.mType = typeInstance;
|
ceEmitContext.mType = typeInstance;
|
||||||
ExecuteCEOnCompile(&ceEmitContext, typeInstance, BfCEOnCompileKind_TypeInit);
|
ExecuteCEOnCompile(&ceEmitContext, typeInstance, BfCEOnCompileKind_TypeInit, underlyingTypeDeferred);
|
||||||
hadNewMembers = (typeInstance->mTypeDef->mEmitParent != NULL);
|
hadNewMembers = (typeInstance->mTypeDef->mEmitParent != NULL);
|
||||||
|
|
||||||
if (ceEmitContext.mFailed)
|
if (ceEmitContext.mFailed)
|
||||||
|
@ -2683,6 +2685,176 @@ void BfModule::DoPopulateType_TypeAlias(BfTypeInstance* typeAlias)
|
||||||
DoPopulateType_SetGenericDependencies(typeAlias);
|
DoPopulateType_SetGenericDependencies(typeAlias);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BfModule::DoPopulateType_FinishEnum(BfTypeInstance* typeInstance, bool underlyingTypeDeferred, HashContext* dataMemberHashCtx, BfType* unionInnerType)
|
||||||
|
{
|
||||||
|
if (typeInstance->IsEnum())
|
||||||
|
{
|
||||||
|
int64 min = 0;
|
||||||
|
int64 max = 0;
|
||||||
|
|
||||||
|
bool isFirst = true;
|
||||||
|
|
||||||
|
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()))
|
||||||
|
{
|
||||||
|
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))
|
||||||
|
typeCode = BfTypeCode_Int8;
|
||||||
|
else if ((min >= 0) && (max <= 0xFF))
|
||||||
|
typeCode = BfTypeCode_UInt8;
|
||||||
|
else if ((min >= -0x8000) && (max <= 0x7FFF))
|
||||||
|
typeCode = BfTypeCode_Int16;
|
||||||
|
else if ((min >= 0) && (max <= 0xFFFF))
|
||||||
|
typeCode = BfTypeCode_UInt16;
|
||||||
|
else if ((min >= -0x80000000LL) && (max <= 0x7FFFFFFF))
|
||||||
|
typeCode = BfTypeCode_Int32;
|
||||||
|
else if ((min >= 0) && (max <= 0xFFFFFFFFLL))
|
||||||
|
typeCode = BfTypeCode_UInt32;
|
||||||
|
else
|
||||||
|
typeCode = BfTypeCode_Int64;
|
||||||
|
|
||||||
|
if (typeCode != BfTypeCode_Int64)
|
||||||
|
{
|
||||||
|
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
||||||
|
{
|
||||||
|
auto fieldInstance = &fieldInstanceRef;
|
||||||
|
if (fieldInstance->mConstIdx == -1)
|
||||||
|
continue;
|
||||||
|
if (!fieldInstance->GetFieldDef()->IsEnumCaseEntry())
|
||||||
|
continue;
|
||||||
|
auto constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx);
|
||||||
|
BfIRValue newConstant = typeInstance->mConstHolder->CreateConst(typeCode, constant->mUInt64);
|
||||||
|
fieldInstance->mConstIdx = newConstant.mId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BfType* underlyingType = GetPrimitiveType(typeCode);
|
||||||
|
auto fieldInstance = &typeInstance->mFieldInstances.back();
|
||||||
|
fieldInstance->mResolvedType = underlyingType;
|
||||||
|
fieldInstance->mDataSize = underlyingType->mSize;
|
||||||
|
|
||||||
|
typeInstance->mTypeInfoEx->mUnderlyingType = underlyingType;
|
||||||
|
|
||||||
|
typeInstance->mSize = underlyingType->mSize;
|
||||||
|
typeInstance->mAlign = underlyingType->mAlign;
|
||||||
|
typeInstance->mInstSize = underlyingType->mSize;
|
||||||
|
typeInstance->mInstAlign = underlyingType->mAlign;
|
||||||
|
|
||||||
|
typeInstance->mRebuildFlags = (BfTypeRebuildFlags)(typeInstance->mRebuildFlags & ~BfTypeRebuildFlag_UnderlyingTypeDeferred);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
BF_ASSERT(!underlyingTypeDeferred);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((typeInstance->IsPayloadEnum()) && (!typeInstance->IsBoxed()))
|
||||||
|
{
|
||||||
|
typeInstance->mAlign = unionInnerType->mAlign;
|
||||||
|
|
||||||
|
int lastTagId = -1;
|
||||||
|
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
||||||
|
{
|
||||||
|
auto fieldInstance = &fieldInstanceRef;
|
||||||
|
auto fieldDef = fieldInstance->GetFieldDef();
|
||||||
|
if ((fieldDef != NULL) && (fieldInstance->mDataIdx < 0))
|
||||||
|
{
|
||||||
|
BF_ASSERT(fieldInstance->mResolvedType->mAlign >= 1);
|
||||||
|
typeInstance->mAlign = BF_MAX(typeInstance->mAlign, fieldInstance->mResolvedType->mAlign);
|
||||||
|
lastTagId = -fieldInstance->mDataIdx - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto fieldInstance = &typeInstance->mFieldInstances.back();
|
||||||
|
//BF_ASSERT(fieldInstance->mResolvedType == NULL);
|
||||||
|
BfPrimitiveType* discriminatorType;
|
||||||
|
if (lastTagId > 0x7FFFFFFF) // HOW?
|
||||||
|
discriminatorType = GetPrimitiveType(BfTypeCode_Int64);
|
||||||
|
else if (lastTagId > 0x7FFF)
|
||||||
|
discriminatorType = GetPrimitiveType(BfTypeCode_Int32);
|
||||||
|
else if (lastTagId > 0x7F)
|
||||||
|
discriminatorType = GetPrimitiveType(BfTypeCode_Int16);
|
||||||
|
else
|
||||||
|
discriminatorType = GetPrimitiveType(BfTypeCode_Int8);
|
||||||
|
fieldInstance->mResolvedType = discriminatorType;
|
||||||
|
|
||||||
|
fieldInstance->mDataOffset = unionInnerType->mSize;
|
||||||
|
fieldInstance->mDataIdx = 2; // 0 = base, 1 = payload, 2 = discriminator
|
||||||
|
if (!typeInstance->mIsPacked)
|
||||||
|
{
|
||||||
|
if ((fieldInstance->mDataOffset % discriminatorType->mAlign) != 0)
|
||||||
|
{
|
||||||
|
fieldInstance->mDataOffset = BF_ALIGN(fieldInstance->mDataOffset, discriminatorType->mAlign);
|
||||||
|
fieldInstance->mDataIdx++; // Add room for explicit padding
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typeInstance->mAlign = BF_MAX(typeInstance->mAlign, discriminatorType->mAlign);
|
||||||
|
typeInstance->mSize = fieldInstance->mDataOffset + discriminatorType->mSize;
|
||||||
|
|
||||||
|
typeInstance->mInstSize = typeInstance->mSize;
|
||||||
|
typeInstance->mInstAlign = typeInstance->mAlign;
|
||||||
|
|
||||||
|
if (dataMemberHashCtx != NULL)
|
||||||
|
{
|
||||||
|
dataMemberHashCtx->Mixin(unionInnerType->mTypeId);
|
||||||
|
dataMemberHashCtx->Mixin(discriminatorType->mTypeId);
|
||||||
|
}
|
||||||
|
|
||||||
|
typeInstance->mMergedFieldDataCount = 1; // Track it as a single entry
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BfModule::DoPopulateType_CeCheckEnum(BfTypeInstance* typeInstance, bool underlyingTypeDeferred)
|
||||||
|
{
|
||||||
|
if (!typeInstance->IsEnum())
|
||||||
|
return;
|
||||||
|
if ((!underlyingTypeDeferred) && (!typeInstance->IsPayloadEnum()))
|
||||||
|
return;
|
||||||
|
if ((typeInstance->mCeTypeInfo != NULL) && (typeInstance->mCeTypeInfo->mNext != NULL))
|
||||||
|
return;
|
||||||
|
|
||||||
|
BfType* unionInnerType = NULL;
|
||||||
|
if (typeInstance->mIsUnion)
|
||||||
|
{
|
||||||
|
SetAndRestoreValue<BfTypeState::ResolveKind> prevResolveKind(mContext->mCurTypeState->mResolveKind, BfTypeState::ResolveKind_UnionInnerType);
|
||||||
|
unionInnerType = typeInstance->GetUnionInnerType();
|
||||||
|
}
|
||||||
|
DoPopulateType_FinishEnum(typeInstance, underlyingTypeDeferred, NULL, unionInnerType);
|
||||||
|
}
|
||||||
|
|
||||||
void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType)
|
void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateType)
|
||||||
{
|
{
|
||||||
if (populateType == BfPopulateType_Identity)
|
if (populateType == BfPopulateType_Identity)
|
||||||
|
@ -4055,7 +4227,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
|
|
||||||
typeInstance->mDefineState = BfTypeDefineState_CETypeInit;
|
typeInstance->mDefineState = BfTypeDefineState_CETypeInit;
|
||||||
bool hadNewMembers = false;
|
bool hadNewMembers = false;
|
||||||
DoCEEmit(typeInstance, hadNewMembers);
|
DoCEEmit(typeInstance, hadNewMembers, underlyingTypeDeferred);
|
||||||
|
|
||||||
if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit)
|
if (typeInstance->mDefineState < BfTypeDefineState_CEPostTypeInit)
|
||||||
typeInstance->mDefineState = BfTypeDefineState_CEPostTypeInit;
|
typeInstance->mDefineState = BfTypeDefineState_CEPostTypeInit;
|
||||||
|
@ -4659,7 +4831,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
typeInstance->mDefineState = BfTypeDefineState_Defined;
|
typeInstance->mDefineState = BfTypeDefineState_Defined;
|
||||||
if (!typeInstance->IsBoxed())
|
if (!typeInstance->IsBoxed())
|
||||||
{
|
{
|
||||||
ExecuteCEOnCompile(NULL, typeInstance, BfCEOnCompileKind_TypeDone);
|
ExecuteCEOnCompile(NULL, typeInstance, BfCEOnCompileKind_TypeDone, underlyingTypeDeferred);
|
||||||
if (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotted)
|
if (typeInstance->mDefineState == BfTypeDefineState_DefinedAndMethodsSlotted)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -4830,151 +5002,7 @@ void BfModule::DoPopulateType(BfType* resolvedTypeRef, BfPopulateType populateTy
|
||||||
BfLogSysM("Setting underlying type %p %d\n", typeInstance, underlyingTypeDeferred);
|
BfLogSysM("Setting underlying type %p %d\n", typeInstance, underlyingTypeDeferred);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeInstance->IsEnum())
|
DoPopulateType_FinishEnum(typeInstance, underlyingTypeDeferred, &dataMemberHashCtx, unionInnerType);
|
||||||
{
|
|
||||||
int64 min = 0;
|
|
||||||
int64 max = 0;
|
|
||||||
|
|
||||||
bool isFirst = true;
|
|
||||||
|
|
||||||
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()))
|
|
||||||
{
|
|
||||||
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))
|
|
||||||
typeCode = BfTypeCode_Int8;
|
|
||||||
else if ((min >= 0) && (max <= 0xFF))
|
|
||||||
typeCode = BfTypeCode_UInt8;
|
|
||||||
else if ((min >= -0x8000) && (max <= 0x7FFF))
|
|
||||||
typeCode = BfTypeCode_Int16;
|
|
||||||
else if ((min >= 0) && (max <= 0xFFFF))
|
|
||||||
typeCode = BfTypeCode_UInt16;
|
|
||||||
else if ((min >= -0x80000000LL) && (max <= 0x7FFFFFFF))
|
|
||||||
typeCode = BfTypeCode_Int32;
|
|
||||||
else if ((min >= 0) && (max <= 0xFFFFFFFFLL))
|
|
||||||
typeCode = BfTypeCode_UInt32;
|
|
||||||
else
|
|
||||||
typeCode = BfTypeCode_Int64;
|
|
||||||
|
|
||||||
if (typeCode != BfTypeCode_Int64)
|
|
||||||
{
|
|
||||||
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
|
||||||
{
|
|
||||||
auto fieldInstance = &fieldInstanceRef;
|
|
||||||
if (fieldInstance->mConstIdx == -1)
|
|
||||||
continue;
|
|
||||||
if (!fieldInstance->GetFieldDef()->IsEnumCaseEntry())
|
|
||||||
continue;
|
|
||||||
auto constant = typeInstance->mConstHolder->GetConstantById(fieldInstance->mConstIdx);
|
|
||||||
BfIRValue newConstant = typeInstance->mConstHolder->CreateConst(typeCode, constant->mUInt64);
|
|
||||||
fieldInstance->mConstIdx = newConstant.mId;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
underlyingType = GetPrimitiveType(typeCode);
|
|
||||||
auto fieldInstance = &typeInstance->mFieldInstances.back();
|
|
||||||
fieldInstance->mResolvedType = underlyingType;
|
|
||||||
fieldInstance->mDataSize = underlyingType->mSize;
|
|
||||||
|
|
||||||
typeInstance->mTypeInfoEx->mUnderlyingType = underlyingType;
|
|
||||||
|
|
||||||
typeInstance->mSize = underlyingType->mSize;
|
|
||||||
typeInstance->mAlign = underlyingType->mAlign;
|
|
||||||
typeInstance->mInstSize = underlyingType->mSize;
|
|
||||||
typeInstance->mInstAlign = underlyingType->mAlign;
|
|
||||||
|
|
||||||
typeInstance->mRebuildFlags = (BfTypeRebuildFlags)(typeInstance->mRebuildFlags & ~BfTypeRebuildFlag_UnderlyingTypeDeferred);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
BF_ASSERT(!underlyingTypeDeferred);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((typeInstance->IsPayloadEnum()) && (!typeInstance->IsBoxed()))
|
|
||||||
{
|
|
||||||
typeInstance->mAlign = unionInnerType->mAlign;
|
|
||||||
|
|
||||||
int lastTagId = -1;
|
|
||||||
for (auto& fieldInstanceRef : typeInstance->mFieldInstances)
|
|
||||||
{
|
|
||||||
auto fieldInstance = &fieldInstanceRef;
|
|
||||||
auto fieldDef = fieldInstance->GetFieldDef();
|
|
||||||
if ((fieldDef != NULL) && (fieldInstance->mDataIdx < 0))
|
|
||||||
{
|
|
||||||
BF_ASSERT(fieldInstance->mResolvedType->mAlign >= 1);
|
|
||||||
typeInstance->mAlign = BF_MAX(typeInstance->mAlign, fieldInstance->mResolvedType->mAlign);
|
|
||||||
lastTagId = -fieldInstance->mDataIdx - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto fieldInstance = &typeInstance->mFieldInstances.back();
|
|
||||||
BF_ASSERT(fieldInstance->mResolvedType == NULL);
|
|
||||||
BfPrimitiveType* discriminatorType;
|
|
||||||
if (lastTagId > 0x7FFFFFFF) // HOW?
|
|
||||||
discriminatorType = GetPrimitiveType(BfTypeCode_Int64);
|
|
||||||
else if (lastTagId > 0x7FFF)
|
|
||||||
discriminatorType = GetPrimitiveType(BfTypeCode_Int32);
|
|
||||||
else if (lastTagId > 0x7F)
|
|
||||||
discriminatorType = GetPrimitiveType(BfTypeCode_Int16);
|
|
||||||
else
|
|
||||||
discriminatorType = GetPrimitiveType(BfTypeCode_Int8);
|
|
||||||
fieldInstance->mResolvedType = discriminatorType;
|
|
||||||
|
|
||||||
fieldInstance->mDataOffset = unionInnerType->mSize;
|
|
||||||
fieldInstance->mDataIdx = 2; // 0 = base, 1 = payload, 2 = discriminator
|
|
||||||
if (!isPacked)
|
|
||||||
{
|
|
||||||
if ((fieldInstance->mDataOffset % discriminatorType->mAlign) != 0)
|
|
||||||
{
|
|
||||||
fieldInstance->mDataOffset = BF_ALIGN(fieldInstance->mDataOffset, discriminatorType->mAlign);
|
|
||||||
fieldInstance->mDataIdx++; // Add room for explicit padding
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
typeInstance->mAlign = BF_MAX(typeInstance->mAlign, discriminatorType->mAlign);
|
|
||||||
typeInstance->mSize = fieldInstance->mDataOffset + discriminatorType->mSize;
|
|
||||||
|
|
||||||
typeInstance->mInstSize = typeInstance->mSize;
|
|
||||||
typeInstance->mInstAlign = typeInstance->mAlign;
|
|
||||||
|
|
||||||
dataMemberHashCtx.Mixin(unionInnerType->mTypeId);
|
|
||||||
dataMemberHashCtx.Mixin(discriminatorType->mTypeId);
|
|
||||||
|
|
||||||
typeInstance->mMergedFieldDataCount = 1; // Track it as a single entry
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!typeInstance->IsBoxed())
|
if (!typeInstance->IsBoxed())
|
||||||
{
|
{
|
||||||
|
|
|
@ -6081,6 +6081,13 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8*
|
||||||
{
|
{
|
||||||
if (iface.mInterfaceType == ifaceType)
|
if (iface.mInterfaceType == ifaceType)
|
||||||
{
|
{
|
||||||
|
if (valueType->mInterfaceMethodTable.IsEmpty())
|
||||||
|
ceModule->PopulateType(valueType, BfPopulateType_Full_Force);
|
||||||
|
if (valueType->mInterfaceMethodTable.IsEmpty())
|
||||||
|
{
|
||||||
|
_Fail("Empty interface table");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
methodInstance = valueType->mInterfaceMethodTable[iface.mStartInterfaceTableIdx + methodIdx].mMethodRef;
|
methodInstance = valueType->mInterfaceMethodTable[iface.mStartInterfaceTableIdx + methodIdx].mMethodRef;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,6 +230,38 @@ namespace Tests
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[CheckEnum]
|
||||||
|
enum EnumA
|
||||||
|
{
|
||||||
|
case A(int64 aa);
|
||||||
|
case B(float bb);
|
||||||
|
}
|
||||||
|
|
||||||
|
[AttributeUsage(.All)]
|
||||||
|
public struct CheckEnumAttribute : Attribute, IComptimeTypeApply
|
||||||
|
{
|
||||||
|
public void ApplyToType(Type type)
|
||||||
|
{
|
||||||
|
int fieldIdx = 0;
|
||||||
|
for (var field in type.GetFields())
|
||||||
|
{
|
||||||
|
switch (fieldIdx)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
Test.Assert(field.Name == "$payload");
|
||||||
|
Test.Assert(field.MemberOffset == 0);
|
||||||
|
Test.Assert(field.FieldType == typeof(int64));
|
||||||
|
case 1:
|
||||||
|
Test.Assert(field.Name == "$discriminator");
|
||||||
|
Test.Assert(field.MemberOffset == 8);
|
||||||
|
Test.Assert(field.FieldType == typeof(int8));
|
||||||
|
}
|
||||||
|
fieldIdx++;
|
||||||
|
}
|
||||||
|
Test.Assert(fieldIdx == 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const String cTest0 = Compiler.ReadText("Test0.txt");
|
const String cTest0 = Compiler.ReadText("Test0.txt");
|
||||||
const String cTest1 = new String('A', 12);
|
const String cTest1 = new String('A', 12);
|
||||||
const uint8[?] cTest0Binary = Compiler.ReadBinary("Test0.txt");
|
const uint8[?] cTest0Binary = Compiler.ReadBinary("Test0.txt");
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue