This commit is contained in:
nub31
2025-06-02 19:56:38 +02:00
parent 81fe75446d
commit e874b8e155
7 changed files with 110 additions and 50 deletions

View File

@@ -275,7 +275,14 @@ public class Generator
private bool IsLargeType(NubType type)
{
return QbeTypeSize(type) > 8;
return type switch
{
NubArrayType => false,
NubPointerType => false,
NubPrimitiveType => false,
NubStructType => true,
_ => throw new ArgumentOutOfRangeException(nameof(type))
};
}
private void GenerateFuncDefinition(LocalFuncDefinitionNode node)
@@ -333,7 +340,6 @@ public class Generator
_builder.AppendLine($" %{pointerName} ={SQT(parameter.Type)} alloc8 {QbeTypeSize(parameter.Type)}");
_builder.AppendLine($" storel %{parameterName}, %{pointerName}");
_variables[parameter.Name] = new Variable
{
Pointer = $"%{pointerName}",
@@ -373,7 +379,7 @@ public class Generator
switch (statement)
{
case ArrayIndexAssignmentNode arrayIndexAssignment:
throw new NotImplementedException();
GenerateArrayIndexAssignment(arrayIndexAssignment);
break;
case BreakNode:
GenerateBreak();
@@ -407,6 +413,36 @@ public class Generator
}
}
private void GenerateArrayIndexAssignment(ArrayIndexAssignmentNode arrayIndexAssignment)
{
var arrayType = (NubArrayType)arrayIndexAssignment.ArrayIndexAccess.Array.Type;
var array = GenerateExpression(arrayIndexAssignment.ArrayIndexAccess.Array);
var index = GenerateExpression(arrayIndexAssignment.ArrayIndexAccess.Index);
GenerateArrayBoundsCheck(array, index);
var value = GenerateExpression(arrayIndexAssignment.Value);
var startName = GenVarName();
_builder.AppendLine($" %{startName} =l add {array}, 8");
var adjustedIndex = GenVarName();
_builder.AppendLine($" %{adjustedIndex} =l mul {index}, {QbeTypeSize(arrayType.BaseType)}");
var offsetName = GenVarName();
_builder.AppendLine($" %{offsetName} =l add %{startName}, %{adjustedIndex}");
if (IsLargeType(arrayType.BaseType))
{
_builder.AppendLine($" blit {value}, %{offsetName}, {QbeTypeSize(arrayType.BaseType)}");
}
else
{
_builder.AppendLine($" store{SQT(arrayType.BaseType)} {value}, %{offsetName}");
}
}
private void GenerateBlock(BlockNode block)
{
foreach (var statement in block.Statements.Where(_ => _codeIsReachable))
@@ -558,51 +594,61 @@ public class Generator
private string GenerateArrayIndex(ArrayIndexAccessNode arrayIndexAccess)
{
var arrayType = ((NubArrayType)arrayIndexAccess.Array.Type).BaseType;
var array = GenerateExpression(arrayIndexAccess.Array);
var index = GenerateExpression(arrayIndexAccess.Index);
GenerateArrayBoundsCheck(array, index);
var arrayBaseType = ((NubArrayType)arrayIndexAccess.Array.Type).BaseType;
var countName = GenVarName();
_builder.AppendLine($" %{countName} =l loadl {array}");
var isNegativeName = GenVarName();
_builder.AppendLine($" %{isNegativeName} =w csltl {index}, 0");
var isOobName = GenVarName();
_builder.AppendLine($" %{isOobName} =w csgel {index}, %{countName}");
var anyOobName = GenVarName();
_builder.AppendLine($" %{anyOobName} =w or %{isNegativeName}, %{isOobName}");
var oobLabel = GenLabelName();
var notOobLabel = GenLabelName();
_builder.AppendLine($" jnz %{anyOobName}, @{oobLabel}, @{notOobLabel}");
_builder.AppendLine($"@{oobLabel}");
_builder.AppendLine($" call $nub_panic(l $oob_message, l {OutOfBoundsMessage.Length})");
_builder.AppendLine($"@{notOobLabel}");
// Calculate element address
var firstItemPointerName = GenVarName();
_builder.AppendLine($" %{firstItemPointerName} =l add {array}, 8");
var offsetPointerName = GenVarName();
_builder.AppendLine($" %{offsetPointerName} =l mul {index}, {QbeTypeSize(arrayBaseType)}");
_builder.AppendLine($" %{offsetPointerName} =l mul {index}, {QbeTypeSize(arrayType)}");
var resultPointerName = GenVarName();
_builder.AppendLine($" %{resultPointerName} =l add %{firstItemPointerName}, %{offsetPointerName}");
// Load the value
var outputName = GenVarName();
_builder.AppendLine($" %{outputName} ={SQT(arrayBaseType)} load{SQT(arrayBaseType)} %{resultPointerName}");
return $"%{outputName}";
if (IsLargeType(arrayType))
{
return $"%{resultPointerName}";
}
else
{
var outputName = GenVarName();
_builder.AppendLine($" %{outputName} ={SQT(arrayType)} load{SQT(arrayType)} %{resultPointerName}");
return $"%{outputName}";
}
}
private void GenerateArrayBoundsCheck(string array, string index)
{
var countName = GenVarName();
_builder.AppendLine($" %{countName} =l loadl {array}");
var isNegativeName = GenVarName();
_builder.AppendLine($" %{isNegativeName} =w csltl {index}, 0");
var isOobName = GenVarName();
_builder.AppendLine($" %{isOobName} =w csgel {index}, %{countName}");
var anyOobName = GenVarName();
_builder.AppendLine($" %{anyOobName} =w or %{isNegativeName}, %{isOobName}");
var oobLabel = GenLabelName();
var notOobLabel = GenLabelName();
_builder.AppendLine($" jnz %{anyOobName}, @{oobLabel}, @{notOobLabel}");
_builder.AppendLine($"@{oobLabel}");
_builder.AppendLine($" call $nub_panic(l $oob_message, l {OutOfBoundsMessage.Length})");
_builder.AppendLine($"@{notOobLabel}");
}
private string GenerateArrayInitializer(ArrayInitializerNode arrayInitializer)
{
var capacity = GenerateExpression(arrayInitializer.Capacity);
var capacityInBytes = GenVarName();
_builder.AppendLine($" %{capacityInBytes} =l mul {capacity}, {QbeTypeSize(arrayInitializer.ItemType)}");
_builder.AppendLine($" %{capacityInBytes} =l mul {capacity}, {QbeTypeSize(arrayInitializer.ElementType)}");
var totalArraySize = GenVarName();
_builder.AppendLine($" %{totalArraySize} =l add %{capacityInBytes}, 8");
var outputName = GenVarName();
@@ -1326,9 +1372,16 @@ public class Generator
private string GenerateIdentifier(IdentifierNode identifier)
{
var variable = _variables[identifier.Identifier];
var outputName = GenVarName();
_builder.AppendLine($" %{outputName} ={SQT(identifier.Type)} load{SQT(identifier.Type)} {variable.Pointer}");
return $"%{outputName}";
if (IsLargeType(identifier.Type))
{
return variable.Pointer;
}
else
{
var outputName = GenVarName();
_builder.AppendLine($" %{outputName} ={SQT(identifier.Type)} load{SQT(identifier.Type)} {variable.Pointer}");
return $"%{outputName}";
}
}
private string GenerateLiteral(LiteralNode literal)