1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 19:48:20 +02:00

Allow FlexibleArray with union array data

This commit is contained in:
Brian Fiete 2022-08-28 10:48:56 -07:00
parent 8aef7275d0
commit cc3fe5e40c
2 changed files with 58 additions and 9 deletions

View file

@ -89,7 +89,7 @@ namespace System
}
}
[AttributeUsage(.Struct)]
[AttributeUsage(.Struct, .DisallowAllowMultiple)]
struct FlexibleArrayAttribute : Attribute, IOnTypeInit
{
String mName;
@ -99,21 +99,62 @@ namespace System
mName = name;
}
public this(params Span<String> names)
{
mName = new String();
for (var name in names)
{
if (!mName.IsEmpty)
mName.Append("\n");
mName.Append(name);
}
}
[Comptime]
public void OnTypeInit(Type type, Self* prev)
{
if (type.IsGenericParam)
return;
var field = type.GetField(type.FieldCount - 1).GetValueOrDefault();
if (field.FieldType?.IsUnion == true)
{
int diff = 0;
for (var unionField in field.FieldType.GetFields(.Instance))
diff++;
for (var names in mName.Split('\n'))
diff--;
if (diff != 0)
Runtime.FatalError("Incorrect number of names specified");
var nameItr = mName.Split('\n');
for (var unionField in field.FieldType.GetFields(.Instance))
{
var name = nameItr.GetNext().Value;
if ((!unionField.FieldType.IsSizedArray) || (unionField.FieldType.Size != 0))
Runtime.FatalError(scope $"Union field '{unionField.Name}' must be a zero-sized array");
var elementType = (unionField.FieldType as SizedArrayType).UnderlyingType;
Compiler.Align(type, elementType.Align);
Compiler.EmitTypeBody(type, scope $"""
public {elementType}* {name} mut => (({elementType}*)((uint8*)&this + typeof(Self).Size));
public static int GetAllocSize_{name}(int arrayCount) => typeof(Self).Size + typeof({elementType}).Size*arrayCount;
""");
}
}
else
{
if (mName.Contains('\n'))
Runtime.FatalError("Only a single accessor name expected");
if ((field.FieldType == null) || (!field.FieldType.IsSizedArray) || (field.FieldType.Size != 0))
Runtime.FatalError("Type must end in a zero-sized array");
var elementType = (field.FieldType as SizedArrayType).UnderlyingType;
Compiler.Align(type, elementType.Align);
Compiler.EmitTypeBody(type, scope $"""
public {elementType}* {mName} mut => (({elementType}*)((uint8*)&this + Math.Align(typeof(Self).Size, typeof({elementType}).Align)));
public static int GetAllocSize(int arrayCount) => Math.Align(typeof(Self).Size, typeof({elementType}).Align) + typeof({elementType}).Size*arrayCount;
public {elementType}* {mName} mut => (({elementType}*)((uint8*)&this + typeof(Self).Size));
public static int GetAllocSize(int arrayCount) => typeof(Self).Size + typeof({elementType}).Size*arrayCount;
""");
}
}
}
}
}

View file

@ -11777,6 +11777,14 @@ BfIRValue BfModule::ConstantToCurrent(BfConstant* constant, BfIRConstHolder* con
newVals.Add(ConstantToCurrent(constHolder->GetConstant(val), constHolder, elementType));
}
}
else if (wantType->IsInstanceOf(mCompiler->mSpanTypeDef))
{
auto elementType = wantType->GetUnderlyingType();
for (auto val : constArray->mValues)
{
newVals.Add(ConstantToCurrent(constHolder->GetConstant(val), constHolder, elementType));
}
}
else
{
auto wantTypeInst = wantType->ToTypeInstance();