1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 03:52:19 +02:00

Added support for some constant enums with payloads

This commit is contained in:
Brian Fiete 2021-02-01 11:19:50 -08:00
parent 5677f27cac
commit 86967c39c3
8 changed files with 313 additions and 39 deletions

View file

@ -2009,7 +2009,7 @@ void BfCompiler::CreateVData(BfVDataModule* bfModule)
int dataSize = 16*1024;
auto irArrType = bfModule->mBfIRBuilder->GetSizedArrayType(bfModule->mBfIRBuilder->MapType(int8Type), dataSize);
String name = "__BFTLS_EXTRA";
auto irVal = bfModule->mBfIRBuilder->CreateGlobalVariable(irArrType, false, BfIRLinkageType_External, bfModule->mBfIRBuilder->CreateConstStructZero(irArrType), name, true);
auto irVal = bfModule->mBfIRBuilder->CreateGlobalVariable(irArrType, false, BfIRLinkageType_External, bfModule->mBfIRBuilder->CreateConstAggZero(irArrType), name, true);
BfIRMDNode dbgArrayType = bfModule->mBfIRBuilder->DbgCreateArrayType(dataSize * 8, 8, bfModule->mBfIRBuilder->DbgGetType(int8Type), dataSize);
bfModule->mBfIRBuilder->DbgCreateGlobalVariable(bfModule->mDICompileUnit, name, name, BfIRMDNode(), 0, dbgArrayType, false, irVal);
}

View file

