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

Improved handling of strings in const enum payloads

This commit is contained in:
Brian Fiete 2022-02-14 12:30:24 -05:00
parent 63ef0fed7a
commit c9f1e37da7
5 changed files with 121 additions and 14 deletions

View file

@ -17351,7 +17351,20 @@ void BfExprEvaluator::DoInvocation(BfAstNode* target, BfMethodBoundExpression* m
if (isCascade) if (isCascade)
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_InCascade); mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_InCascade);
ResolveArgValues(argValues, resolveArgsFlags); ResolveArgValues(argValues, resolveArgsFlags);
//
{
// We also apply this right before the actual call, but we need to set the comptime flag earlier
SetAndRestoreValue<BfEvalExprFlags> prevEvalExprFlag(mBfEvalExprFlags);
if ((mModule->mAttributeState != NULL) && (mModule->mAttributeState->mCustomAttributes != NULL) && (mModule->mAttributeState->mCustomAttributes->Contains(mModule->mCompiler->mConstEvalAttributeTypeDef)))
{
mModule->mAttributeState->mUsed = true;
mBfEvalExprFlags = (BfEvalExprFlags)(mBfEvalExprFlags | BfEvalExprFlags_Comptime);
}
mResult = MatchMethod(methodNodeSrc, methodBoundExpr, thisValue, allowImplicitThis, bypassVirtual, targetFunctionName, argValues, methodGenericArgs, checkedKind); mResult = MatchMethod(methodNodeSrc, methodBoundExpr, thisValue, allowImplicitThis, bypassVirtual, targetFunctionName, argValues, methodGenericArgs, checkedKind);
}
argValues.HandleFixits(mModule); argValues.HandleFixits(mModule);
if (mModule->mAttributeState == &attributeState) if (mModule->mAttributeState == &attributeState)

View file

@ -971,6 +971,7 @@ bool BfIRConstHolder::WriteConstant(BfIRValue val, void* ptr, BfType* type)
case BfTypeCode_Int32: case BfTypeCode_Int32:
case BfTypeCode_UInt32: case BfTypeCode_UInt32:
case BfTypeCode_Char32: case BfTypeCode_Char32:
case BfTypeCode_StringId:
*(int32*)ptr = constant->mInt32; *(int32*)ptr = constant->mInt32;
return true; return true;
case BfTypeCode_Int64: case BfTypeCode_Int64:
@ -1003,7 +1004,7 @@ bool BfIRConstHolder::WriteConstant(BfIRValue val, void* ptr, BfType* type)
return false; return false;
} }
return false; return true;
} }
else else
{ {
@ -1055,6 +1056,24 @@ bool BfIRConstHolder::WriteConstant(BfIRValue val, void* ptr, BfType* type)
return WriteConstant(BfIRValue(BfIRValueFlags_Const, constBitCast->mTarget), ptr, type); return WriteConstant(BfIRValue(BfIRValueFlags_Const, constBitCast->mTarget), ptr, type);
} }
if (constant->mConstType == BfConstType_GlobalVar)
{
auto constGV = (BfGlobalVar*)constant;
const char* strDataPrefix = "__bfStrData";
if (strncmp(constGV->mName, strDataPrefix, strlen(strDataPrefix)) == 0)
{
*(int32*)ptr = atoi(constGV->mName + strlen(strDataPrefix));
return true;
}
const char* strObjPrefix = "__bfStrObj";
if (strncmp(constGV->mName, strObjPrefix, strlen(strObjPrefix)) == 0)
{
*(int32*)ptr = atoi(constGV->mName + strlen(strObjPrefix));
return true;
}
}
return false; return false;
} }
@ -1077,6 +1096,7 @@ BfIRValue BfIRConstHolder::ReadConstant(void* ptr, BfType* type)
case BfTypeCode_Int32: case BfTypeCode_Int32:
case BfTypeCode_UInt32: case BfTypeCode_UInt32:
case BfTypeCode_Char32: case BfTypeCode_Char32:
case BfTypeCode_StringId:
return CreateConst(primType->mTypeDef->mTypeCode, *(int32*)ptr); return CreateConst(primType->mTypeDef->mTypeCode, *(int32*)ptr);
case BfTypeCode_Int64: case BfTypeCode_Int64:
case BfTypeCode_UInt64: case BfTypeCode_UInt64:
@ -1165,6 +1185,11 @@ BfIRValue BfIRConstHolder::ReadConstant(void* ptr, BfType* type)
return CreateConstAgg(irType, irValues); return CreateConstAgg(irType, irValues);
} }
if (type->IsInstanceOf(mModule->mCompiler->mStringTypeDef))
{
return CreateConst(BfTypeCode_StringId, *(int32*)ptr);
}
return BfIRValue(); return BfIRValue();
} }

View file

