...
This commit is contained in:
@@ -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}";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user