...
This commit is contained in:
@@ -264,7 +264,7 @@ public static class QBEGenerator
|
||||
throw new ArgumentOutOfRangeException(nameof(type));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static string EmitCopy(NubType type, string source)
|
||||
{
|
||||
var destination = VarName();
|
||||
@@ -301,8 +301,7 @@ public static class QBEGenerator
|
||||
case NubPointerType:
|
||||
case NubPrimitiveType:
|
||||
{
|
||||
_builder.AppendLine($" {destination} {QBEAssign(type)} {source}");
|
||||
break;
|
||||
return source;
|
||||
}
|
||||
case NubVoidType:
|
||||
case NubFuncType:
|
||||
@@ -311,7 +310,7 @@ public static class QBEGenerator
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(type));
|
||||
}
|
||||
|
||||
|
||||
return destination;
|
||||
}
|
||||
|
||||
@@ -649,7 +648,7 @@ public static class QBEGenerator
|
||||
{
|
||||
var destination = EmitExpression(assignment.Expression);
|
||||
Debug.Assert(destination.Kind == ValKind.Pointer);
|
||||
|
||||
|
||||
var source = EmitUnwrap(EmitExpression(assignment.Value));
|
||||
EmitCopyInto(assignment.Value.Type, source, destination.Name);
|
||||
}
|
||||
@@ -857,214 +856,117 @@ public static class QBEGenerator
|
||||
{
|
||||
var left = EmitUnwrap(EmitExpression(binaryExpression.Left));
|
||||
var right = EmitUnwrap(EmitExpression(binaryExpression.Right));
|
||||
|
||||
var outputName = VarName();
|
||||
var output = new Val(outputName, binaryExpression.Type, ValKind.Direct);
|
||||
|
||||
switch (binaryExpression.Operator)
|
||||
var instruction = EmitBinaryInstructionFor(binaryExpression.Operator, binaryExpression.Left.Type, left, right);
|
||||
|
||||
_builder.AppendLine($" {outputName} {QBEAssign(binaryExpression.Left.Type)} {instruction} {left}, {right}");
|
||||
return new Val(outputName, binaryExpression.Type, ValKind.Direct);
|
||||
}
|
||||
|
||||
private static string EmitBinaryInstructionFor(BinaryExpressionOperator op, NubType type, string left, string right)
|
||||
{
|
||||
if (op is
|
||||
BinaryExpressionOperator.Equal or
|
||||
BinaryExpressionOperator.NotEqual or
|
||||
BinaryExpressionOperator.GreaterThan or
|
||||
BinaryExpressionOperator.GreaterThanOrEqual or
|
||||
BinaryExpressionOperator.LessThan or
|
||||
BinaryExpressionOperator.LessThanOrEqual)
|
||||
{
|
||||
case BinaryExpressionOperator.Equal:
|
||||
char suffix;
|
||||
|
||||
if (type.Is8BitInteger)
|
||||
{
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
|
||||
if (type.IsSignedInteger)
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w ceql {left}, {right}");
|
||||
return output;
|
||||
_builder.AppendLine($" {left} =w extsb {left}");
|
||||
_builder.AppendLine($" {right} =w extsb {right}");
|
||||
}
|
||||
else
|
||||
{
|
||||
_builder.AppendLine($" {left} =w extub {left}");
|
||||
_builder.AppendLine($" {right} =w extub {right}");
|
||||
}
|
||||
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w ceqw {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w ceqw {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
break;
|
||||
suffix = 'w';
|
||||
}
|
||||
case BinaryExpressionOperator.NotEqual:
|
||||
else if (type.Is16BitInteger)
|
||||
{
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
|
||||
if (type.IsSignedInteger)
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w cnel {left}, {right}");
|
||||
return output;
|
||||
_builder.AppendLine($" {left} =w extsh {left}");
|
||||
_builder.AppendLine($" {right} =w extsh {right}");
|
||||
}
|
||||
else
|
||||
{
|
||||
_builder.AppendLine($" {left} =w extuh {left}");
|
||||
_builder.AppendLine($" {right} =w extuh {right}");
|
||||
}
|
||||
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w cnew {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w cnew {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
break;
|
||||
suffix = 'w';
|
||||
}
|
||||
case BinaryExpressionOperator.GreaterThan:
|
||||
else if (type.Is32BitInteger)
|
||||
{
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w csgtl {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w csgtw {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w csgtw {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
break;
|
||||
suffix = 'w';
|
||||
}
|
||||
case BinaryExpressionOperator.GreaterThanOrEqual:
|
||||
else if (type.Is64BitInteger)
|
||||
{
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w csgel {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w csgew {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w csgew {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
break;
|
||||
suffix = 'l';
|
||||
}
|
||||
case BinaryExpressionOperator.LessThan:
|
||||
else
|
||||
{
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w csltl {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w csltw {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w csltw {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
break;
|
||||
throw new NotSupportedException($"Unsupported type '{type}' for binary operator '{op}'");
|
||||
}
|
||||
case BinaryExpressionOperator.LessThanOrEqual:
|
||||
|
||||
if (op is BinaryExpressionOperator.Equal)
|
||||
{
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w cslel {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w cslew {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.Bool))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w cslew {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
break;
|
||||
return "ceq" + suffix;
|
||||
}
|
||||
case BinaryExpressionOperator.Plus:
|
||||
|
||||
if (op is BinaryExpressionOperator.NotEqual)
|
||||
{
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =l add {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w add {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
break;
|
||||
return "cne" + suffix;
|
||||
}
|
||||
case BinaryExpressionOperator.Minus:
|
||||
|
||||
string sign;
|
||||
|
||||
if (type.IsSignedInteger)
|
||||
{
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =l sub {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w sub {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
break;
|
||||
sign = "s";
|
||||
}
|
||||
case BinaryExpressionOperator.Multiply:
|
||||
else if (type.IsUnsignedInteger)
|
||||
{
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =l mul {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w mul {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
break;
|
||||
sign = "u";
|
||||
}
|
||||
case BinaryExpressionOperator.Divide:
|
||||
else if (type.IsFloat)
|
||||
{
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I64))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =l div {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
if (binaryExpression.Left.Type.Equals(NubPrimitiveType.I32))
|
||||
{
|
||||
_builder.AppendLine($" {outputName} =w div {left}, {right}");
|
||||
return output;
|
||||
}
|
||||
|
||||
break;
|
||||
sign = "";
|
||||
}
|
||||
default:
|
||||
else
|
||||
{
|
||||
throw new ArgumentOutOfRangeException();
|
||||
throw new NotSupportedException($"Unsupported type '{type}' for binary operator '{op}'");
|
||||
}
|
||||
|
||||
return op switch
|
||||
{
|
||||
BinaryExpressionOperator.GreaterThan => 'c' + sign + "gt" + suffix,
|
||||
BinaryExpressionOperator.GreaterThanOrEqual => 'c' + sign + "ge" + suffix,
|
||||
BinaryExpressionOperator.LessThan => 'c' + sign + "lt" + suffix,
|
||||
BinaryExpressionOperator.LessThanOrEqual => 'c' + sign + "le" + suffix,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(op), op, null)
|
||||
};
|
||||
}
|
||||
|
||||
throw new NotSupportedException($"Binary operator {binaryExpression.Operator} for types {binaryExpression.Left.Type} and {binaryExpression.Right.Type} not supported");
|
||||
return op switch
|
||||
{
|
||||
BinaryExpressionOperator.Plus => "add",
|
||||
BinaryExpressionOperator.Minus => "sub",
|
||||
BinaryExpressionOperator.Multiply => "mul",
|
||||
BinaryExpressionOperator.Divide => "div",
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(op))
|
||||
};
|
||||
}
|
||||
|
||||
private static Val EmitIdentifier(BoundIdentifierNode identifier)
|
||||
|
||||
Reference in New Issue
Block a user