...
This commit is contained in:
@@ -141,79 +141,6 @@ public static class QBEGenerator
|
||||
return $":{@namespace}_{name}";
|
||||
}
|
||||
|
||||
private static int AlignTo(int offset, int alignment)
|
||||
{
|
||||
return (offset + alignment - 1) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
private static int SizeOf(NubType type)
|
||||
{
|
||||
if (type.IsSimpleType(out var simpleType, out var complexType))
|
||||
{
|
||||
return simpleType.StorageSize switch
|
||||
{
|
||||
StorageSize.I64 or StorageSize.U64 or StorageSize.F64 => 8,
|
||||
StorageSize.I32 or StorageSize.U32 or StorageSize.F32 => 4,
|
||||
StorageSize.I16 or StorageSize.U16 => 2,
|
||||
StorageSize.I8 or StorageSize.U8 => 1,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(simpleType.StorageSize))
|
||||
};
|
||||
}
|
||||
|
||||
// Only custom types such as structs/traits have known sizes for now. For objects other than custom types, we store pointers
|
||||
if (complexType is not NubCustomType customType)
|
||||
{
|
||||
return 8;
|
||||
}
|
||||
|
||||
switch (customType.Kind(_definitionTable))
|
||||
{
|
||||
case CustomTypeKind.Struct:
|
||||
{
|
||||
var structDef = _definitionTable.LookupStruct(customType.Namespace, customType.Name);
|
||||
var size = 0;
|
||||
var maxAlignment = 1;
|
||||
|
||||
foreach (var field in structDef.Fields)
|
||||
{
|
||||
var fieldAlignment = field.Type.Alignment(_definitionTable);
|
||||
maxAlignment = Math.Max(maxAlignment, fieldAlignment);
|
||||
|
||||
size = AlignTo(size, fieldAlignment);
|
||||
size += SizeOf(field.Type);
|
||||
}
|
||||
|
||||
return AlignTo(size, maxAlignment);
|
||||
}
|
||||
case CustomTypeKind.Trait:
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
private static int OffsetOf(BoundStructNode structDefinition, string member)
|
||||
{
|
||||
var offset = 0;
|
||||
|
||||
foreach (var field in structDefinition.Fields)
|
||||
{
|
||||
if (field.Name == member)
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
|
||||
var fieldAlignment = field.Type.Alignment(_definitionTable);
|
||||
|
||||
offset = AlignTo(offset, fieldAlignment);
|
||||
offset += SizeOf(field.Type);
|
||||
}
|
||||
|
||||
throw new UnreachableException($"Member '{member}' not found in struct");
|
||||
}
|
||||
|
||||
private static void EmitStore(NubType type, string value, string destination)
|
||||
{
|
||||
string store;
|
||||
@@ -279,7 +206,7 @@ public static class QBEGenerator
|
||||
{
|
||||
var size = TmpName();
|
||||
_writer.Indented($"{size} =l loadl {array}");
|
||||
_writer.Indented($"{size} =l mul {size}, {SizeOf(type.ElementType)}");
|
||||
_writer.Indented($"{size} =l mul {size}, {type.ElementType.Size(_definitionTable)}");
|
||||
_writer.Indented($"{size} =l add {size}, 8");
|
||||
return size;
|
||||
}
|
||||
@@ -345,7 +272,7 @@ public static class QBEGenerator
|
||||
{
|
||||
if (complexType is NubCustomType customType)
|
||||
{
|
||||
EmitMemcpy(value, destinationPointer, SizeOf(customType).ToString());
|
||||
EmitMemcpy(value, destinationPointer, customType.Size(_definitionTable).ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -403,7 +330,7 @@ public static class QBEGenerator
|
||||
NubArrayType arrayType => EmitArraySizeInBytes(arrayType, value),
|
||||
NubCStringType => EmitCStringSizeInBytes(value),
|
||||
NubStringType => EmitStringSizeInBytes(value),
|
||||
NubCustomType customType => SizeOf(customType).ToString(),
|
||||
NubCustomType customType => customType.Size(_definitionTable).ToString(),
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(source.Type))
|
||||
};
|
||||
|
||||
@@ -575,10 +502,10 @@ public static class QBEGenerator
|
||||
case BoundAssignmentNode assignment:
|
||||
EmitAssignment(assignment);
|
||||
break;
|
||||
case BoundBreakNode @break:
|
||||
case BoundBreakNode:
|
||||
EmitBreak();
|
||||
break;
|
||||
case BoundContinueNode @continue:
|
||||
case BoundContinueNode:
|
||||
EmitContinue();
|
||||
break;
|
||||
case BoundIfNode ifStatement:
|
||||
@@ -754,10 +681,12 @@ public static class QBEGenerator
|
||||
var array = EmitUnwrap(EmitExpression(arrayIndexAccess.Target));
|
||||
var index = EmitUnwrap(EmitExpression(arrayIndexAccess.Index));
|
||||
|
||||
EmitArrayBoundsCheck(array, index);
|
||||
|
||||
var elementType = ((NubArrayType)arrayIndexAccess.Target.Type).ElementType;
|
||||
|
||||
var pointer = TmpName();
|
||||
_writer.Indented($"{pointer} =l mul {index}, {SizeOf(elementType)}");
|
||||
_writer.Indented($"{pointer} =l mul {index}, {elementType.Size(_definitionTable)}");
|
||||
_writer.Indented($"{pointer} =l add {pointer}, 8");
|
||||
_writer.Indented($"{pointer} =l add {array}, {pointer}");
|
||||
return new Val(pointer, arrayIndexAccess.Type, ValKind.Pointer);
|
||||
@@ -790,7 +719,7 @@ public static class QBEGenerator
|
||||
private static Val EmitArrayInitializer(BoundArrayInitializerNode arrayInitializer)
|
||||
{
|
||||
var capacity = EmitUnwrap(EmitExpression(arrayInitializer.Capacity));
|
||||
var elementSize = SizeOf(arrayInitializer.ElementType);
|
||||
var elementSize = arrayInitializer.ElementType.Size(_definitionTable);
|
||||
|
||||
var capacityInBytes = TmpName();
|
||||
_writer.Indented($"{capacityInBytes} =l mul {capacity}, {elementSize}");
|
||||
@@ -816,7 +745,11 @@ public static class QBEGenerator
|
||||
private static Val EmitAddressOf(BoundAddressOfNode addressOf)
|
||||
{
|
||||
var value = EmitExpression(addressOf.Expression);
|
||||
Debug.Assert(value.Kind == ValKind.Pointer);
|
||||
if (value.Kind != ValKind.Pointer)
|
||||
{
|
||||
throw new UnreachableException("Tried to take address of non-pointer type. This should have been causht in the type checker");
|
||||
}
|
||||
|
||||
return new Val(value.Name, addressOf.Type, ValKind.Direct);
|
||||
}
|
||||
|
||||
@@ -1033,7 +966,7 @@ public static class QBEGenerator
|
||||
if (destination == null)
|
||||
{
|
||||
destination = TmpName();
|
||||
var size = SizeOf(structInitializer.StructType);
|
||||
var size = structInitializer.StructType.Size(_definitionTable);
|
||||
_writer.Indented($"{destination} =l alloc8 {size}");
|
||||
}
|
||||
|
||||
@@ -1177,6 +1110,26 @@ public static class QBEGenerator
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
private static int OffsetOf(BoundStructNode structDefinition, string member)
|
||||
{
|
||||
var offset = 0;
|
||||
|
||||
foreach (var field in structDefinition.Fields)
|
||||
{
|
||||
if (field.Name == member)
|
||||
{
|
||||
return offset;
|
||||
}
|
||||
|
||||
var fieldAlignment = field.Type.Alignment(_definitionTable);
|
||||
|
||||
offset = NubType.AlignTo(offset, fieldAlignment);
|
||||
offset += field.Type.Size(_definitionTable);
|
||||
}
|
||||
|
||||
throw new UnreachableException($"Member '{member}' not found in struct");
|
||||
}
|
||||
}
|
||||
|
||||
internal class StringLiteral(string value, string name)
|
||||
|
||||
@@ -37,8 +37,14 @@ public abstract class NubType : IEquatable<NubType>
|
||||
throw new ArgumentException($"Type {this} is not a simple type, not a compex type");
|
||||
}
|
||||
|
||||
public abstract int Size(BoundDefinitionTable definitionTable);
|
||||
public abstract int Alignment(BoundDefinitionTable definitionTable);
|
||||
|
||||
public static int AlignTo(int offset, int alignment)
|
||||
{
|
||||
return (offset + alignment - 1) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
public override bool Equals(object? obj) => obj is NubType other && Equals(other);
|
||||
|
||||
public abstract bool Equals(NubType? other);
|
||||
@@ -68,7 +74,7 @@ public abstract class NubSimpleType : NubType
|
||||
{
|
||||
public abstract StorageSize StorageSize { get; }
|
||||
|
||||
public override int Alignment(BoundDefinitionTable definitionTable)
|
||||
public override int Size(BoundDefinitionTable definitionTable)
|
||||
{
|
||||
return StorageSize switch
|
||||
{
|
||||
@@ -79,6 +85,11 @@ public abstract class NubSimpleType : NubType
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(StorageSize))
|
||||
};
|
||||
}
|
||||
|
||||
public override int Alignment(BoundDefinitionTable definitionTable)
|
||||
{
|
||||
return Size(definitionTable);
|
||||
}
|
||||
}
|
||||
|
||||
#region Simple types
|
||||
@@ -196,7 +207,8 @@ public abstract class NubComplexType : NubType;
|
||||
|
||||
public class NubCStringType : NubComplexType
|
||||
{
|
||||
public override int Alignment(BoundDefinitionTable definitionTable) => 8;
|
||||
public override int Size(BoundDefinitionTable definitionTable) => 8;
|
||||
public override int Alignment(BoundDefinitionTable definitionTable) => Size(definitionTable);
|
||||
|
||||
public override string ToString() => "cstring";
|
||||
public override bool Equals(NubType? other) => other is NubCStringType;
|
||||
@@ -205,7 +217,8 @@ public class NubCStringType : NubComplexType
|
||||
|
||||
public class NubStringType : NubComplexType
|
||||
{
|
||||
public override int Alignment(BoundDefinitionTable definitionTable) => 8;
|
||||
public override int Size(BoundDefinitionTable definitionTable) => 8;
|
||||
public override int Alignment(BoundDefinitionTable definitionTable) => Size(definitionTable);
|
||||
|
||||
public override string ToString() => "string";
|
||||
public override bool Equals(NubType? other) => other is NubStringType;
|
||||
@@ -232,6 +245,36 @@ public class NubCustomType(string @namespace, string name) : NubComplexType
|
||||
throw new ArgumentException($"Definition table does not have any type information for {this}");
|
||||
}
|
||||
|
||||
public override int Size(BoundDefinitionTable definitionTable)
|
||||
{
|
||||
switch (Kind(definitionTable))
|
||||
{
|
||||
case CustomTypeKind.Struct:
|
||||
{
|
||||
var structDef = definitionTable.LookupStruct(Namespace, Name);
|
||||
var size = 0;
|
||||
var maxAlignment = 1;
|
||||
|
||||
foreach (var field in structDef.Fields)
|
||||
{
|
||||
var fieldAlignment = field.Type.Alignment(definitionTable);
|
||||
maxAlignment = Math.Max(maxAlignment, fieldAlignment);
|
||||
|
||||
size = AlignTo(size, fieldAlignment);
|
||||
size += field.Type.Size(definitionTable);
|
||||
}
|
||||
|
||||
return AlignTo(size, maxAlignment);
|
||||
}
|
||||
case CustomTypeKind.Trait:
|
||||
{
|
||||
return 16;
|
||||
}
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
public override int Alignment(BoundDefinitionTable definitionTable)
|
||||
{
|
||||
switch (Kind(definitionTable))
|
||||
@@ -260,7 +303,8 @@ public class NubArrayType(NubType elementType) : NubComplexType
|
||||
{
|
||||
public NubType ElementType { get; } = elementType;
|
||||
|
||||
public override int Alignment(BoundDefinitionTable definitionTable) => 8;
|
||||
public override int Size(BoundDefinitionTable definitionTable) => 8;
|
||||
public override int Alignment(BoundDefinitionTable definitionTable) => Size(definitionTable);
|
||||
|
||||
public override string ToString() => "[]" + ElementType;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user