This commit is contained in:
nub31
2025-06-14 18:34:33 +02:00
parent 9d74a3716d
commit d57d95ec8e

View File

@@ -55,7 +55,7 @@ public static class QBEGenerator
foreach (var funcDef in _compilationUnit.Definitions.OfType<LocalFuncDefinitionNode>()) foreach (var funcDef in _compilationUnit.Definitions.OfType<LocalFuncDefinitionNode>())
{ {
GenerateFuncDefinition(FuncName(funcDef), funcDef.Parameters, funcDef.ReturnType, funcDef.Body, funcDef.Exported); GenerateFuncDefinition(FuncName(funcDef), funcDef.Parameters, funcDef.ReturnType, funcDef.Body, funcDef.Exported);
_builder.AppendLine(); _builder.AppendLine();
} }
@@ -130,7 +130,7 @@ public static class QBEGenerator
_ => throw new NotSupportedException($"'{type}' type cannot be used in store instructions") _ => throw new NotSupportedException($"'{type}' type cannot be used in store instructions")
}; };
} }
private static string QBELoad(NubType type) private static string QBELoad(NubType type)
{ {
return type switch return type switch
@@ -158,7 +158,7 @@ public static class QBEGenerator
_ => throw new NotSupportedException($"'{type}' type cannot be used in load instructions") _ => throw new NotSupportedException($"'{type}' type cannot be used in load instructions")
}; };
} }
private static string QBEAssign(NubType type) private static string QBEAssign(NubType type)
{ {
return type switch return type switch
@@ -193,26 +193,14 @@ public static class QBEGenerator
{ {
case NubPrimitiveType primitiveType: case NubPrimitiveType primitiveType:
{ {
switch (primitiveType.Kind) return primitiveType.Kind switch
{ {
case PrimitiveTypeKind.I64: PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 or PrimitiveTypeKind.F64 => 8,
case PrimitiveTypeKind.U64: PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 or PrimitiveTypeKind.F32 or PrimitiveTypeKind.Bool => 4,
case PrimitiveTypeKind.F64: PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 => 2,
return 8; PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 => 1,
case PrimitiveTypeKind.I32: _ => throw new ArgumentOutOfRangeException()
case PrimitiveTypeKind.U32: };
case PrimitiveTypeKind.F32:
return 4;
case PrimitiveTypeKind.I16:
case PrimitiveTypeKind.U16:
return 2;
case PrimitiveTypeKind.I8:
case PrimitiveTypeKind.U8:
case PrimitiveTypeKind.Bool:
return 1;
default:
throw new ArgumentOutOfRangeException();
}
} }
case NubStructType nubStructType: case NubStructType nubStructType:
{ {
@@ -247,47 +235,35 @@ public static class QBEGenerator
{ {
case NubPrimitiveType primitiveType: case NubPrimitiveType primitiveType:
{ {
switch (primitiveType.Kind) return primitiveType.Kind switch
{ {
case PrimitiveTypeKind.I64: PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 => 8,
case PrimitiveTypeKind.U64: PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 or PrimitiveTypeKind.Bool => 4,
return 8; PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 => 2,
case PrimitiveTypeKind.I32: PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 => 1,
case PrimitiveTypeKind.U32: PrimitiveTypeKind.F64 => 8,
return 4; PrimitiveTypeKind.F32 => 4,
case PrimitiveTypeKind.I16: _ => throw new ArgumentOutOfRangeException()
case PrimitiveTypeKind.U16: };
return 2;
case PrimitiveTypeKind.I8:
case PrimitiveTypeKind.U8:
case PrimitiveTypeKind.Bool:
return 1;
case PrimitiveTypeKind.F64:
return 8;
case PrimitiveTypeKind.F32:
return 4;
default:
throw new ArgumentOutOfRangeException();
}
} }
case NubStructType nubStructType: case NubStructType nubStructType:
{ {
var definition = _definitionTable.LookupStruct(nubStructType.Namespace, nubStructType.Name).GetValue(); var definition = _definitionTable.LookupStruct(nubStructType.Namespace, nubStructType.Name).GetValue();
var size = 0; var size = 0;
var maxAlignment = 1; var maxAlignment = 1;
foreach (var field in definition.Fields) foreach (var field in definition.Fields)
{ {
var fieldAlignment = AlignmentOf(field.Type); var fieldAlignment = AlignmentOf(field.Type);
maxAlignment = Math.Max(maxAlignment, fieldAlignment); maxAlignment = Math.Max(maxAlignment, fieldAlignment);
size = AlignTo(size, fieldAlignment); size = AlignTo(size, fieldAlignment);
size += SizeOf(field.Type); size += SizeOf(field.Type);
} }
size = AlignTo(size, maxAlignment); size = AlignTo(size, maxAlignment);
return size; return size;
} }
case NubPointerType: case NubPointerType:
@@ -298,8 +274,7 @@ public static class QBEGenerator
} }
case NubFixedArrayType nubFixedArrayType: case NubFixedArrayType nubFixedArrayType:
{ {
int elementSize = SizeOf(nubFixedArrayType.ElementType); return SizeOf(nubFixedArrayType.ElementType) * nubFixedArrayType.Capacity + 8;
return elementSize * nubFixedArrayType.Capacity + 8;
} }
default: default:
{ {
@@ -311,20 +286,20 @@ public static class QBEGenerator
private static int OffsetOf(StructDefinitionNode structDefinition, string member) private static int OffsetOf(StructDefinitionNode structDefinition, string member)
{ {
var offset = 0; var offset = 0;
foreach (var field in structDefinition.Fields) foreach (var field in structDefinition.Fields)
{ {
if (field.Name == member) if (field.Name == member)
{ {
return offset; return offset;
} }
var fieldAlignment = AlignmentOf(field.Type); var fieldAlignment = AlignmentOf(field.Type);
offset = AlignTo(offset, fieldAlignment); offset = AlignTo(offset, fieldAlignment);
offset += SizeOf(field.Type); offset += SizeOf(field.Type);
} }
throw new UnreachableException($"Member '{member}' not found in struct"); throw new UnreachableException($"Member '{member}' not found in struct");
} }
@@ -346,7 +321,7 @@ public static class QBEGenerator
{ {
_variables.Clear(); _variables.Clear();
_variableScopes.Clear(); _variableScopes.Clear();
if (exported) if (exported)
{ {
_builder.Append("export "); _builder.Append("export ");
@@ -418,7 +393,7 @@ public static class QBEGenerator
_builder.AppendLine("@start"); _builder.AppendLine("@start");
List<(string Name, string Pointer)> parameterVars = []; List<(string Name, string Pointer)> parameterVars = [];
foreach (var parameter in parameters) foreach (var parameter in parameters)
{ {
var parameterName = "%" + parameter.Name; var parameterName = "%" + parameter.Name;
@@ -445,7 +420,7 @@ public static class QBEGenerator
break; break;
} }
} }
parameterVars.Add((parameter.Name, parameterName)); parameterVars.Add((parameter.Name, parameterName));
} }
@@ -493,6 +468,7 @@ public static class QBEGenerator
}; };
_builder.Append(qbeType + ", "); _builder.Append(qbeType + ", ");
} }
_builder.AppendLine("}"); _builder.AppendLine("}");
} }
@@ -551,7 +527,7 @@ public static class QBEGenerator
{ {
var startName = VarName(); var startName = VarName();
_builder.AppendLine($" {startName} =l add {array}, 8"); _builder.AppendLine($" {startName} =l add {array}, 8");
var adjustedIndex = VarName(); var adjustedIndex = VarName();
_builder.AppendLine($" {adjustedIndex} =l mul {index}, {SizeOf(arrayType.ElementType)}"); _builder.AppendLine($" {adjustedIndex} =l mul {index}, {SizeOf(arrayType.ElementType)}");
@@ -565,7 +541,7 @@ public static class QBEGenerator
{ {
var startName = VarName(); var startName = VarName();
_builder.AppendLine($" {startName} =l add {array}, 8"); _builder.AppendLine($" {startName} =l add {array}, 8");
var adjustedIndex = VarName(); var adjustedIndex = VarName();
_builder.AppendLine($" {adjustedIndex} =l mul {index}, {SizeOf(fixedArrayType.ElementType)}"); _builder.AppendLine($" {adjustedIndex} =l mul {index}, {SizeOf(fixedArrayType.ElementType)}");
@@ -592,12 +568,12 @@ public static class QBEGenerator
_variables.Push(variable); _variables.Push(variable);
} }
} }
foreach (var statement in block.Statements.Where(_ => _codeIsReachable)) foreach (var statement in block.Statements.Where(_ => _codeIsReachable))
{ {
GenerateStatement(statement); GenerateStatement(statement);
} }
var count = _variableScopes.Pop(); var count = _variableScopes.Pop();
while (_variableScopes.Count > count) while (_variableScopes.Count > count)
{ {
@@ -654,13 +630,13 @@ public static class QBEGenerator
{ {
var structType = memberAssignment.MemberAccess.Expression.Type as NubStructType; var structType = memberAssignment.MemberAccess.Expression.Type as NubStructType;
Debug.Assert(structType != null); Debug.Assert(structType != null);
var structDefinition = _definitionTable.LookupStruct(structType.Namespace, structType.Name).GetValue(); var structDefinition = _definitionTable.LookupStruct(structType.Namespace, structType.Name).GetValue();
var offset = OffsetOf(structDefinition, memberAssignment.MemberAccess.Member); var offset = OffsetOf(structDefinition, memberAssignment.MemberAccess.Member);
var item = GenerateExpression(memberAssignment.MemberAccess.Expression); var item = GenerateExpression(memberAssignment.MemberAccess.Expression);
var pointer = VarName(); var pointer = VarName();
_builder.AppendLine($" {pointer} =l add {item}, {offset}"); _builder.AppendLine($" {pointer} =l add {item}, {offset}");
var value = GenerateExpression(memberAssignment.Value); var value = GenerateExpression(memberAssignment.Value);
@@ -686,7 +662,7 @@ public static class QBEGenerator
var type = variableDeclaration.ExplicitType.Value ?? variableDeclaration.Value.Value!.Type; var type = variableDeclaration.ExplicitType.Value ?? variableDeclaration.Value.Value!.Type;
var pointer = VarName(); var pointer = VarName();
_builder.AppendLine($" {pointer} =l alloc8 {SizeOf(type)}"); _builder.AppendLine($" {pointer} =l alloc8 {SizeOf(type)}");
if (variableDeclaration.Value.HasValue) if (variableDeclaration.Value.HasValue)
{ {
var value = GenerateExpression(variableDeclaration.Value.Value); var value = GenerateExpression(variableDeclaration.Value.Value);
@@ -697,10 +673,10 @@ public static class QBEGenerator
var pointerName = VarName(); var pointerName = VarName();
_variables.Push((variableDeclaration.Name, pointerName)); _variables.Push((variableDeclaration.Name, pointerName));
} }
_variables.Push((variableDeclaration.Name, pointer)); _variables.Push((variableDeclaration.Name, pointer));
} }
private static void GenerateVariableAssignment(VariableAssignmentNode variableAssignment) private static void GenerateVariableAssignment(VariableAssignmentNode variableAssignment)
{ {
var value = GenerateExpression(variableAssignment.Value); var value = GenerateExpression(variableAssignment.Value);
@@ -765,7 +741,7 @@ public static class QBEGenerator
var array = GenerateExpression(arrayIndexAccess.Array); var array = GenerateExpression(arrayIndexAccess.Array);
var index = GenerateExpression(arrayIndexAccess.Index); var index = GenerateExpression(arrayIndexAccess.Index);
GenerateArrayBoundsCheck(array, index); GenerateArrayBoundsCheck(array, index);
switch (arrayIndexAccess.Array.Type) switch (arrayIndexAccess.Array.Type)
{ {
case NubArrayType arrayType: case NubArrayType arrayType:
@@ -794,7 +770,7 @@ public static class QBEGenerator
} }
} }
} }
private static string GenerateArrayAccessIndex(ArrayIndexAccessNode arrayIndexAccess) private static string GenerateArrayAccessIndex(ArrayIndexAccessNode arrayIndexAccess)
{ {
var pointerName = GenerateArrayIndexPointer(arrayIndexAccess); var pointerName = GenerateArrayIndexPointer(arrayIndexAccess);
@@ -807,7 +783,7 @@ public static class QBEGenerator
{ {
var outputName = VarName(); var outputName = VarName();
_builder.AppendLine($" {outputName} {QBEAssign(arrayIndexAccess.Type)} {QBELoad(arrayIndexAccess.Type)} {pointerName}"); _builder.AppendLine($" {outputName} {QBEAssign(arrayIndexAccess.Type)} {QBELoad(arrayIndexAccess.Type)} {pointerName}");
return outputName; return outputName;
} }
} }
@@ -815,23 +791,23 @@ public static class QBEGenerator
{ {
var countName = VarName(); var countName = VarName();
_builder.AppendLine($" {countName} =l loadl {array}"); _builder.AppendLine($" {countName} =l loadl {array}");
var isNegativeName = VarName(); var isNegativeName = VarName();
_builder.AppendLine($" {isNegativeName} =w csltl {index}, 0"); _builder.AppendLine($" {isNegativeName} =w csltl {index}, 0");
var isOobName = VarName(); var isOobName = VarName();
_builder.AppendLine($" {isOobName} =w csgel {index}, {countName}"); _builder.AppendLine($" {isOobName} =w csgel {index}, {countName}");
var anyOobName = VarName(); var anyOobName = VarName();
_builder.AppendLine($" {anyOobName} =w or {isNegativeName}, {isOobName}"); _builder.AppendLine($" {anyOobName} =w or {isNegativeName}, {isOobName}");
var oobLabel = LabelName(); var oobLabel = LabelName();
var notOobLabel = LabelName(); var notOobLabel = LabelName();
_builder.AppendLine($" jnz {anyOobName}, {oobLabel}, {notOobLabel}"); _builder.AppendLine($" jnz {anyOobName}, {oobLabel}, {notOobLabel}");
_builder.AppendLine(oobLabel); _builder.AppendLine(oobLabel);
_builder.AppendLine($" call $nub_panic(l $oob_message, l {OutOfBoundsMessage.Length})"); _builder.AppendLine($" call $nub_panic(l $oob_message, l {OutOfBoundsMessage.Length})");
_builder.AppendLine(notOobLabel); _builder.AppendLine(notOobLabel);
} }
@@ -875,6 +851,7 @@ public static class QBEGenerator
{ {
throw new NotSupportedException("There is nothing to address in another namespace"); throw new NotSupportedException("There is nothing to address in another namespace");
} }
return _variables.Single(x => x.Name == identifier.Name).Pointer; return _variables.Single(x => x.Name == identifier.Name).Pointer;
case MemberAccessNode memberAccess: case MemberAccessNode memberAccess:
return GenerateMemberAccessPointer(memberAccess); return GenerateMemberAccessPointer(memberAccess);
@@ -1149,7 +1126,7 @@ public static class QBEGenerator
var bits = BitConverter.DoubleToInt64Bits(value); var bits = BitConverter.DoubleToInt64Bits(value);
return bits.ToString(); return bits.ToString();
} }
if (literal.Type.IsFloat32) if (literal.Type.IsFloat32)
{ {
var value = float.Parse(literal.Literal, CultureInfo.InvariantCulture); var value = float.Parse(literal.Literal, CultureInfo.InvariantCulture);
@@ -1169,11 +1146,11 @@ public static class QBEGenerator
} }
} }
private static string GenerateStructInitializer(StructInitializerNode structInitializer) private static string GenerateStructInitializer(StructInitializerNode structInitializer)
{ {
var structDefinition = _definitionTable.LookupStruct(structInitializer.StructType.Namespace, structInitializer.StructType.Name).GetValue(); var structDefinition = _definitionTable.LookupStruct(structInitializer.StructType.Namespace, structInitializer.StructType.Name).GetValue();
var structVar = VarName(); var structVar = VarName();
var size = SizeOf(structInitializer.StructType); var size = SizeOf(structInitializer.StructType);
_builder.AppendLine($" {structVar} =l alloc8 {size}"); _builder.AppendLine($" {structVar} =l alloc8 {size}");
@@ -1285,7 +1262,7 @@ public static class QBEGenerator
private static string GenerateMemberAccess(MemberAccessNode memberAccess) private static string GenerateMemberAccess(MemberAccessNode memberAccess)
{ {
var pointer = GenerateMemberAccessPointer(memberAccess); var pointer = GenerateMemberAccessPointer(memberAccess);
if (IsLargeType(memberAccess.Type)) if (IsLargeType(memberAccess.Type))
{ {
return pointer; return pointer;
@@ -1303,12 +1280,12 @@ public static class QBEGenerator
var totalSize = SizeOf(fixedArrayInitializer.Type); var totalSize = SizeOf(fixedArrayInitializer.Type);
var outputName = VarName(); var outputName = VarName();
_builder.AppendLine($" {outputName} =l alloc8 {totalSize}"); _builder.AppendLine($" {outputName} =l alloc8 {totalSize}");
_builder.AppendLine($" storel {fixedArrayInitializer.Capacity}, {outputName}"); _builder.AppendLine($" storel {fixedArrayInitializer.Capacity}, {outputName}");
var dataPtr = VarName(); var dataPtr = VarName();
_builder.AppendLine($" {dataPtr} =l add {outputName}, 8"); _builder.AppendLine($" {dataPtr} =l add {outputName}, 8");
var dataSize = totalSize - 8; var dataSize = totalSize - 8;
_builder.AppendLine($" call $nub_memset(l {dataPtr}, w 0, l {dataSize})"); _builder.AppendLine($" call $nub_memset(l {dataPtr}, w 0, l {dataSize})");
@@ -1318,7 +1295,7 @@ public static class QBEGenerator
private static string GenerateFuncCall(FuncCallNode funcCall) private static string GenerateFuncCall(FuncCallNode funcCall)
{ {
var funcType = (NubFuncType)funcCall.Expression.Type; var funcType = (NubFuncType)funcCall.Expression.Type;
var parameterStrings = new List<string>(); var parameterStrings = new List<string>();
for (var i = 0; i < funcCall.Parameters.Count; i++) for (var i = 0; i < funcCall.Parameters.Count; i++)
@@ -1365,7 +1342,7 @@ public static class QBEGenerator
_builder.AppendLine($" {funcPointer} =l loadl {funcPointerPointer}"); _builder.AppendLine($" {funcPointer} =l loadl {funcPointerPointer}");
funcTarget = funcPointer; funcTarget = funcPointer;
} }
if (funcType.ReturnType is not NubVoidType) if (funcType.ReturnType is not NubVoidType)
{ {
var outputName = VarName(); var outputName = VarName();
@@ -1390,7 +1367,7 @@ public static class QBEGenerator
_builder.AppendLine($" {QBEStore(type)} {value}, {destinationPointer}"); _builder.AppendLine($" {QBEStore(type)} {value}, {destinationPointer}");
} }
} }
private static string GenerateDereference(NubType type, string pointer) private static string GenerateDereference(NubType type, string pointer)
{ {
if (IsLargeType(type)) if (IsLargeType(type))