...
This commit is contained in:
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user