...
This commit is contained in:
@@ -21,7 +21,7 @@ public static class QBEGenerator
|
||||
private static Stack<string> _breakLabels = [];
|
||||
private static Stack<string> _continueLabels = [];
|
||||
private static Queue<(AnonymousFuncNode Func, string Name)> _anonymousFunctions = [];
|
||||
private static Stack<(string Name, string Pointer)> _variables = [];
|
||||
private static Stack<Variable> _variables = [];
|
||||
private static Stack<int> _variableScopes = [];
|
||||
private static int _variableIndex;
|
||||
private static int _labelIndex;
|
||||
@@ -298,14 +298,14 @@ public static class QBEGenerator
|
||||
throw new UnreachableException($"Member '{member}' not found in struct");
|
||||
}
|
||||
|
||||
private static bool IsLargeType(NubType type)
|
||||
private static bool IsPointerType(NubType type)
|
||||
{
|
||||
return type switch
|
||||
{
|
||||
NubArrayType => false,
|
||||
NubPointerType => false,
|
||||
NubPrimitiveType => false,
|
||||
NubStructType => true,
|
||||
NubArrayType => true,
|
||||
NubFixedArrayType => true,
|
||||
NubFuncType => false,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(type))
|
||||
@@ -387,7 +387,7 @@ public static class QBEGenerator
|
||||
_builder.AppendLine($"({string.Join(", ", parameterStrings)}) {{");
|
||||
_builder.AppendLine("@start");
|
||||
|
||||
List<(string Name, string Pointer)> parameterVars = [];
|
||||
List<Variable> parameterVars = [];
|
||||
|
||||
foreach (var parameter in parameters)
|
||||
{
|
||||
@@ -416,7 +416,7 @@ public static class QBEGenerator
|
||||
}
|
||||
}
|
||||
|
||||
parameterVars.Add((parameter.Name, parameterName));
|
||||
parameterVars.Add(new Variable(parameter.Name, parameterName).Assign());
|
||||
}
|
||||
|
||||
GenerateBlock(body, parameterVars);
|
||||
@@ -553,7 +553,7 @@ public static class QBEGenerator
|
||||
}
|
||||
}
|
||||
|
||||
private static void GenerateBlock(BlockNode block, List<(string Name, string Pointer)>? variables = null)
|
||||
private static void GenerateBlock(BlockNode block, List<Variable>? variables = null)
|
||||
{
|
||||
_variableScopes.Push(_variables.Count);
|
||||
if (variables != null)
|
||||
@@ -654,29 +654,17 @@ public static class QBEGenerator
|
||||
|
||||
private static void GenerateVariableDeclaration(VariableDeclarationNode variableDeclaration)
|
||||
{
|
||||
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);
|
||||
GenerateCopy(variableDeclaration.Value.Value.Type, value, pointer);
|
||||
}
|
||||
else
|
||||
{
|
||||
var pointerName = VarName();
|
||||
_variables.Push((variableDeclaration.Name, pointerName));
|
||||
}
|
||||
|
||||
_variables.Push((variableDeclaration.Name, pointer));
|
||||
var generatedName = VarName();
|
||||
_builder.AppendLine($" {generatedName} =l alloc8 {SizeOf(variableDeclaration.Type)}");
|
||||
_variables.Push(new Variable(variableDeclaration.Name, generatedName));
|
||||
}
|
||||
|
||||
private static void GenerateVariableAssignment(VariableAssignmentNode variableAssignment)
|
||||
{
|
||||
var value = GenerateExpression(variableAssignment.Value);
|
||||
var variable = _variables.Single(x => x.Name == variableAssignment.Identifier.Name);
|
||||
GenerateCopy(variableAssignment.Value.Type, value, variable.Pointer);
|
||||
GenerateCopy(variableAssignment.Value.Type, value, variable.GeneratedName);
|
||||
variable.Assign();
|
||||
}
|
||||
|
||||
private static void GenerateWhile(WhileNode whileStatement)
|
||||
@@ -706,7 +694,7 @@ public static class QBEGenerator
|
||||
{
|
||||
AddressOfNode addressOf => GenerateAddressOf(addressOf),
|
||||
AnonymousFuncNode anonymousFunc => GenerateAnonymousFunc(anonymousFunc),
|
||||
ArrayIndexAccessNode arrayIndex => GenerateArrayAccessIndex(arrayIndex),
|
||||
ArrayIndexAccessNode arrayIndex => GenerateArrayIndexAccessNode(arrayIndex),
|
||||
ArrayInitializerNode arrayInitializer => GenerateArrayInitializer(arrayInitializer),
|
||||
BinaryExpressionNode binaryExpression => GenerateBinaryExpression(binaryExpression),
|
||||
DereferenceNode dereference => GenerateDereference(dereference),
|
||||
@@ -725,10 +713,7 @@ public static class QBEGenerator
|
||||
{
|
||||
var name = $"$anon_func{++_anonymousFuncIndex}";
|
||||
_anonymousFunctions.Enqueue((anonymousFunc, name));
|
||||
var pointer = VarName();
|
||||
_builder.AppendLine($" {pointer} =l alloc8 8");
|
||||
_builder.AppendLine($" storel {name}, {pointer}");
|
||||
return pointer;
|
||||
return name;
|
||||
}
|
||||
|
||||
private static string GenerateArrayIndexPointer(ArrayIndexAccessNode arrayIndexAccess)
|
||||
@@ -737,40 +722,27 @@ public static class QBEGenerator
|
||||
var index = GenerateExpression(arrayIndexAccess.Index);
|
||||
GenerateArrayBoundsCheck(array, index);
|
||||
|
||||
switch (arrayIndexAccess.Array.Type)
|
||||
var elementType = arrayIndexAccess.Array.Type switch
|
||||
{
|
||||
case NubArrayType arrayType:
|
||||
{
|
||||
var firstItemPointerName = VarName();
|
||||
_builder.AppendLine($" {firstItemPointerName} =l add {array}, 8");
|
||||
var offsetPointerName = VarName();
|
||||
_builder.AppendLine($" {offsetPointerName} =l mul {index}, {SizeOf(arrayType.ElementType)}");
|
||||
var resultPointerName = VarName();
|
||||
_builder.AppendLine($" {resultPointerName} =l add {firstItemPointerName}, {offsetPointerName}");
|
||||
return resultPointerName;
|
||||
}
|
||||
case NubFixedArrayType fixedArrayType:
|
||||
{
|
||||
var firstItemPointerName = VarName();
|
||||
_builder.AppendLine($" {firstItemPointerName} =l add {array}, 8");
|
||||
var offsetPointerName = VarName();
|
||||
_builder.AppendLine($" {offsetPointerName} =l mul {index}, {SizeOf(fixedArrayType.ElementType)}");
|
||||
var resultPointerName = VarName();
|
||||
_builder.AppendLine($" {resultPointerName} =l add {firstItemPointerName}, {offsetPointerName}");
|
||||
return resultPointerName;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
NubArrayType arrayType => arrayType.ElementType,
|
||||
NubFixedArrayType fixedArrayType => fixedArrayType.ElementType,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
var firstItemPointerName = VarName();
|
||||
_builder.AppendLine($" {firstItemPointerName} =l add {array}, 8");
|
||||
var offsetPointerName = VarName();
|
||||
_builder.AppendLine($" {offsetPointerName} =l mul {index}, {SizeOf(elementType)}");
|
||||
var resultPointerName = VarName();
|
||||
_builder.AppendLine($" {resultPointerName} =l add {firstItemPointerName}, {offsetPointerName}");
|
||||
return resultPointerName;
|
||||
}
|
||||
|
||||
private static string GenerateArrayAccessIndex(ArrayIndexAccessNode arrayIndexAccess)
|
||||
private static string GenerateArrayIndexAccessNode(ArrayIndexAccessNode arrayIndexAccess)
|
||||
{
|
||||
var pointerName = GenerateArrayIndexPointer(arrayIndexAccess);
|
||||
|
||||
if (IsLargeType(arrayIndexAccess.Type))
|
||||
if (IsPointerType(arrayIndexAccess.Type))
|
||||
{
|
||||
return pointerName;
|
||||
}
|
||||
@@ -784,26 +756,26 @@ public static class QBEGenerator
|
||||
|
||||
private static void GenerateArrayBoundsCheck(string array, string index)
|
||||
{
|
||||
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_array_oob()");
|
||||
|
||||
_builder.AppendLine(notOobLabel);
|
||||
// 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_array_oob()");
|
||||
//
|
||||
// _builder.AppendLine(notOobLabel);
|
||||
}
|
||||
|
||||
private static string GenerateArrayInitializer(ArrayInitializerNode arrayInitializer)
|
||||
@@ -847,7 +819,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;
|
||||
return _variables.Single(x => x.Name == identifier.Name).GeneratedName;
|
||||
case MemberAccessNode memberAccess:
|
||||
return GenerateMemberAccessPointer(memberAccess);
|
||||
default:
|
||||
@@ -1085,16 +1057,22 @@ public static class QBEGenerator
|
||||
{
|
||||
if (_definitionTable.LookupFunc(identifier.Namespace.Or(_compilationUnit.Namespace), identifier.Name).TryGetValue(out var func))
|
||||
{
|
||||
var pointer = VarName();
|
||||
_builder.AppendLine($" {pointer} =l alloc8 8");
|
||||
_builder.AppendLine($" storel {FuncName(func)}, {pointer}");
|
||||
return pointer;
|
||||
return FuncName(func);
|
||||
}
|
||||
|
||||
if (!identifier.Namespace.HasValue)
|
||||
{
|
||||
var variable = _variables.Single(v => v.Name == identifier.Name);
|
||||
return GenerateDereference(identifier.Type, variable.Pointer);
|
||||
if (IsPointerType(identifier.Type))
|
||||
{
|
||||
return variable.GeneratedName;
|
||||
}
|
||||
else
|
||||
{
|
||||
var output = VarName();
|
||||
_builder.AppendLine($" {output} {QBEAssign(identifier.Type)} {QBELoad(identifier.Type)} {variable.GeneratedName}");
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
throw new UnreachableException();
|
||||
@@ -1257,7 +1235,7 @@ public static class QBEGenerator
|
||||
{
|
||||
var pointer = GenerateMemberAccessPointer(memberAccess);
|
||||
|
||||
if (IsLargeType(memberAccess.Type))
|
||||
if (IsPointerType(memberAccess.Type))
|
||||
{
|
||||
return pointer;
|
||||
}
|
||||
@@ -1324,35 +1302,24 @@ public static class QBEGenerator
|
||||
parameterStrings.Add($"{qbeType} {result}");
|
||||
}
|
||||
|
||||
string funcTarget;
|
||||
if (funcCall.Expression is IdentifierNode identifier && _definitionTable.LookupFunc(identifier.Namespace.Or(_compilationUnit.Namespace), identifier.Name).TryGetValue(out var func))
|
||||
{
|
||||
funcTarget = FuncName(func);
|
||||
}
|
||||
else
|
||||
{
|
||||
var funcPointerPointer = GenerateExpression(funcCall.Expression);
|
||||
var funcPointer = VarName();
|
||||
_builder.AppendLine($" {funcPointer} =l loadl {funcPointerPointer}");
|
||||
funcTarget = funcPointer;
|
||||
}
|
||||
var funcPointer = GenerateExpression(funcCall.Expression);
|
||||
|
||||
if (funcType.ReturnType is not NubVoidType)
|
||||
{
|
||||
var outputName = VarName();
|
||||
_builder.AppendLine($" {outputName} {QBEAssign(funcCall.Type)} call {funcTarget}({string.Join(", ", parameterStrings)})");
|
||||
_builder.AppendLine($" {outputName} {QBEAssign(funcCall.Type)} call {funcPointer}({string.Join(", ", parameterStrings)})");
|
||||
return outputName;
|
||||
}
|
||||
else
|
||||
{
|
||||
_builder.AppendLine($" call {funcTarget}({string.Join(", ", parameterStrings)})");
|
||||
_builder.AppendLine($" call {funcPointer}({string.Join(", ", parameterStrings)})");
|
||||
return "fuck";
|
||||
}
|
||||
}
|
||||
|
||||
private static void GenerateCopy(NubType type, string value, string destinationPointer)
|
||||
{
|
||||
if (IsLargeType(type))
|
||||
if (IsPointerType(type))
|
||||
{
|
||||
_builder.AppendLine($" blit {value}, {destinationPointer}, {SizeOf(type)}");
|
||||
}
|
||||
@@ -1361,18 +1328,17 @@ public static class QBEGenerator
|
||||
_builder.AppendLine($" {QBEStore(type)} {value}, {destinationPointer}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static string GenerateDereference(NubType type, string pointer)
|
||||
internal class Variable(string name, string generatedName)
|
||||
{
|
||||
public string Name { get; init; } = name;
|
||||
public string GeneratedName { get; init; } = generatedName;
|
||||
public bool Initialized { get; private set; }
|
||||
|
||||
public Variable Assign()
|
||||
{
|
||||
if (IsLargeType(type))
|
||||
{
|
||||
return pointer;
|
||||
}
|
||||
else
|
||||
{
|
||||
var result = VarName();
|
||||
_builder.AppendLine($" {result} {QBEAssign(type)} {QBELoad(type)} {pointer}");
|
||||
return result;
|
||||
}
|
||||
Initialized = true;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user