...
This commit is contained in:
@@ -141,79 +141,6 @@ public static class QBEGenerator
|
|||||||
return $":{@namespace}_{name}";
|
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)
|
private static void EmitStore(NubType type, string value, string destination)
|
||||||
{
|
{
|
||||||
string store;
|
string store;
|
||||||
@@ -279,7 +206,7 @@ public static class QBEGenerator
|
|||||||
{
|
{
|
||||||
var size = TmpName();
|
var size = TmpName();
|
||||||
_writer.Indented($"{size} =l loadl {array}");
|
_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");
|
_writer.Indented($"{size} =l add {size}, 8");
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@@ -345,7 +272,7 @@ public static class QBEGenerator
|
|||||||
{
|
{
|
||||||
if (complexType is NubCustomType customType)
|
if (complexType is NubCustomType customType)
|
||||||
{
|
{
|
||||||
EmitMemcpy(value, destinationPointer, SizeOf(customType).ToString());
|
EmitMemcpy(value, destinationPointer, customType.Size(_definitionTable).ToString());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -403,7 +330,7 @@ public static class QBEGenerator
|
|||||||
NubArrayType arrayType => EmitArraySizeInBytes(arrayType, value),
|
NubArrayType arrayType => EmitArraySizeInBytes(arrayType, value),
|
||||||
NubCStringType => EmitCStringSizeInBytes(value),
|
NubCStringType => EmitCStringSizeInBytes(value),
|
||||||
NubStringType => EmitStringSizeInBytes(value),
|
NubStringType => EmitStringSizeInBytes(value),
|
||||||
NubCustomType customType => SizeOf(customType).ToString(),
|
NubCustomType customType => customType.Size(_definitionTable).ToString(),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(source.Type))
|
_ => throw new ArgumentOutOfRangeException(nameof(source.Type))
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -575,10 +502,10 @@ public static class QBEGenerator
|
|||||||
case BoundAssignmentNode assignment:
|
case BoundAssignmentNode assignment:
|
||||||
EmitAssignment(assignment);
|
EmitAssignment(assignment);
|
||||||
break;
|
break;
|
||||||
case BoundBreakNode @break:
|
case BoundBreakNode:
|
||||||
EmitBreak();
|
EmitBreak();
|
||||||
break;
|
break;
|
||||||
case BoundContinueNode @continue:
|
case BoundContinueNode:
|
||||||
EmitContinue();
|
EmitContinue();
|
||||||
break;
|
break;
|
||||||
case BoundIfNode ifStatement:
|
case BoundIfNode ifStatement:
|
||||||
@@ -754,10 +681,12 @@ public static class QBEGenerator
|
|||||||
var array = EmitUnwrap(EmitExpression(arrayIndexAccess.Target));
|
var array = EmitUnwrap(EmitExpression(arrayIndexAccess.Target));
|
||||||
var index = EmitUnwrap(EmitExpression(arrayIndexAccess.Index));
|
var index = EmitUnwrap(EmitExpression(arrayIndexAccess.Index));
|
||||||
|
|
||||||
|
EmitArrayBoundsCheck(array, index);
|
||||||
|
|
||||||
var elementType = ((NubArrayType)arrayIndexAccess.Target.Type).ElementType;
|
var elementType = ((NubArrayType)arrayIndexAccess.Target.Type).ElementType;
|
||||||
|
|
||||||
var pointer = TmpName();
|
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 {pointer}, 8");
|
||||||
_writer.Indented($"{pointer} =l add {array}, {pointer}");
|
_writer.Indented($"{pointer} =l add {array}, {pointer}");
|
||||||
return new Val(pointer, arrayIndexAccess.Type, ValKind.Pointer);
|
return new Val(pointer, arrayIndexAccess.Type, ValKind.Pointer);
|
||||||
@@ -790,7 +719,7 @@ public static class QBEGenerator
|
|||||||
private static Val EmitArrayInitializer(BoundArrayInitializerNode arrayInitializer)
|
private static Val EmitArrayInitializer(BoundArrayInitializerNode arrayInitializer)
|
||||||
{
|
{
|
||||||
var capacity = EmitUnwrap(EmitExpression(arrayInitializer.Capacity));
|
var capacity = EmitUnwrap(EmitExpression(arrayInitializer.Capacity));
|
||||||
var elementSize = SizeOf(arrayInitializer.ElementType);
|
var elementSize = arrayInitializer.ElementType.Size(_definitionTable);
|
||||||
|
|
||||||
var capacityInBytes = TmpName();
|
var capacityInBytes = TmpName();
|
||||||
_writer.Indented($"{capacityInBytes} =l mul {capacity}, {elementSize}");
|
_writer.Indented($"{capacityInBytes} =l mul {capacity}, {elementSize}");
|
||||||
@@ -816,7 +745,11 @@ public static class QBEGenerator
|
|||||||
private static Val EmitAddressOf(BoundAddressOfNode addressOf)
|
private static Val EmitAddressOf(BoundAddressOfNode addressOf)
|
||||||
{
|
{
|
||||||
var value = EmitExpression(addressOf.Expression);
|
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);
|
return new Val(value.Name, addressOf.Type, ValKind.Direct);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1033,7 +966,7 @@ public static class QBEGenerator
|
|||||||
if (destination == null)
|
if (destination == null)
|
||||||
{
|
{
|
||||||
destination = TmpName();
|
destination = TmpName();
|
||||||
var size = SizeOf(structInitializer.StructType);
|
var size = structInitializer.StructType.Size(_definitionTable);
|
||||||
_writer.Indented($"{destination} =l alloc8 {size}");
|
_writer.Indented($"{destination} =l alloc8 {size}");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1177,6 +1110,26 @@ public static class QBEGenerator
|
|||||||
_ => throw new ArgumentOutOfRangeException()
|
_ => 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)
|
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");
|
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 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 override bool Equals(object? obj) => obj is NubType other && Equals(other);
|
||||||
|
|
||||||
public abstract bool Equals(NubType? other);
|
public abstract bool Equals(NubType? other);
|
||||||
@@ -68,7 +74,7 @@ public abstract class NubSimpleType : NubType
|
|||||||
{
|
{
|
||||||
public abstract StorageSize StorageSize { get; }
|
public abstract StorageSize StorageSize { get; }
|
||||||
|
|
||||||
public override int Alignment(BoundDefinitionTable definitionTable)
|
public override int Size(BoundDefinitionTable definitionTable)
|
||||||
{
|
{
|
||||||
return StorageSize switch
|
return StorageSize switch
|
||||||
{
|
{
|
||||||
@@ -79,6 +85,11 @@ public abstract class NubSimpleType : NubType
|
|||||||
_ => throw new ArgumentOutOfRangeException(nameof(StorageSize))
|
_ => throw new ArgumentOutOfRangeException(nameof(StorageSize))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override int Alignment(BoundDefinitionTable definitionTable)
|
||||||
|
{
|
||||||
|
return Size(definitionTable);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Simple types
|
#region Simple types
|
||||||
@@ -196,7 +207,8 @@ public abstract class NubComplexType : NubType;
|
|||||||
|
|
||||||
public class NubCStringType : NubComplexType
|
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 string ToString() => "cstring";
|
||||||
public override bool Equals(NubType? other) => other is NubCStringType;
|
public override bool Equals(NubType? other) => other is NubCStringType;
|
||||||
@@ -205,7 +217,8 @@ public class NubCStringType : NubComplexType
|
|||||||
|
|
||||||
public class NubStringType : 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 string ToString() => "string";
|
||||||
public override bool Equals(NubType? other) => other is NubStringType;
|
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}");
|
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)
|
public override int Alignment(BoundDefinitionTable definitionTable)
|
||||||
{
|
{
|
||||||
switch (Kind(definitionTable))
|
switch (Kind(definitionTable))
|
||||||
@@ -260,7 +303,8 @@ public class NubArrayType(NubType elementType) : NubComplexType
|
|||||||
{
|
{
|
||||||
public NubType ElementType { get; } = elementType;
|
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;
|
public override string ToString() => "[]" + ElementType;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user