fuck me
This commit is contained in:
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user