Files
nub-lang/src/compiler/NubLang/Generation/QBE/QBEGenerator.Statement.cs
nub31 d993581361 ...
2025-07-22 23:20:56 +02:00

131 lines
3.9 KiB
C#

using System.Diagnostics;
using NubLang.TypeChecking.Node;
namespace NubLang.Generation.QBE;
public partial class QBEGenerator
{
private void EmitStatement(Statement statement)
{
switch (statement)
{
case Assignment assignment:
EmitAssignment(assignment);
break;
case Break:
EmitBreak();
break;
case Continue:
EmitContinue();
break;
case If ifStatement:
EmitIf(ifStatement);
break;
case Return @return:
EmitReturn(@return);
break;
case StatementExpression statementExpression:
EmitExpression(statementExpression.Expression);
break;
case VariableDeclaration variableDeclaration:
EmitVariableDeclaration(variableDeclaration);
break;
case While whileStatement:
EmitWhile(whileStatement);
break;
default:
throw new ArgumentOutOfRangeException(nameof(statement));
}
}
private void EmitAssignment(Assignment assignment)
{
var destination = EmitExpression(assignment.Target);
Debug.Assert(destination.Kind == ValKind.Pointer);
EmitCopyIntoOrInitialize(assignment.Value, destination.Name);
}
private void EmitBreak()
{
_writer.Indented($"jmp {_breakLabels.Peek()}");
_codeIsReachable = false;
}
private void EmitContinue()
{
_writer.Indented($"jmp {_continueLabels.Peek()}");
_codeIsReachable = false;
}
private void EmitIf(If ifStatement)
{
var trueLabel = LabelName();
var falseLabel = LabelName();
var endLabel = LabelName();
var result = EmitUnwrap(EmitExpression(ifStatement.Condition));
_writer.Indented($"jnz {result}, {trueLabel}, {falseLabel}");
_writer.WriteLine(trueLabel);
EmitBlock(ifStatement.Body);
_writer.Indented($"jmp {endLabel}");
_writer.WriteLine(falseLabel);
if (ifStatement.Else.HasValue)
{
ifStatement.Else.Value.Match
(
elseIfNode => EmitIf(elseIfNode),
elseNode => EmitBlock(elseNode)
);
}
_writer.WriteLine(endLabel);
}
private void EmitReturn(Return @return)
{
if (@return.Value.HasValue)
{
var result = EmitUnwrap(EmitExpression(@return.Value.Value));
_writer.Indented($"ret {result}");
}
else
{
_writer.Indented("ret");
}
}
private void EmitVariableDeclaration(VariableDeclaration variableDeclaration)
{
var name = $"%{variableDeclaration.Name}";
_writer.Indented($"{name} =l alloc8 8");
if (variableDeclaration.Assignment.HasValue)
{
var value = EmitCreateCopyOrInitialize(variableDeclaration.Assignment.Value);
EmitStore(variableDeclaration.Assignment.Value.Type, value, name);
}
Scope.Declare(variableDeclaration.Name, new Val(name, variableDeclaration.Type, ValKind.Pointer));
}
private void EmitWhile(While whileStatement)
{
var conditionLabel = LabelName();
var iterationLabel = LabelName();
var endLabel = LabelName();
_breakLabels.Push(endLabel);
_continueLabels.Push(conditionLabel);
_writer.Indented($"jmp {conditionLabel}");
_writer.WriteLine(iterationLabel);
EmitBlock(whileStatement.Body);
_writer.WriteLine(conditionLabel);
var result = EmitUnwrap(EmitExpression(whileStatement.Condition));
_writer.Indented($"jnz {result}, {iterationLabel}, {endLabel}");
_writer.WriteLine(endLabel);
_continueLabels.Pop();
_breakLabels.Pop();
}
}