Array type works with args

This commit is contained in:
nub31
2025-05-22 19:31:11 +02:00
parent ba51daa3c0
commit f6d7cdbf58
9 changed files with 250 additions and 105 deletions

View File

@@ -74,6 +74,7 @@ public class Generator
}
case NubStructType:
case NubPointerType:
case NubArrayType:
{
return "l";
}
@@ -120,6 +121,7 @@ public class Generator
return ":" + nubCustomType.Name;
}
case NubPointerType:
case NubArrayType:
{
return "l";
}
@@ -169,6 +171,7 @@ public class Generator
return ":" + nubCustomType.Name;
}
case NubPointerType:
case NubArrayType:
{
return "l";
}
@@ -221,6 +224,7 @@ public class Generator
return definition.Fields.Sum(f => QbeTypeSize(f.Type));
}
case NubPointerType:
case NubArrayType:
{
return 8;
}
@@ -259,7 +263,7 @@ public class Generator
_builder.AppendLine("@start");
_builder.AppendLine(" # Variable allocation");
foreach (var parameter in node.Parameters)
{
var parameterName = parameter.Name;
@@ -287,8 +291,8 @@ public class Generator
var pointerLabel = GenName();
_builder.AppendLine($" %{pointerLabel} ={SQT(parameter.Type)} alloc8 {QbeTypeSize(parameter.Type)}");
_builder.AppendLine($" storel %{parameterName}, %{pointerLabel}");
_variables[parameter.Name] = new Variable
{
Pointer = $"%{pointerLabel}",
@@ -474,15 +478,23 @@ public class Generator
private void GenerateVariableAssignment(VariableAssignmentNode variableAssignment)
{
var result = GenerateExpression(variableAssignment.Value);
var pointerLabel = GenName();
_builder.AppendLine($" %{pointerLabel} ={SQT(variableAssignment.Value.Type)} alloc8 {QbeTypeSize(variableAssignment.Value.Type)}");
_builder.AppendLine($" storel {result}, %{pointerLabel}");
_variables[variableAssignment.Name] = new Variable
if (_variables.TryGetValue(variableAssignment.Name, out var existingVariable))
{
Pointer = $"%{pointerLabel}",
Type = variableAssignment.Value.Type
};
_builder.AppendLine($" storel {result}, {existingVariable.Pointer}");
}
else
{
var pointerLabel = GenName();
_builder.AppendLine($" %{pointerLabel} ={SQT(variableAssignment.Value.Type)} alloc8 {QbeTypeSize(variableAssignment.Value.Type)}");
_builder.AppendLine($" storel {result}, %{pointerLabel}");
_variables[variableAssignment.Name] = new Variable
{
Pointer = $"%{pointerLabel}",
Type = variableAssignment.Value.Type
};
}
}
private void GenerateWhile(WhileNode whileStatement)
@@ -511,6 +523,7 @@ public class Generator
return expression switch
{
AddressOfNode addressOf => GenerateAddressOf(addressOf),
ArrayIndexNode arrayIndex => GenerateArrayIndex(arrayIndex),
BinaryExpressionNode binaryExpression => GenerateBinaryExpression(binaryExpression),
CastNode cast => GenerateCast(cast),
DereferenceNode dereference => GenerateDereference(dereference),
@@ -519,11 +532,29 @@ public class Generator
LiteralNode literal => GenerateLiteral(literal),
StructInitializerNode structInitializer => GenerateStructInitializer(structInitializer),
UnaryExpressionNode unaryExpression => GenerateUnaryExpression(unaryExpression),
StructFieldAccessorNode structMemberAccessor => GenerateStructFieldAccessor(structMemberAccessor),
MemberAccessNode memberAccess => GenerateMemberAccess(memberAccess),
_ => throw new ArgumentOutOfRangeException(nameof(expression))
};
}
private string GenerateArrayIndex(ArrayIndexNode arrayIndex)
{
var array = GenerateExpression(arrayIndex.Expression);
var index = GenerateExpression(arrayIndex.Index);
var arrayBaseType = ((NubArrayType)arrayIndex.Expression.Type).BaseType;
var firstItem = GenName();
_builder.AppendLine($" %{firstItem} =l add {array}, 8");
var adjustedIndex = GenName();
_builder.AppendLine($" %{adjustedIndex} =l mul {index}, {QbeTypeSize(arrayBaseType)}");
var indexLabel = GenName();
_builder.AppendLine($" %{indexLabel} ={SQT(arrayIndex.Type)} add %{firstItem}, %{adjustedIndex}");
var outputLabel = GenName();
_builder.AppendLine($" %{outputLabel} =l load{SQT(arrayBaseType)} %{indexLabel}");
return $"%{outputLabel}";
}
private string GenerateDereference(DereferenceNode dereference)
{
var result = GenerateExpression(dereference.Expression);
@@ -1331,7 +1362,7 @@ public class Generator
_builder.AppendLine($" %{outputLabel} =s neg {operand}");
return $"%{outputLabel}";
}
break;
}
case UnaryExpressionOperator.Invert:
@@ -1354,42 +1385,60 @@ public class Generator
throw new NotSupportedException($"Unary operator {unaryExpression.Operator} for type {unaryExpression.Operand.Type} not supported");
}
private string GenerateStructFieldAccessor(StructFieldAccessorNode structFieldAccessor)
private string GenerateMemberAccess(MemberAccessNode memberAccess)
{
var structType = structFieldAccessor.Struct.Type;
var structDefinition = _definitions
.OfType<StructDefinitionNode>()
.FirstOrDefault(s => s.Name == structType.Name);
var expression = GenerateExpression(memberAccess.Expression);
if (structDefinition == null)
switch (memberAccess.Expression.Type)
{
throw new Exception($"Struct {structType.Name} is not defined");
}
var @struct = GenerateExpression(structFieldAccessor.Struct);
var fieldIndex = -1;
for (var i = 0; i < structDefinition.Fields.Count; i++)
{
if (structDefinition.Fields[i].Name == structFieldAccessor.Field)
case NubArrayType:
{
fieldIndex = i;
if (memberAccess.Member == "count")
{
var outputLabel = GenName();
_builder.AppendLine($" %{outputLabel} =l loadl {expression}");
return $"%{outputLabel}";
}
break;
}
case NubStructType structType:
{
var structDefinition = _definitions
.OfType<StructDefinitionNode>()
.FirstOrDefault(s => s.Name == structType.Name);
if (structDefinition == null)
{
throw new Exception($"Struct {structType.Name} is not defined");
}
var fieldIndex = -1;
for (var i = 0; i < structDefinition.Fields.Count; i++)
{
if (structDefinition.Fields[i].Name == memberAccess.Member)
{
fieldIndex = i;
break;
}
}
if (fieldIndex == -1)
{
throw new Exception($"Field {memberAccess.Member} is not defined in struct {structType.Name}");
}
var offsetLabel = GenName();
_builder.AppendLine($" %{offsetLabel} =l add {expression}, {fieldIndex * QbeTypeSize(memberAccess.Type)}");
var outputLabel = GenName();
_builder.AppendLine($" %{outputLabel} ={SQT(memberAccess.Type)} load{SQT(memberAccess.Type)} %{offsetLabel}");
return $"%{outputLabel}";
}
}
if (fieldIndex == -1)
{
throw new Exception($"Field {structFieldAccessor.Field} is not defined in struct {structType.Name}");
}
var offsetLabel = GenName();
_builder.AppendLine($" %{offsetLabel} =l add {@struct}, {fieldIndex * QbeTypeSize(structFieldAccessor.Type)}");
var outputLabel = GenName();
_builder.AppendLine($" %{outputLabel} ={SQT(structFieldAccessor.Type)} load{SQT(structFieldAccessor.Type)} %{offsetLabel}");
return $"%{outputLabel}";
throw new ArgumentOutOfRangeException(nameof(memberAccess.Expression.Type));
}
private string GenerateExpressionFuncCall(FuncCallExpressionNode funcCall)