@ -23842,6 +23842,8 @@ bool BfModule::SlotVirtualMethod(BfMethodInstance* methodInstance, BfAmbiguityCo
continue; continue;
int checkMethodIdx = lookupMethodInstance->mVirtualTableIdx; int checkMethodIdx = lookupMethodInstance->mVirtualTableIdx;
if (checkMethodIdx >= baseVirtualMethodTable.mSize)
FatalError("SlotVirtualMethod OOB in baseVirtualMethodTable[checkMethodIdx]");
auto& baseMethodRef = baseVirtualMethodTable[checkMethodIdx]; auto& baseMethodRef = baseVirtualMethodTable[checkMethodIdx];
if (baseMethodRef.mDeclaringMethod.mMethodNum == -1) if (baseMethodRef.mDeclaringMethod.mMethodNum == -1)
{ {

View file

@ -3618,12 +3618,50 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta
return false; return false;
} }
BfType* innerType = NULL;
BfType* payloadType = NULL;
if (typeInst->IsUnion())
innerType = typeInst->GetUnionInnerType();
if (typeInst->IsPayloadEnum()) if (typeInst->IsPayloadEnum())
{ {
auto innerType = typeInst->GetUnionInnerType(); auto& dscrFieldInstance = typeInst->mFieldInstances.back();
auto fieldConstant = module->mBfIRBuilder->GetConstant(aggConstant->mValues[dscrFieldInstance.mDataIdx]);
if (fieldConstant == NULL)
return false;
if (!WriteConstant(module, addr + dscrFieldInstance.mDataOffset, fieldConstant, dscrFieldInstance.mResolvedType))
return false;
for (auto& fieldInstance : typeInst->mFieldInstances)
{
auto fieldDef = fieldInstance.GetFieldDef();
if (!fieldInstance.mIsEnumPayloadCase)
continue;
int tagIdx = -fieldInstance.mDataIdx - 1;
if (fieldConstant->mInt32 == tagIdx)
payloadType = fieldInstance.mResolvedType;
}
}
if (typeInst->IsUnion())
{
if (!innerType->IsValuelessType()) if (!innerType->IsValuelessType())
{ {
auto fieldConstant = module->mBfIRBuilder->GetConstant(aggConstant->mValues[1]); BfIRValue dataVal = aggConstant->mValues[1];
if ((payloadType != NULL) && (innerType != NULL))
{
Array<uint8> memArr;
memArr.Resize(innerType->mSize);
if (!module->mBfIRBuilder->WriteConstant(dataVal, memArr.mVals, innerType))
return false;
dataVal = module->mBfIRBuilder->ReadConstant(memArr.mVals, payloadType);
if (!dataVal)
return false;
innerType = payloadType;
}
auto fieldConstant = module->mBfIRBuilder->GetConstant(dataVal);
if (fieldConstant == NULL) if (fieldConstant == NULL)
return false; return false;
if (!WriteConstant(module, addr, fieldConstant, innerType)) if (!WriteConstant(module, addr, fieldConstant, innerType))
@ -3631,6 +3669,8 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta
} }
} }
if (!typeInst->IsUnion())
{
for (auto& fieldInstance : typeInst->mFieldInstances) for (auto& fieldInstance : typeInst->mFieldInstances)
{ {
if (fieldInstance.mDataOffset < 0) if (fieldInstance.mDataOffset < 0)
@ -3643,6 +3683,7 @@ bool CeContext::WriteConstant(BfModule* module, addr_ce addr, BfConstant* consta
return false; return false;
} }
} }
}
return true; return true;
} }

View file

@ -6,6 +6,18 @@ namespace Tests
{ {
class ConstEval class ConstEval
{ {
public enum EnumA
{
case A;
case B(float a, float b);
case C(String str);
public struct Inner
{
public const EnumA cVal = EnumA.C("InnerTest");
}
}
struct StructA struct StructA
{ {
public int32 mA; public int32 mA;
@ -145,6 +157,11 @@ namespace Tests
return test!(); return test!();
} }
static String EnumAToStr(EnumA ea)
{
return ea.ToString(.. new .());
}
[Test] [Test]
public static void TestBasics() public static void TestBasics()
{ {
@ -183,6 +200,15 @@ namespace Tests
Test.Assert(MethodC() == 1753); Test.Assert(MethodC() == 1753);
Test.Assert(StrLenMixin("ABCD") == 4); Test.Assert(StrLenMixin("ABCD") == 4);
String s1 = [ConstEval]EnumAToStr(.C("Test1"));
Test.Assert(s1 === "C(\"Test1\")");
const String s2 = EnumAToStr(.C("Test2"));
Test.Assert(s2 === "C(\"Test2\")");
const String s3 = EnumAToStr(.B(1, 2));
Test.Assert(s3 === "B(1, 2)");
const let s4 = EnumAToStr(EnumA.Inner.cVal);
Test.Assert(s4 === "C(\"InnerTest\")");
} }
} }
} }