@ -4495,28 +4495,26 @@ BfTypedValue BfExprEvaluator::LookupField(BfAstNode* targetSrc, BfTypedValue tar
{
return BfTypedValue(mModule->mBfIRBuilder->CreateConst(dscrType->mTypeDef->mTypeCode, tagIdx), fieldInstance->mOwner);
}
mModule->PopulateType(fieldInstance->mOwner, BfPopulateType_Data);
// auto agg = mModule->mBfIRBuilder->CreateUndefValue(mModule->mBfIRBuilder->MapType(fieldInstance->mOwner));
// agg = mModule->mBfIRBuilder->CreateInsertValue(agg, mModule->mBfIRBuilder->CreateConst(dscrType->mTypeDef->mTypeCode, tagIdx), 2);
// OLD:
// auto agg = mModule->CreateAlloca(fieldInstance->mOwner);
// auto gep = mModule->mBfIRBuilder->CreateInBoundsGEP(agg, 0, 2);
// mModule->mBfIRBuilder->CreateStore(mModule->mBfIRBuilder->CreateConst(dscrType->mTypeDef->mTypeCode, tagIdx), gep);
//
// if (fieldInstance->mResolvedType->mSize != 0)
// {
// mModule->FailAfter("Enum case parameters expected", targetSrc);
// }
//
// return BfTypedValue(agg, fieldInstance->mOwner);
// return BfTypedValue(agg, fieldInstance->mOwner, true);
auto agg = mModule->CreateAlloca(fieldInstance->mOwner);
auto gep = mModule->mBfIRBuilder->CreateInBoundsGEP(agg, 0, 2);
mModule->mBfIRBuilder->CreateStore(mModule->mBfIRBuilder->CreateConst(dscrType->mTypeDef->mTypeCode, tagIdx), gep);
if (fieldInstance->mResolvedType->mSize != 0)
{
mModule->FailAfter("Enum case parameters expected", targetSrc);
}
return BfTypedValue(agg, fieldInstance->mOwner, true);
//NEW
SizedArray<BfIRValue, 3> values;
values.Add(mModule->mBfIRBuilder->CreateConstAggZero(mModule->mBfIRBuilder->MapType(curCheckType->mBaseType)));
values.Add(mModule->mBfIRBuilder->CreateConstAggZero(mModule->mBfIRBuilder->MapType(curCheckType->GetUnionInnerType())));
values.Add(mModule->mBfIRBuilder->CreateConst(dscrType->mTypeDef->mTypeCode, tagIdx));
return BfTypedValue(mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(curCheckType), values), curCheckType);
}
if (fieldInstance->mConstIdx == -1)
@ -7640,7 +7638,13 @@ BfTypedValue BfExprEvaluator::CheckEnumCreation(BfAstNode* targetSrc, BfTypeInst
BfIRValue enumValue;
BfTypedValue result;
if ((mReceivingValue != NULL) && (mReceivingValue->mType == enumType) && (mReceivingValue->IsAddr()))
bool wantConst = IsComptimeEntry();
if (wantConst)
{
NOP;
}
else if ((mReceivingValue != NULL) && (mReceivingValue->mType == enumType) && (mReceivingValue->IsAddr()))
{
result = *mReceivingValue;
mReceivingValue = NULL;
@ -7657,10 +7661,16 @@ BfTypedValue BfExprEvaluator::CheckEnumCreation(BfAstNode* targetSrc, BfTypeInst
auto tupleType = (BfTypeInstance*)fieldInstance->mResolvedType;
mModule->mBfIRBuilder->PopulateType(tupleType);
bool constFailed = false;
SizedArray<BfIRValue, 8> constTupleMembers;
BfIRValue fieldPtr;
BfIRValue tuplePtr;
if (!tupleType->IsValuelessType())
if (wantConst)
{
constTupleMembers.Add(mModule->mBfIRBuilder->CreateConstAggZero(mModule->mBfIRBuilder->MapType(tupleType->mBaseType)));
}
else if (!tupleType->IsValuelessType())
{
fieldPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(enumValue, 0, 1);
auto tuplePtrType = mModule->CreatePointerType(tupleType);
@ -7688,6 +7698,8 @@ BfTypedValue BfExprEvaluator::CheckEnumCreation(BfAstNode* targetSrc, BfTypeInst
BfError* error = mModule->Fail(StrFormat("Not enough parameters specified, expected %d more.", tupleType->mFieldInstances.size() - (int)argValues.mArguments->size()), refNode);
if (error != NULL)
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See enum declaration"), fieldDef->mFieldDeclaration);
if (wantConst)
constFailed = true;
break;
}
@ -7701,12 +7713,21 @@ BfTypedValue BfExprEvaluator::CheckEnumCreation(BfAstNode* targetSrc, BfTypeInst
auto argValue = ResolveArgValue(argValues.mResolvedArgs[tupleFieldIdx], resolvedFieldType, &receivingValue);
if (!argValue)
{
if (wantConst)
constFailed = true;
continue;
}
if (argValue.IsValuelessType())
{
continue;
}
// Used receiving value?
if (argValue.mValue == receivingValue.mValue)
continue;
if ((!argValue) || (argValue.IsValuelessType()))
continue;
argValue = mModule->AggregateSplat(argValue);
argValues.mResolvedArgs[tupleFieldIdx].mExpectedType = resolvedFieldType;
if ((argValues.mResolvedArgs[tupleFieldIdx].mArgFlags & (BfArgFlag_DelegateBindAttempt | BfArgFlag_LambdaBindAttempt | BfArgFlag_UnqualifiedDotAttempt)) != 0)
@ -7721,13 +7742,24 @@ BfTypedValue BfExprEvaluator::CheckEnumCreation(BfAstNode* targetSrc, BfTypeInst
// argValue can have a value even if tuplePtr does not have a value. This can happen if we are assigning to a (void) tuple,
// but we have a value that needs to be attempted to be casted to void
argValue = mModule->Cast(argValues.mResolvedArgs[tupleFieldIdx].mExpression, argValue, resolvedFieldType);
if (tupleFieldPtr)
if (wantConst)
{
if (!argValue.mValue.IsConst())
{
mModule->Fail("Field not const", argValues.mResolvedArgs[tupleFieldIdx].mExpression);
constFailed = true;
}
constTupleMembers.Add(argValue.mValue);
}
else if (tupleFieldPtr)
{
argValue = mModule->LoadValue(argValue);
if (argValue)
mModule->mBfIRBuilder->CreateAlignedStore(argValue.mValue, tupleFieldPtr, resolvedFieldType->mAlign);
}
}
else if (wantConst)
constFailed = true;
}
if ((intptr)argValues.mResolvedArgs.size() > tupleType->mFieldInstances.size())
@ -7739,14 +7771,49 @@ BfTypedValue BfExprEvaluator::CheckEnumCreation(BfAstNode* targetSrc, BfTypeInst
BfError* error = mModule->Fail(StrFormat("Too many arguments, expected %d fewer.", argValues.mResolvedArgs.size() - tupleType->mFieldInstances.size()), errorRef);
if (error != NULL)
mModule->mCompiler->mPassInstance->MoreInfo(StrFormat("See enum declaration"), fieldDef->mFieldDeclaration);
}
//auto fieldPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(enumValue, 0, 2);
if (wantConst)
constFailed = true;
}
auto dscrType = enumType->GetDiscriminatorType();
auto dscrField = &enumType->mFieldInstances.back();
int tagIdx = -fieldInstance->mDataIdx - 1;
if ((wantConst) && (!constFailed))
{
auto unionType = enumType->GetUnionInnerType();
auto constTuple = mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(tupleType, BfIRPopulateType_Full), constTupleMembers);
Array<uint8> memArr;
memArr.Resize(unionType->mSize);
if (!mModule->mBfIRBuilder->WriteConstant(constTuple, memArr.mVals, tupleType))
{
constFailed = true;
}
else
{
auto unionValue = mModule->mBfIRBuilder->ReadConstant(memArr.mVals, unionType);
if (!unionValue)
{
constFailed = true;
}
else
{
SizedArray<BfIRValue, 3> constEnumMembers;
constEnumMembers.Add(mModule->mBfIRBuilder->CreateConstAggZero(mModule->mBfIRBuilder->MapType(enumType->mBaseType, BfIRPopulateType_Full)));
constEnumMembers.Add(unionValue);
constEnumMembers.Add(mModule->mBfIRBuilder->CreateConst(dscrType->mTypeDef->mTypeCode, tagIdx));
return BfTypedValue(mModule->mBfIRBuilder->CreateConstAgg(mModule->mBfIRBuilder->MapType(enumType, BfIRPopulateType_Full), constEnumMembers), enumType);
}
}
}
if (constFailed)
{
return mModule->GetDefaultTypedValue(enumType, false, BfDefaultValueKind_Addr);
}
auto dscFieldPtr = mModule->mBfIRBuilder->CreateInBoundsGEP(enumValue, 0, dscrField->mDataIdx);
mModule->mBfIRBuilder->CreateAlignedStore(mModule->mBfIRBuilder->CreateConst(dscrType->mTypeDef->mTypeCode, tagIdx), dscFieldPtr, 4);
return result;
@ -18598,7 +18665,7 @@ void BfExprEvaluator::Visit(BfTupleExpression* tupleExpr)
Array<BfIRValue> irValues;
irValues.Resize(typedValues.mSize + 1);
irValues[0] = mModule->mBfIRBuilder->CreateConstStructZero(mModule->mBfIRBuilder->MapType(tupleType->mBaseType));
irValues[0] = mModule->mBfIRBuilder->CreateConstAggZero(mModule->mBfIRBuilder->MapType(tupleType->mBaseType));
for (int fieldIdx = 0; fieldIdx < (int)tupleType->mFieldInstances.size(); fieldIdx++)
{

View file

@ -664,7 +664,7 @@ BfIRValue BfIRConstHolder::CreateConst(BfConstant* fromConst, BfIRConstHolder* f
else if (fromConst->mConstType == BfConstType_AggZero)
{
auto aggZero = (BfConstant*)fromConst;
return CreateConstStructZero(fromConst->mIRType);
return CreateConstAggZero(fromConst->mIRType);
}
else if (fromConst->mConstType == BfConstType_Agg)
{
@ -747,7 +747,7 @@ BfIRValue BfIRConstHolder::CreateConstNull(BfIRType ptrType)
return irValue;
}
BfIRValue BfIRConstHolder::CreateConstStructZero(BfIRType aggType)
BfIRValue BfIRConstHolder::CreateConstAggZero(BfIRType aggType)
{
BfConstant* constant = mTempAlloc.Alloc<BfConstant>();
constant->mConstType = BfConstType_AggZero;
@ -863,6 +863,203 @@ BfIRValue BfIRConstHolder::GetUndefConstValue(BfIRType irType)
return undefVal;
}
bool BfIRConstHolder::WriteConstant(BfIRValue val, void* ptr, BfType* type)
{
auto constant = GetConstant(val);
if (constant == NULL)
return false;
switch (constant->mTypeCode)
{
case BfTypeCode_Int8:
case BfTypeCode_UInt8:
case BfTypeCode_Boolean:
case BfTypeCode_Char8:
*(int8*)ptr = constant->mInt8;
return true;
case BfTypeCode_Int16:
case BfTypeCode_UInt16:
case BfTypeCode_Char16:
*(int16*)ptr = constant->mInt16;
return true;
case BfTypeCode_Int32:
case BfTypeCode_UInt32:
case BfTypeCode_Char32:
*(int32*)ptr = constant->mInt32;
return true;
case BfTypeCode_Int64:
case BfTypeCode_UInt64:
*(int64*)ptr = constant->mInt64;
return true;
case BfTypeCode_NullPtr:
if (mModule->mSystem->mPtrSize == 4)
*(int32*)ptr = 0;
else
*(int64*)ptr = 0;
return true;
case BfTypeCode_Float:
*(float*)ptr = (float)constant->mDouble;
return true;
case BfTypeCode_Double:
*(double*)ptr = constant->mDouble;
return true;
}
if (constant->mConstType == BfConstType_Agg)
{
auto aggConstant = (BfConstantAgg*)constant;
if (type->IsSizedArray())
{
auto sizedArrayType = (BfSizedArrayType*)type;
for (int i = 0; i < sizedArrayType->mElementCount; i++)
{
if (!WriteConstant(aggConstant->mValues[i], (uint8*)ptr + (i * sizedArrayType->mElementType->GetStride()), sizedArrayType->mElementType))
return false;
}
return false;
}
else
{
BF_ASSERT(type->IsStruct());
mModule->PopulateType(type);
auto typeInst = type->ToTypeInstance();
int idx = 0;
if (typeInst->mBaseType != NULL)
{
if (!WriteConstant(aggConstant->mValues[0], ptr, typeInst->mBaseType))
return false;
}
for (auto& fieldInstance : typeInst->mFieldInstances)
{
if (fieldInstance.mDataOffset < 0)
continue;
if (!WriteConstant(aggConstant->mValues[fieldInstance.mDataIdx], (uint8*)ptr + fieldInstance.mDataOffset, fieldInstance.mResolvedType))
return false;
}
}
return true;
}
if (constant->mConstType == BfConstType_AggZero)
{
BF_ASSERT(type->IsComposite());
memset(ptr, 0, type->mSize);
return true;
}
if (constant->mConstType == BfConstType_BitCast)
{
auto constBitCast = (BfConstantBitCast*)constant;
auto constTarget = mModule->mBfIRBuilder->GetConstantById(constBitCast->mTarget);
return WriteConstant(BfIRValue(BfIRValueFlags_Const, constBitCast->mTarget), ptr, type);
}
return false;
}
BfIRValue BfIRConstHolder::ReadConstant(void* ptr, BfType* type)
{
if (type->IsPrimitiveType())
{
auto primType = (BfPrimitiveType*)type;
switch (primType->mTypeDef->mTypeCode)
{
case BfTypeCode_Int8:
case BfTypeCode_UInt8:
case BfTypeCode_Boolean:
case BfTypeCode_Char8:
return CreateConst(primType->mTypeDef->mTypeCode, *(int8*)ptr);
case BfTypeCode_Int16:
case BfTypeCode_UInt16:
case BfTypeCode_Char16:
return CreateConst(primType->mTypeDef->mTypeCode, *(int16*)ptr);
case BfTypeCode_Int32:
case BfTypeCode_UInt32:
case BfTypeCode_Char32:
return CreateConst(primType->mTypeDef->mTypeCode, *(int32*)ptr);
case BfTypeCode_Int64:
case BfTypeCode_UInt64:
return CreateConst(primType->mTypeDef->mTypeCode, *(uint64*)ptr);
case BfTypeCode_NullPtr:
return CreateConstNull();
case BfTypeCode_Float:
return CreateConst(primType->mTypeDef->mTypeCode, *(float*)ptr);
case BfTypeCode_Double:
return CreateConst(primType->mTypeDef->mTypeCode, *(double*)ptr);
case BfTypeCode_IntPtr:
case BfTypeCode_UIntPtr:
if (mModule->mSystem->mPtrSize == 4)
return CreateConst(primType->mTypeDef->mTypeCode, *(int32*)ptr);
else
return CreateConst(primType->mTypeDef->mTypeCode, *(uint64*)ptr);
default:
return BfIRValue();
}
}
if (type->IsTypedPrimitive())
{
return ReadConstant(ptr, type->GetUnderlyingType());
}
if (type->IsSizedArray())
{
SizedArray<BfIRValue, 8> irValues;
auto sizedArrayType = (BfSizedArrayType*)type;
for (int i = 0; i < sizedArrayType->mElementCount; i++)
{
auto val = ReadConstant((uint8*)ptr + (i * sizedArrayType->mElementType->GetStride()), sizedArrayType->mElementType);
if (!val)
return BfIRValue();
irValues.Add(val);
}
BfIRType irType;
irType.mKind = BfIRTypeData::TypeKind_TypeId;
irType.mId = type->mTypeId;
return CreateConstAgg(irType, irValues);
}
if (type->IsStruct())
{
mModule->PopulateType(type);
auto typeInst = type->ToTypeInstance();
int idx = 0;
SizedArray<BfIRValue, 8> irValues;
if (typeInst->mBaseType != NULL)
{
auto val = ReadConstant(ptr, typeInst->mBaseType);
if (!val)
return BfIRValue();
irValues.Add(val);
}
for (auto& fieldInstance : typeInst->mFieldInstances)
{
if (fieldInstance.mDataOffset < 0)
continue;
auto val = ReadConstant((uint8*)ptr + fieldInstance.mDataOffset, fieldInstance.mResolvedType);
if (!val)
return BfIRValue();
irValues.Add(val);
}
BfIRType irType;
irType.mKind = BfIRTypeData::TypeKind_TypeId;
irType.mId = type->mTypeId;
return CreateConstAgg(irType, irValues);
}
return BfIRValue();
}
//////////////////////////////////////////////////////////////////////////
void BfIRBuilder::OpFailed()

View file

@ -928,7 +928,7 @@ public:
BfIRValue CreateConst(BfConstant* fromConst, BfIRConstHolder* fromHolder);
BfIRValue CreateConstNull();
BfIRValue CreateConstNull(BfIRType nullType);
BfIRValue CreateConstStructZero(BfIRType aggType);
BfIRValue CreateConstAggZero(BfIRType aggType);
BfIRValue CreateConstAgg(BfIRType type, const BfSizedArray<BfIRValue>& values);
BfIRValue CreateConstAggCE(BfIRType type, addr_ce ptr);
BfIRValue CreateConstArrayZero(BfIRType type, int count);
@ -936,6 +936,9 @@ public:
BfIRValue CreateTypeOf(BfType* type);
BfIRValue CreateTypeOf(BfType* type, BfIRValue typeData);
BfIRValue GetUndefConstValue(BfIRType type);
bool WriteConstant(BfIRValue val, void* ptr, BfType* type);
BfIRValue ReadConstant(void* ptr, BfType* type);
};
enum BfIRPopulateType

View file

@ -1454,7 +1454,7 @@ BfIRValue BfModule::GetDefaultValue(BfType* type)
}
if (type->IsVoid())
return mBfIRBuilder->CreateConstNull(mBfIRBuilder->MapType(type));
return mBfIRBuilder->CreateConstStructZero(mBfIRBuilder->MapType(type));
return mBfIRBuilder->CreateConstAggZero(mBfIRBuilder->MapType(type));
}
BfTypedValue BfModule::GetFakeTypedValue(BfType* type)
@ -8440,7 +8440,7 @@ BfIRValue BfModule::GetDbgRawAllocData(BfType* type)
}
SizedArray<BfIRValue, 2> dataValues;
dataValues.Add(mBfIRBuilder->CreateConstStructZero(mBfIRBuilder->MapType(dbgRawAllocDataType->mBaseType, BfIRPopulateType_Full)));
dataValues.Add(mBfIRBuilder->CreateConstAggZero(mBfIRBuilder->MapType(dbgRawAllocDataType->mBaseType, BfIRPopulateType_Full)));
dataValues.Add(typeDataRef);
dataValues.Add(markFuncPtr);
dataValues.Add(mBfIRBuilder->CreateConst(BfTypeCode_Int32, stackCount));

