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 struct FlexibleArrayAttribute : Attribute, IOnTypeInit
{ {
String mName; String mName;
@ -99,20 +99,61 @@ namespace System
mName = name; 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] [Comptime]
public void OnTypeInit(Type type, Self* prev) public void OnTypeInit(Type type, Self* prev)
{ {
if (type.IsGenericParam) if (type.IsGenericParam)
return; return;
var field = type.GetField(type.FieldCount - 1).GetValueOrDefault(); var field = type.GetField(type.FieldCount - 1).GetValueOrDefault();
if ((field.FieldType == null) || (!field.FieldType.IsSizedArray) || (field.FieldType.Size != 0)) if (field.FieldType?.IsUnion == true)
Runtime.FatalError("Type must end in a zero-sized array"); {
var elementType = (field.FieldType as SizedArrayType).UnderlyingType; int diff = 0;
Compiler.Align(type, elementType.Align); for (var unionField in field.FieldType.GetFields(.Instance))
Compiler.EmitTypeBody(type, scope $""" diff++;
public {elementType}* {mName} mut => (({elementType}*)((uint8*)&this + Math.Align(typeof(Self).Size, typeof({elementType}).Align))); for (var names in mName.Split('\n'))
public static int GetAllocSize(int arrayCount) => Math.Align(typeof(Self).Size, typeof({elementType}).Align) + typeof({elementType}).Size*arrayCount; 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 + 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)); 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 else
{ {
auto wantTypeInst = wantType->ToTypeInstance(); auto wantTypeInst = wantType->ToTypeInstance();