This commit is contained in:
nub31
2025-06-14 18:34:33 +02:00
parent b261816043
commit 31bfa7a218

View File

@@ -55,7 +55,7 @@ public static class QBEGenerator
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();
}
@@ -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<string>();
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))