View file

@ -11351,7 +11351,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
return allocaInst;
}
auto zeroNullable = mBfIRBuilder->CreateConstStructZero(mBfIRBuilder->MapType(toType));
auto zeroNullable = mBfIRBuilder->CreateConstAggZero(mBfIRBuilder->MapType(toType));
return zeroNullable;
}
@ -11778,7 +11778,7 @@ BfIRValue BfModule::CastToValue(BfAstNode* srcNode, BfTypedValue typedVal, BfTyp
auto stringCharPtr = GetStringCharPtr(stringId);
SizedArray<BfIRValue, 2> spanFieldVals;
spanFieldVals.Add(mBfIRBuilder->CreateConstStructZero(mBfIRBuilder->MapType(svTypeInst->mBaseType->mBaseType)));
spanFieldVals.Add(mBfIRBuilder->CreateConstAggZero(mBfIRBuilder->MapType(svTypeInst->mBaseType->mBaseType)));
spanFieldVals.Add(stringCharPtr);
spanFieldVals.Add(mBfIRBuilder->CreateConst(BfTypeCode_IntPtr, entry->mString.mLength));

View file

@ -3368,7 +3368,8 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta
auto fieldConstant = module->mBfIRBuilder->GetConstant(aggConstant->mValues[i]);
if (fieldConstant == NULL)
return false;
WriteConstant(module, elemsAddr + i * elemType->GetStride(), fieldConstant, elemType);
if (!WriteConstant(module, elemsAddr + i * elemType->GetStride(), fieldConstant, elemType))
return false;
}
if (mCeMachine->mCeModule->mSystem->mPtrSize == 4)
@ -3388,7 +3389,8 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta
auto fieldConstant = module->mBfIRBuilder->GetConstant(aggConstant->mValues[i]);
if (fieldConstant == NULL)
return false;
WriteConstant(module, elemsAddr + i * elemType->GetStride(), fieldConstant, elemType);
if (!WriteConstant(module, elemsAddr + i * elemType->GetStride(), fieldConstant, elemType))
return false;
}
if (mCeMachine->mCeModule->mSystem->mPtrSize == 4)
@ -3415,7 +3417,8 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta
if (typeInst->mBaseType != NULL)
{
auto baseConstant = module->mBfIRBuilder->GetConstant(aggConstant->mValues[0]);
WriteConstant(module, addr, baseConstant, typeInst->mBaseType);
if (!WriteConstant(module, addr, baseConstant, typeInst->mBaseType))
return false;
}
for (auto& fieldInstance : typeInst->mFieldInstances)
@ -3426,7 +3429,8 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta
auto fieldConstant = module->mBfIRBuilder->GetConstant(aggConstant->mValues[fieldInstance.mDataIdx]);
if (fieldConstant == NULL)
return false;
WriteConstant(module, addr + fieldInstance.mDataOffset, fieldConstant, fieldInstance.mResolvedType);
if (!WriteConstant(module, addr + fieldInstance.mDataOffset, fieldConstant, fieldInstance.mResolvedType))
return false;
}
}
return true;

View file

@ -85,6 +85,9 @@ namespace Tests
}
Test.Assert(a == 3);
Test.Assert(b == 4);
const EnumE e0 = .A;
const EnumE e1 = .B(1);
}
[Test]