Simplify addressing

This commit is contained in:
nub31
2025-09-08 20:22:44 +02:00
parent 3295f76001
commit 343d515f37
5 changed files with 143 additions and 110 deletions

View File

@@ -230,7 +230,7 @@ public class QBEGenerator
return;
}
var value = EmitUnwrap(EmitExpression(source));
var value = EmitExpression(source);
if (source.Type.IsSimpleType(out var simpleType, out var complexType))
{
@@ -269,7 +269,7 @@ public class QBEGenerator
case InterfaceInitializerNode:
case LiteralNode { Kind: LiteralKind.String }:
{
destination = EmitUnwrap(EmitExpression(source));
destination = EmitExpression(source);
return true;
}
}
@@ -286,7 +286,7 @@ public class QBEGenerator
return uncopiedValue;
}
var value = EmitUnwrap(EmitExpression(source));
var value = EmitExpression(source);
if (source.Type.IsSimpleType(out _, out var complexType))
{
@@ -508,13 +508,7 @@ public class QBEGenerator
private void EmitAssignment(AssignmentNode assignment)
{
if (!assignment.Target.IsLValue)
{
throw new UnreachableException("Destination of assignment must be an lvalue. This should have been caught in the type checker");
}
var destination = EmitExpression(assignment.Target);
EmitCopyIntoOrInitialize(assignment.Value, destination.Name);
EmitCopyIntoOrInitialize(assignment.Value, EmitAddressOfLValue(assignment.Target));
}
private void EmitBreak()
@@ -535,7 +529,7 @@ public class QBEGenerator
var falseLabel = LabelName();
var endLabel = LabelName();
var result = EmitUnwrap(EmitExpression(ifStatement.Condition));
var result = EmitExpression(ifStatement.Condition);
_writer.Indented($"jnz {result}, {trueLabel}, {falseLabel}");
_writer.WriteLine(trueLabel);
EmitBlock(ifStatement.Body);
@@ -543,11 +537,7 @@ public class QBEGenerator
_writer.WriteLine(falseLabel);
if (ifStatement.Else.HasValue)
{
ifStatement.Else.Value.Match
(
elseIfNode => EmitIf(elseIfNode),
elseNode => EmitBlock(elseNode)
);
ifStatement.Else.Value.Match(EmitIf, EmitBlock);
}
_writer.WriteLine(endLabel);
@@ -557,7 +547,7 @@ public class QBEGenerator
{
if (@return.Value.HasValue)
{
var result = EmitUnwrap(EmitExpression(@return.Value.Value));
var result = EmitExpression(@return.Value.Value);
_writer.Indented($"ret {result}");
}
else
@@ -591,7 +581,7 @@ public class QBEGenerator
_writer.WriteLine(iterationLabel);
EmitBlock(whileStatement.Body);
_writer.WriteLine(conditionLabel);
var result = EmitUnwrap(EmitExpression(whileStatement.Condition));
var result = EmitExpression(whileStatement.Condition);
_writer.Indented($"jnz {result}, {iterationLabel}, {endLabel}");
_writer.WriteLine(endLabel);
@@ -599,21 +589,22 @@ public class QBEGenerator
_breakLabels.Pop();
}
private Val EmitExpression(ExpressionNode expression)
private string EmitExpression(ExpressionNode expression)
{
var value = expression switch
return expression switch
{
ArrayInitializerNode arrayInitializer => EmitArrayInitializer(arrayInitializer),
StructInitializerNode structInitializer => EmitStructInitializer(structInitializer),
AddressOfNode addressOf => EmitAddressOf(addressOf),
DereferenceNode dereference => EmitDereference(dereference),
BinaryExpressionNode binaryExpression => EmitBinaryExpression(binaryExpression),
FuncCallNode funcCallExpression => EmitFuncCall(funcCallExpression),
BinaryExpressionNode binary => EmitBinaryExpression(binary),
FuncCallNode funcCall => EmitFuncCall(funcCall),
InterfaceFuncCallNode interfaceFuncCall => EmitInterfaceFuncCall(interfaceFuncCall),
InterfaceInitializerNode interfaceInitializer => EmitInterfaceInitializer(interfaceInitializer),
ExternFuncIdentNode externFuncIdent => EmitExternFuncIdent(externFuncIdent),
LocalFuncIdentNode localFuncIdent => EmitLocalFuncIdent(localFuncIdent),
VariableIdentNode variableIdent => EmitVariableIdent(variableIdent),
FuncParameterIdentNode funcParameterIdent => EmitFuncParameterIdent(funcParameterIdent),
LiteralNode literal => EmitLiteral(literal),
UnaryExpressionNode unaryExpression => EmitUnaryExpression(unaryExpression),
StructFieldAccessNode structFieldAccess => EmitStructFieldAccess(structFieldAccess),
@@ -621,27 +612,14 @@ public class QBEGenerator
ArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex),
_ => throw new ArgumentOutOfRangeException(nameof(expression))
};
return new Val(value, expression.Type, expression.IsLValue);
}
private string EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess)
{
var array = EmitUnwrap(EmitExpression(arrayIndexAccess.Target));
var index = EmitUnwrap(EmitExpression(arrayIndexAccess.Index));
EmitArraysCheck(array, index);
var elementType = ((ArrayTypeNode)arrayIndexAccess.Target.Type).ElementType;
var pointer = TmpName();
_writer.Indented($"{pointer} =l mul {index}, {SizeOf(elementType)}");
_writer.Indented($"{pointer} =l add {pointer}, 8");
_writer.Indented($"{pointer} =l add {array}, {pointer}");
return pointer;
return EmitLoad(arrayIndexAccess.Type, EmitAddressOfArrayIndexAccess(arrayIndexAccess));
}
private void EmitArraysCheck(string array, string index)
private void EmitArrayBoundsCheck(string array, string index)
{
var count = TmpName();
_writer.Indented($"{count} =l loadl {array}");
@@ -667,7 +645,7 @@ public class QBEGenerator
private string EmitArrayInitializer(ArrayInitializerNode arrayInitializer)
{
var capacity = EmitUnwrap(EmitExpression(arrayInitializer.Capacity));
var capacity = EmitExpression(arrayInitializer.Capacity);
var elementSize = SizeOf(arrayInitializer.ElementType);
var capacityInBytes = TmpName();
@@ -688,24 +666,65 @@ public class QBEGenerator
private string EmitDereference(DereferenceNode dereference)
{
return EmitLoad(dereference.Type, EmitUnwrap(EmitExpression(dereference.Expression)));
return EmitLoad(dereference.Type, EmitExpression(dereference.Expression));
}
private string EmitAddressOf(AddressOfNode addressOf)
{
var value = EmitExpression(addressOf.Expression);
if (!value.IsLValue)
{
throw new UnreachableException("Tried to take address of rvalue. This should have been caught in the type checker");
}
return EmitAddressOfLValue(addressOf.LValue);
}
return value.Name;
private string EmitAddressOfLValue(LValueExpressionNode addressOf)
{
return addressOf switch
{
ArrayIndexAccessNode arrayIndexAccess => EmitAddressOfArrayIndexAccess(arrayIndexAccess),
ArrayInitializerNode arrayInitializer => EmitArrayInitializer(arrayInitializer),
InterfaceInitializerNode interfaceInitializer => EmitInterfaceInitializer(interfaceInitializer),
StructFieldAccessNode structFieldAccess => EmitAddressOfStructFieldAccess(structFieldAccess),
StructInitializerNode structInitializer => EmitStructInitializer(structInitializer),
VariableIdentNode variableIdent => EmitAddressOfVariableIdent(variableIdent),
_ => throw new ArgumentOutOfRangeException(nameof(addressOf))
};
}
private string EmitAddressOfArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess)
{
var array = EmitExpression(arrayIndexAccess.Target);
var index = EmitExpression(arrayIndexAccess.Index);
EmitArrayBoundsCheck(array, index);
var elementType = ((ArrayTypeNode)arrayIndexAccess.Target.Type).ElementType;
var address = TmpName();
_writer.Indented($"{address} =l mul {index}, {SizeOf(elementType)}");
_writer.Indented($"{address} =l add {address}, 8");
_writer.Indented($"{address} =l add {array}, {address}");
return address;
}
private string EmitAddressOfStructFieldAccess(StructFieldAccessNode structFieldAccess)
{
var target = EmitExpression(structFieldAccess.Target);
var structDef = _definitionTable.LookupStruct(structFieldAccess.StructType.Name);
var offset = OffsetOf(structDef, structFieldAccess.Field);
var address = TmpName();
_writer.Indented($"{address} =l add {target}, {offset}");
return address;
}
private string EmitAddressOfVariableIdent(VariableIdentNode variableIdent)
{
return "%" + variableIdent.Name;
}
private string EmitBinaryExpression(BinaryExpressionNode binaryExpression)
{
var left = EmitUnwrap(EmitExpression(binaryExpression.Left));
var right = EmitUnwrap(EmitExpression(binaryExpression.Right));
var left = EmitExpression(binaryExpression.Left);
var right = EmitExpression(binaryExpression.Right);
var outputName = TmpName();
@@ -811,19 +830,22 @@ public class QBEGenerator
private string EmitExternFuncIdent(ExternFuncIdentNode externFuncIdent)
{
var func = _definitionTable.LookupExternFunc(externFuncIdent.Name);
return ExternFuncName(func);
return ExternFuncName(_definitionTable.LookupExternFunc(externFuncIdent.Name));
}
private string EmitLocalFuncIdent(LocalFuncIdentNode localFuncIdent)
{
var func = _definitionTable.LookupLocalFunc(localFuncIdent.Name);
return LocalFuncName(func);
return LocalFuncName(_definitionTable.LookupLocalFunc(localFuncIdent.Name));
}
private string EmitVariableIdent(VariableIdentNode variableIdent)
{
return variableIdent.Name;
return EmitLoad(variableIdent.Type, EmitAddressOfVariableIdent(variableIdent));
}
private string EmitFuncParameterIdent(FuncParameterIdentNode funcParameterIdent)
{
return "%" + funcParameterIdent.Name;
}
private string EmitLiteral(LiteralNode literal)
@@ -941,7 +963,7 @@ public class QBEGenerator
private string EmitUnaryExpression(UnaryExpressionNode unaryExpression)
{
var operand = EmitUnwrap(EmitExpression(unaryExpression.Operand));
var operand = EmitExpression(unaryExpression.Operand);
var outputName = TmpName();
switch (unaryExpression.Operator)
@@ -988,15 +1010,7 @@ public class QBEGenerator
private string EmitStructFieldAccess(StructFieldAccessNode structFieldAccess)
{
var target = EmitUnwrap(EmitExpression(structFieldAccess.Target));
var structDef = _definitionTable.LookupStruct(structFieldAccess.StructType.Name);
var offset = OffsetOf(structDef, structFieldAccess.Field);
var output = TmpName();
_writer.Indented($"{output} =l add {target}, {offset}");
return output;
return EmitLoad(structFieldAccess.Type, EmitAddressOfStructFieldAccess(structFieldAccess));
}
private string EmitStructFuncCall(StructFuncCallNode structFuncCall)
@@ -1004,7 +1018,7 @@ public class QBEGenerator
var structDef = _definitionTable.LookupStruct(structFuncCall.StructType.Name);
var func = StructFuncName(structDef.Name, structFuncCall.Name);
var thisParameter = EmitUnwrap(EmitExpression(structFuncCall.StructExpression));
var thisParameter = EmitExpression(structFuncCall.StructExpression);
List<string> parameterStrings = [$"l {thisParameter}"];
@@ -1029,7 +1043,7 @@ public class QBEGenerator
private string EmitInterfaceFuncCall(InterfaceFuncCallNode interfaceFuncCall)
{
var target = EmitUnwrap(EmitExpression(interfaceFuncCall.InterfaceExpression));
var target = EmitExpression(interfaceFuncCall.InterfaceExpression);
var interfaceDef = _definitionTable.LookupInterface(interfaceFuncCall.InterfaceType.Name);
var functionIndex = interfaceDef.Functions.ToList().FindIndex(x => x.Name == interfaceFuncCall.Name);
@@ -1070,7 +1084,7 @@ public class QBEGenerator
private string EmitInterfaceInitializer(InterfaceInitializerNode interfaceInitializer, string? destination = null)
{
var implementation = EmitUnwrap(EmitExpression(interfaceInitializer.Implementation));
var implementation = EmitExpression(interfaceInitializer.Implementation);
var vtableOffset = 0;
foreach (var interfaceImplementation in interfaceInitializer.StructType.InterfaceImplementations)
@@ -1102,7 +1116,7 @@ public class QBEGenerator
private string EmitFuncCall(FuncCallNode funcCall)
{
var expression = EmitExpression(funcCall.Expression);
var funcPointer = EmitExpression(funcCall.Expression);
var parameterStrings = new List<string>();
@@ -1112,7 +1126,6 @@ public class QBEGenerator
parameterStrings.Add($"{FuncQBETypeName(parameter.Type)} {copy}");
}
var funcPointer = EmitUnwrap(expression);
if (funcCall.Type is VoidTypeNode)
{
_writer.Indented($"call {funcPointer}({string.Join(", ", parameterStrings)})");
@@ -1126,11 +1139,6 @@ public class QBEGenerator
}
}
private string EmitUnwrap(Val val)
{
return val.IsLValue ? EmitLoad(val.Type, val.Name) : val.Name;
}
private static int SizeOf(TypeNode type)
{
return type switch
@@ -1293,6 +1301,4 @@ public class CStringLiteral(string value, string name)
{
public string Value { get; } = value;
public string Name { get; } = name;
}
public record Val(string Name, TypeNode Type, bool IsLValue);
}