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