...
This commit is contained in:
@@ -1,5 +1,4 @@
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using NubLang.Tokenization;
|
||||
@@ -11,6 +10,7 @@ public class QBEGenerator
|
||||
{
|
||||
private readonly TypedSyntaxTree _syntaxTree;
|
||||
private readonly TypedDefinitionTable _definitionTable;
|
||||
private readonly string _sourceFileName;
|
||||
private readonly QBEWriter _writer;
|
||||
|
||||
private readonly List<CStringLiteral> _cStringLiterals = [];
|
||||
@@ -23,10 +23,11 @@ public class QBEGenerator
|
||||
private int _stringLiteralIndex;
|
||||
private bool _codeIsReachable = true;
|
||||
|
||||
public QBEGenerator(TypedSyntaxTree syntaxTree, TypedDefinitionTable definitionTable)
|
||||
public QBEGenerator(TypedSyntaxTree syntaxTree, TypedDefinitionTable definitionTable, string sourceFileName)
|
||||
{
|
||||
_syntaxTree = syntaxTree;
|
||||
_definitionTable = definitionTable;
|
||||
_sourceFileName = sourceFileName;
|
||||
_writer = new QBEWriter();
|
||||
}
|
||||
|
||||
@@ -42,6 +43,8 @@ public class QBEGenerator
|
||||
_stringLiteralIndex = 0;
|
||||
_codeIsReachable = true;
|
||||
|
||||
_writer.WriteLine($"dbgfile \"{_sourceFileName}\"");
|
||||
|
||||
foreach (var structDef in _definitionTable.GetStructs())
|
||||
{
|
||||
EmitStructTypeDefinition(structDef);
|
||||
@@ -260,39 +263,22 @@ public class QBEGenerator
|
||||
}
|
||||
}
|
||||
|
||||
private bool EmitTryCreateWithoutCopy(ExpressionNode source, [NotNullWhen(true)] out string? destination)
|
||||
private string EmitCreateCopy(ExpressionNode source)
|
||||
{
|
||||
switch (source)
|
||||
// Allowlist for types which are safe to not copy
|
||||
if (source is ArrayInitializerNode or StructInitializerNode or ConvertToInterfaceNode or LiteralNode)
|
||||
{
|
||||
case ArrayInitializerNode:
|
||||
case StructInitializerNode:
|
||||
case LiteralNode { Kind: LiteralKind.String }:
|
||||
{
|
||||
destination = EmitExpression(source);
|
||||
return true;
|
||||
}
|
||||
return EmitExpression(source);
|
||||
}
|
||||
|
||||
destination = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
private string EmitCreateCopyOrInitialize(ExpressionNode source)
|
||||
{
|
||||
// If the source is a value which is not used yet such as an array/struct/interface initializer or literal, we can skip copying
|
||||
if (EmitTryCreateWithoutCopy(source, out var uncopiedValue))
|
||||
{
|
||||
return uncopiedValue;
|
||||
}
|
||||
|
||||
var value = EmitExpression(source);
|
||||
|
||||
// Simple types are passed in registers and therefore always copied
|
||||
if (source.Type.IsSimpleType(out _, out var complexType))
|
||||
{
|
||||
// Simple types are passed in registers and are therefore always copied
|
||||
return value;
|
||||
return EmitExpression(source);
|
||||
}
|
||||
|
||||
// For the rest, we figure out the size of the type and shallow copy them
|
||||
var value = EmitExpression(source);
|
||||
var size = complexType switch
|
||||
{
|
||||
ArrayTypeNode arrayType => EmitArraySizeInBytes(arrayType, value),
|
||||
@@ -474,6 +460,12 @@ public class QBEGenerator
|
||||
|
||||
private void EmitStatement(StatementNode statement)
|
||||
{
|
||||
var tokens = statement.Tokens.ToArray();
|
||||
if (tokens.Length != 0)
|
||||
{
|
||||
_writer.WriteLine($"dbgloc {tokens[0].FileSpan.Span.Start.Line}");
|
||||
}
|
||||
|
||||
switch (statement)
|
||||
{
|
||||
case AssignmentNode assignment:
|
||||
@@ -589,6 +581,12 @@ public class QBEGenerator
|
||||
|
||||
private string EmitExpression(ExpressionNode expression)
|
||||
{
|
||||
var tokens = expression.Tokens.ToArray();
|
||||
if (tokens.Length != 0)
|
||||
{
|
||||
_writer.WriteLine($"dbgloc {tokens[0].FileSpan.Span.Start.Line}");
|
||||
}
|
||||
|
||||
return expression switch
|
||||
{
|
||||
ArrayInitializerNode arrayInitializer => EmitArrayInitializer(arrayInitializer),
|
||||
@@ -616,7 +614,13 @@ public class QBEGenerator
|
||||
|
||||
private string EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess)
|
||||
{
|
||||
return EmitLoad(arrayIndexAccess.Type, EmitAddressOfArrayIndexAccess(arrayIndexAccess));
|
||||
var address = EmitAddressOfArrayIndexAccess(arrayIndexAccess);
|
||||
if (arrayIndexAccess.Type is StructTypeNode)
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
return EmitLoad(arrayIndexAccess.Type, address);
|
||||
}
|
||||
|
||||
private void EmitArrayBoundsCheck(string array, string index)
|
||||
@@ -666,7 +670,13 @@ public class QBEGenerator
|
||||
|
||||
private string EmitDereference(DereferenceNode dereference)
|
||||
{
|
||||
return EmitLoad(dereference.Type, EmitExpression(dereference.Expression));
|
||||
var address = EmitExpression(dereference.Expression);
|
||||
if (dereference.Type is StructTypeNode)
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
return EmitLoad(dereference.Type, address);
|
||||
}
|
||||
|
||||
private string EmitAddressOf(AddressOfNode addressOf)
|
||||
@@ -901,10 +911,12 @@ public class QBEGenerator
|
||||
private string EmitVariableIdent(VariableIdentNode variableIdent)
|
||||
{
|
||||
var address = EmitAddressOfVariableIdent(variableIdent);
|
||||
if (variableIdent.Type is StructTypeNode)
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
return variableIdent.Type.IsSimpleType(out _, out _)
|
||||
? EmitLoad(variableIdent.Type, address)
|
||||
: address;
|
||||
return EmitLoad(variableIdent.Type, address);
|
||||
}
|
||||
|
||||
private string EmitFuncParameterIdent(FuncParameterIdentNode funcParameterIdent)
|
||||
@@ -1075,13 +1087,11 @@ public class QBEGenerator
|
||||
private string EmitStructFieldAccess(StructFieldAccessNode structFieldAccess)
|
||||
{
|
||||
var address = EmitAddressOfStructFieldAccess(structFieldAccess);
|
||||
|
||||
// Inline structs should not be loaded
|
||||
if (structFieldAccess.Type is StructTypeNode)
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
|
||||
return EmitLoad(structFieldAccess.Type, address);
|
||||
}
|
||||
|
||||
@@ -1096,7 +1106,7 @@ public class QBEGenerator
|
||||
|
||||
foreach (var parameter in structFuncCall.Parameters)
|
||||
{
|
||||
var copy = EmitCreateCopyOrInitialize(parameter);
|
||||
var copy = EmitCreateCopy(parameter);
|
||||
parameterStrings.Add($"{FuncQBETypeName(parameter.Type)} {copy}");
|
||||
}
|
||||
|
||||
@@ -1138,7 +1148,7 @@ public class QBEGenerator
|
||||
|
||||
foreach (var parameter in interfaceFuncCall.Parameters)
|
||||
{
|
||||
var copy = EmitCreateCopyOrInitialize(parameter);
|
||||
var copy = EmitCreateCopy(parameter);
|
||||
parameterStrings.Add($"{FuncQBETypeName(parameter.Type)} {copy}");
|
||||
}
|
||||
|
||||
@@ -1248,7 +1258,7 @@ public class QBEGenerator
|
||||
|
||||
foreach (var parameter in funcCall.Parameters)
|
||||
{
|
||||
var copy = EmitCreateCopyOrInitialize(parameter);
|
||||
var copy = EmitCreateCopy(parameter);
|
||||
parameterStrings.Add($"{FuncQBETypeName(parameter.Type)} {copy}");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user