This commit is contained in:
nub31
2025-08-12 20:55:35 +02:00
parent f31c16bbac
commit 9dabf0d2f7
7 changed files with 248 additions and 174 deletions

View File

@@ -189,7 +189,7 @@ public partial class QBEGenerator
{
var size = TmpName();
_writer.Indented($"{size} =l loadl {array}");
_writer.Indented($"{size} =l mul {size}, {type.ElementType.Size(_definitionTable)}");
_writer.Indented($"{size} =l mul {size}, {SizeOf(type.ElementType)}");
_writer.Indented($"{size} =l add {size}, 8");
return size;
}
@@ -250,9 +250,9 @@ public partial class QBEGenerator
}
else
{
if (complexType is CustomTypeNode customType)
if (complexType is StructTypeNode structType)
{
EmitMemcpy(value, destinationPointer, customType.Size(_definitionTable).ToString());
EmitMemcpy(value, destinationPointer, SizeOf(structType).ToString());
}
else
{
@@ -260,7 +260,8 @@ public partial class QBEGenerator
{
ArrayTypeNode arrayType => EmitArraySizeInBytes(arrayType, value),
CStringTypeNode => EmitCStringSizeInBytes(value),
NubStringTypeNode => EmitStringSizeInBytes(value),
StringTypeNode => EmitStringSizeInBytes(value),
InterfaceTypeNode => 16.ToString(),
_ => throw new ArgumentOutOfRangeException(nameof(source.Type))
};
@@ -309,8 +310,9 @@ public partial class QBEGenerator
{
ArrayTypeNode arrayType => EmitArraySizeInBytes(arrayType, value),
CStringTypeNode => EmitCStringSizeInBytes(value),
NubStringTypeNode => EmitStringSizeInBytes(value),
CustomTypeNode customType => customType.Size(_definitionTable).ToString(),
StringTypeNode => EmitStringSizeInBytes(value),
InterfaceTypeNode => 16.ToString(),
StructTypeNode structType => SizeOf(structType).ToString(),
_ => throw new ArgumentOutOfRangeException(nameof(source.Type))
};
@@ -339,9 +341,14 @@ public partial class QBEGenerator
};
}
if (complexType is CustomTypeNode customType)
if (complexType is StructTypeNode structType)
{
return CustomTypeName(customType.Name);
return StructTypeName(structType.Name);
}
if (complexType is InterfaceTypeNode interfaceType)
{
return InterfaceTypeName(interfaceType.Name);
}
return "l";
@@ -387,7 +394,7 @@ public partial class QBEGenerator
private void EmitStructTypeDefinition(StructNode structDef)
{
_writer.WriteLine($"type {CustomTypeName(structDef.Name)} = {{ ");
_writer.WriteLine($"type {StructTypeName(structDef.Name)} = {{ ");
var types = new Dictionary<string, string>();
@@ -422,9 +429,14 @@ public partial class QBEGenerator
};
}
if (complexType is CustomTypeNode customType)
if (complexType is StructTypeNode structType)
{
return CustomTypeName(customType.Name);
return StructTypeName(structType.Name);
}
if (complexType is InterfaceTypeNode interfaceType)
{
return InterfaceTypeName(interfaceType.Name);
}
return "l";
@@ -458,6 +470,93 @@ public partial class QBEGenerator
};
}
private static int SizeOf(TypeNode type)
{
return type switch
{
SimpleTypeNode simple => simple.StorageSize switch
{
StorageSize.Void => 0,
StorageSize.I8 or StorageSize.U8 => 1,
StorageSize.I16 or StorageSize.U16 => 2,
StorageSize.I32 or StorageSize.U32 or StorageSize.F32 => 4,
StorageSize.I64 or StorageSize.U64 or StorageSize.F64 => 8,
_ => throw new ArgumentOutOfRangeException(nameof(type), $"Unknown storage size: {simple.StorageSize}")
},
CStringTypeNode => 8,
StringTypeNode => 8,
ArrayTypeNode => 8,
StructTypeNode structType => CalculateStructSize(structType),
InterfaceTypeNode => 16,
_ => throw new ArgumentOutOfRangeException(nameof(type), $"Unknown type: {type.GetType()}")
};
}
private static int CalculateStructSize(StructTypeNode structType)
{
var offset = 0;
if (structType.InterfaceImplementations.Any())
{
offset = 8;
}
foreach (var field in structType.Fields)
{
var fieldAlignment = AlignmentOf(field);
offset = AlignTo(offset, fieldAlignment);
offset += SizeOf(field);
}
var structAlignment = CalculateStructAlignment(structType);
return AlignTo(offset, structAlignment);
}
private static int AlignmentOf(TypeNode type)
{
return type switch
{
SimpleTypeNode simple => simple.StorageSize switch
{
StorageSize.Void => 1,
StorageSize.I8 or StorageSize.U8 => 1,
StorageSize.I16 or StorageSize.U16 => 2,
StorageSize.I32 or StorageSize.U32 or StorageSize.F32 => 4,
StorageSize.I64 or StorageSize.U64 or StorageSize.F64 => 8,
_ => throw new ArgumentOutOfRangeException(nameof(type), $"Unknown storage size: {simple.StorageSize}")
},
CStringTypeNode => 8,
StringTypeNode => 8,
ArrayTypeNode => 8,
StructTypeNode structType => CalculateStructAlignment(structType),
InterfaceTypeNode => 8,
_ => throw new ArgumentOutOfRangeException(nameof(type), $"Unknown type: {type.GetType()}")
};
}
private static int CalculateStructAlignment(StructTypeNode structType)
{
var maxAlignment = 1;
if (structType.InterfaceImplementations.Any())
{
maxAlignment = Math.Max(maxAlignment, 8);
}
foreach (var field in structType.Fields)
{
var fieldAlignment = AlignmentOf(field);
maxAlignment = Math.Max(maxAlignment, fieldAlignment);
}
return maxAlignment;
}
private static int AlignTo(int offset, int alignment)
{
return (offset + alignment - 1) & ~(alignment - 1);
}
private int OffsetOf(StructNode structDef, string member)
{
var offset = 0;
@@ -474,10 +573,10 @@ public partial class QBEGenerator
return offset;
}
var fieldAlignment = field.Type.Alignment(_definitionTable);
var fieldAlignment = AlignmentOf(field.Type);
offset = TypeNode.AlignTo(offset, fieldAlignment);
offset += field.Type.Size(_definitionTable);
offset = AlignTo(offset, fieldAlignment);
offset += SizeOf(field.Type);
}
throw new UnreachableException($"Member '{member}' not found in struct");
@@ -515,7 +614,12 @@ public partial class QBEGenerator
return $"${funcDef.CallName}";
}
private string CustomTypeName(string name)
private string StructTypeName(string name)
{
return $":{name}";
}
private string InterfaceTypeName(string name)
{
return $":{name}";
}