...
This commit is contained in:
@@ -477,8 +477,8 @@ public static class QBEGenerator
|
||||
{
|
||||
switch (statement)
|
||||
{
|
||||
case BoundArrayIndexAssignmentNode arrayIndexAssignment:
|
||||
EmitArrayIndexAssignment(arrayIndexAssignment);
|
||||
case BoundAssignmentNode assignment:
|
||||
EmitAssignment(assignment);
|
||||
break;
|
||||
case BoundBreakNode:
|
||||
EmitBreak();
|
||||
@@ -486,15 +486,9 @@ public static class QBEGenerator
|
||||
case BoundContinueNode:
|
||||
EmitContinue();
|
||||
break;
|
||||
case BoundDereferenceAssignmentNode dereferenceAssignment:
|
||||
EmitDereferenceAssignment(dereferenceAssignment);
|
||||
break;
|
||||
case BoundIfNode ifStatement:
|
||||
EmitIf(ifStatement);
|
||||
break;
|
||||
case BoundMemberAssignmentNode memberAssignment:
|
||||
EmitMemberAssignment(memberAssignment);
|
||||
break;
|
||||
case BoundReturnNode @return:
|
||||
EmitReturn(@return);
|
||||
break;
|
||||
@@ -504,9 +498,6 @@ public static class QBEGenerator
|
||||
case BoundVariableDeclarationNode variableDeclaration:
|
||||
EmitVariableDeclaration(variableDeclaration);
|
||||
break;
|
||||
case BoundVariableAssignmentNode variableAssignment:
|
||||
EmitVariableAssignment(variableAssignment);
|
||||
break;
|
||||
case BoundWhileNode whileStatement:
|
||||
EmitWhile(whileStatement);
|
||||
break;
|
||||
@@ -515,30 +506,16 @@ public static class QBEGenerator
|
||||
}
|
||||
}
|
||||
|
||||
private static void EmitArrayIndexAssignment(BoundArrayIndexAssignmentNode arrayIndexAssignment)
|
||||
private static void EmitAssignment(BoundAssignmentNode assignment)
|
||||
{
|
||||
var array = EmitUnwrap(EmitExpression(arrayIndexAssignment.ArrayIndexAccess.Array));
|
||||
var index = EmitUnwrap(EmitExpression(arrayIndexAssignment.ArrayIndexAccess.Index));
|
||||
EmitArrayBoundsCheck(array, index);
|
||||
var value = EmitUnwrap(EmitExpression(arrayIndexAssignment.Value));
|
||||
|
||||
switch (arrayIndexAssignment.ArrayIndexAccess.Array.Type)
|
||||
var expression = EmitExpression(assignment.Expression);
|
||||
if (expression.Kind != ValKind.Pointer)
|
||||
{
|
||||
case NubArrayType arrayType:
|
||||
{
|
||||
var pointer = VarName();
|
||||
_builder.AppendLine($" {pointer} =l mul {index}, {SizeOf(arrayType.ElementType)}");
|
||||
_builder.AppendLine($" {pointer} =l add {pointer}, 8");
|
||||
_builder.AppendLine($" {pointer} =l add {array}, {pointer}");
|
||||
|
||||
EmitCopy(arrayType.ElementType, value, pointer);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
throw new UnreachableException();
|
||||
}
|
||||
|
||||
var value = EmitUnwrap(EmitExpression(assignment.Value));
|
||||
EmitCopy(assignment.Value.Type, value, expression.Name);
|
||||
}
|
||||
|
||||
private static void EmitBlock(BoundBlockNode block, List<Variable>? variables = null)
|
||||
@@ -578,13 +555,6 @@ public static class QBEGenerator
|
||||
_codeIsReachable = false;
|
||||
}
|
||||
|
||||
private static void EmitDereferenceAssignment(BoundDereferenceAssignmentNode dereferenceAssignment)
|
||||
{
|
||||
var pointer = EmitUnwrap(EmitExpression(dereferenceAssignment.Dereference.Expression));
|
||||
var value = EmitUnwrap(EmitExpression(dereferenceAssignment.Value));
|
||||
EmitCopy(dereferenceAssignment.Value.Type, value, pointer);
|
||||
}
|
||||
|
||||
private static void EmitIf(BoundIfNode ifStatement)
|
||||
{
|
||||
var trueLabel = LabelName();
|
||||
@@ -609,24 +579,6 @@ public static class QBEGenerator
|
||||
_builder.AppendLine(endLabel);
|
||||
}
|
||||
|
||||
private static void EmitMemberAssignment(BoundMemberAssignmentNode memberAssignment)
|
||||
{
|
||||
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 = EmitUnwrap(EmitExpression(memberAssignment.MemberAccess.Expression));
|
||||
var pointer = VarName();
|
||||
|
||||
_builder.AppendLine($" {pointer} =l add {item}, {offset}");
|
||||
|
||||
var value = EmitUnwrap(EmitExpression(memberAssignment.Value));
|
||||
|
||||
EmitCopy(memberAssignment.Value.Type, value, pointer);
|
||||
}
|
||||
|
||||
private static void EmitReturn(BoundReturnNode @return)
|
||||
{
|
||||
if (@return.Value.HasValue)
|
||||
@@ -647,13 +599,6 @@ public static class QBEGenerator
|
||||
_variables.Push(new Variable(variableDeclaration.Name, new Val(tmp, variableDeclaration.Type, ValKind.Pointer)));
|
||||
}
|
||||
|
||||
private static void EmitVariableAssignment(BoundVariableAssignmentNode variableAssignment)
|
||||
{
|
||||
var value = EmitUnwrap(EmitExpression(variableAssignment.Value));
|
||||
var variable = _variables.Single(x => x.Name == variableAssignment.Identifier.Name);
|
||||
EmitCopy(variableAssignment.Value.Type, value, variable.Val.Name);
|
||||
}
|
||||
|
||||
private static void EmitWhile(BoundWhileNode whileStatement)
|
||||
{
|
||||
var conditionLabel = LabelName();
|
||||
@@ -685,7 +630,6 @@ public static class QBEGenerator
|
||||
BoundArrayInitializerNode arrayInitializer => EmitArrayInitializer(arrayInitializer),
|
||||
BoundBinaryExpressionNode binaryExpression => EmitBinaryExpression(binaryExpression),
|
||||
BoundDereferenceNode dereference => EmitDereference(dereference),
|
||||
BoundFixedArrayInitializerNode fixedArrayInitializer => EmitFixedArrayInitializer(fixedArrayInitializer),
|
||||
BoundFuncCallNode funcCallExpression => EmitFuncCall(funcCallExpression),
|
||||
BoundIdentifierNode identifier => EmitIdentifier(identifier),
|
||||
BoundLiteralNode literal => EmitLiteral(literal),
|
||||
@@ -703,31 +647,18 @@ public static class QBEGenerator
|
||||
return new Val(name, anonymousFunc.Type, ValKind.Func);
|
||||
}
|
||||
|
||||
private static string EmitArrayIndexPointer(BoundArrayIndexAccessNode arrayIndexAccess)
|
||||
private static Val EmitArrayIndexAccess(BoundArrayIndexAccessNode arrayIndexAccess)
|
||||
{
|
||||
var array = EmitUnwrap(EmitExpression(arrayIndexAccess.Array));
|
||||
var index = EmitUnwrap(EmitExpression(arrayIndexAccess.Index));
|
||||
EmitArrayBoundsCheck(array, index);
|
||||
|
||||
var elementType = arrayIndexAccess.Array.Type switch
|
||||
{
|
||||
NubArrayType arrayType => arrayType.ElementType,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
var elementType = ((NubArrayType)arrayIndexAccess.Array.Type).ElementType;
|
||||
|
||||
var pointer = VarName();
|
||||
_builder.AppendLine($" {pointer} =l mul {index}, {SizeOf(elementType)}");
|
||||
_builder.AppendLine($" {pointer} =l add {pointer}, 8");
|
||||
_builder.AppendLine($" {pointer} =l add {array}, {pointer}");
|
||||
return pointer;
|
||||
}
|
||||
|
||||
private static Val EmitArrayIndexAccess(BoundArrayIndexAccessNode arrayIndexAccess)
|
||||
{
|
||||
var pointer = EmitArrayIndexPointer(arrayIndexAccess);
|
||||
var outputName = VarName();
|
||||
_builder.AppendLine($" {outputName} {QBEAssign(arrayIndexAccess.Type)} {QBELoad(arrayIndexAccess.Type)} {pointer}");
|
||||
return new Val(outputName, arrayIndexAccess.Type, ValKind.Immediate);
|
||||
return new Val(pointer, arrayIndexAccess.Type, ValKind.Pointer);
|
||||
}
|
||||
|
||||
private static void EmitArrayBoundsCheck(string array, string index)
|
||||
@@ -785,31 +716,13 @@ public static class QBEGenerator
|
||||
|
||||
private static Val EmitAddressOf(BoundAddressOfNode addressOf)
|
||||
{
|
||||
switch (addressOf.Expression)
|
||||
var value = EmitExpression(addressOf.Expression);
|
||||
if (value.Kind != ValKind.Pointer)
|
||||
{
|
||||
case BoundArrayIndexAccessNode arrayIndexAccess:
|
||||
{
|
||||
var pointer = EmitArrayIndexPointer(arrayIndexAccess);
|
||||
return new Val(pointer, addressOf.Type, ValKind.Immediate);
|
||||
}
|
||||
case BoundDereferenceNode dereference:
|
||||
{
|
||||
return EmitExpression(dereference.Expression);
|
||||
}
|
||||
case BoundIdentifierNode identifier:
|
||||
{
|
||||
if (identifier.Namespace.HasValue)
|
||||
{
|
||||
throw new NotSupportedException("There is nothing to address in another namespace");
|
||||
}
|
||||
|
||||
return _variables.Single(x => x.Name == identifier.Name).Val;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
throw new UnreachableException();
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
private static Val EmitBinaryExpression(BoundBinaryExpressionNode binaryExpression)
|
||||
@@ -1217,19 +1130,27 @@ public static class QBEGenerator
|
||||
if (memberAccess.Member == "count")
|
||||
{
|
||||
_builder.AppendLine($" {output} =l loadl {item}");
|
||||
break;
|
||||
return new Val(output, memberAccess.Type, ValKind.Immediate);
|
||||
}
|
||||
|
||||
throw new UnreachableException();
|
||||
break;
|
||||
}
|
||||
case NubStringType:
|
||||
{
|
||||
_builder.AppendLine($" {output} =l call $nub_string_length(l {item})");
|
||||
if (memberAccess.Member == "count")
|
||||
{
|
||||
_builder.AppendLine($" {output} =l call $nub_string_length(l {item})");
|
||||
return new Val(output, memberAccess.Type, ValKind.Immediate);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NubCStringType:
|
||||
{
|
||||
_builder.AppendLine($" {output} =l call $nub_cstring_length(l {item})");
|
||||
if (memberAccess.Member == "count")
|
||||
{
|
||||
_builder.AppendLine($" {output} =l call $nub_cstring_length(l {item})");
|
||||
return new Val(output, memberAccess.Type, ValKind.Immediate);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case NubStructType structType:
|
||||
@@ -1237,35 +1158,12 @@ public static class QBEGenerator
|
||||
var structDefinition = _definitionTable.LookupStruct(structType.Namespace, structType.Name).GetValue();
|
||||
var offset = OffsetOf(structDefinition, memberAccess.Member);
|
||||
|
||||
var offsetName = VarName();
|
||||
_builder.AppendLine($" {offsetName} =l add {item}, {offset}");
|
||||
_builder.AppendLine($" {output} {QBEAssign(memberAccess.Type)} {QBELoad(memberAccess.Type)} {item}");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
_builder.AppendLine($" {output} =l add {item}, {offset}");
|
||||
return new Val(output, memberAccess.Type, ValKind.Pointer);
|
||||
}
|
||||
}
|
||||
|
||||
return new Val(output, memberAccess.Type, ValKind.Immediate);
|
||||
}
|
||||
|
||||
private static Val EmitFixedArrayInitializer(BoundFixedArrayInitializerNode fixedArrayInitializer)
|
||||
{
|
||||
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})");
|
||||
|
||||
return new Val(outputName, fixedArrayInitializer.Type, ValKind.Immediate);
|
||||
throw new UnreachableException();
|
||||
}
|
||||
|
||||
private static Val EmitFuncCall(BoundFuncCallNode funcCall)
|
||||
|
||||
Reference in New Issue
Block a user