This commit is contained in:
nub31
2025-07-03 00:49:16 +02:00
parent e7aa16183a
commit 2159a731dd
5 changed files with 119 additions and 239 deletions

View File

@@ -8,7 +8,18 @@ struct Human
export func main(args: []cstring): i64
{
c::puts("john")
let x: i64
x = 23
if (x == 23)
{
c::printf("true\n")
}
else
{
c::printf("false\n")
}
return 0
}

View File

@@ -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:
@@ -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)

View File

@@ -4,42 +4,25 @@ namespace Syntax.Typing;
public abstract class NubType
{
public abstract bool ValueIsPointer { get; }
public bool Is8BitInteger => this is NubPrimitiveType { Kind: PrimitiveTypeKind.I8 or PrimitiveTypeKind.U8 };
public bool Is16BitInteger => this is NubPrimitiveType { Kind: PrimitiveTypeKind.I16 or PrimitiveTypeKind.U16 };
public bool Is32BitInteger => this is NubPrimitiveType { Kind: PrimitiveTypeKind.I32 or PrimitiveTypeKind.U32 };
public bool Is64BitInteger => this is NubPrimitiveType { Kind: PrimitiveTypeKind.I64 or PrimitiveTypeKind.U64 };
public bool IsInteger => this is NubPrimitiveType
{
Kind: PrimitiveTypeKind.I8
or PrimitiveTypeKind.I16
or PrimitiveTypeKind.I32
or PrimitiveTypeKind.I64
or PrimitiveTypeKind.U8
or PrimitiveTypeKind.U16
or PrimitiveTypeKind.U32
or PrimitiveTypeKind.U64
};
public bool IsSignedInteger => this is NubPrimitiveType { Kind: PrimitiveTypeKind.I8 or PrimitiveTypeKind.I16 or PrimitiveTypeKind.I32 or PrimitiveTypeKind.I64 };
public bool IsUnsignedInteger => this is NubPrimitiveType { Kind: PrimitiveTypeKind.U8 or PrimitiveTypeKind.U16 or PrimitiveTypeKind.U32 or PrimitiveTypeKind.U64 };
public bool IsInteger => IsSignedInteger || IsUnsignedInteger;
public bool IsFloat32 => this is NubPrimitiveType
{
Kind: PrimitiveTypeKind.F32
};
public bool IsFloat32 => this is NubPrimitiveType { Kind: PrimitiveTypeKind.F32 };
public bool IsFloat64 => this is NubPrimitiveType { Kind: PrimitiveTypeKind.F64 };
public bool IsFloat => IsFloat32 || IsFloat64;
public bool IsFloat64 => this is NubPrimitiveType
{
Kind: PrimitiveTypeKind.F64
};
public bool IsNumber => IsFloat32 || IsFloat64 || IsInteger;
public bool IsNumber => IsFloat || IsInteger;
public bool IsVoid => this is NubVoidType;
public bool IsString => this is NubStringType;
public bool IsCString => this is NubCStringType;
public bool IsBool => this is NubPrimitiveType
{
Kind: PrimitiveTypeKind.Bool
};
public bool IsBool => this is NubPrimitiveType { Kind: PrimitiveTypeKind.Bool };
public abstract override bool Equals(object? obj);
public abstract override int GetHashCode();
@@ -48,8 +31,6 @@ public abstract class NubType
public class NubCStringType : NubType
{
public override bool ValueIsPointer => true;
public override bool Equals(object? obj)
{
return obj is NubCStringType;
@@ -68,8 +49,6 @@ public class NubCStringType : NubType
public class NubStringType : NubType
{
public override bool ValueIsPointer => true;
public override bool Equals(object? obj)
{
return obj is NubStringType;
@@ -88,8 +67,6 @@ public class NubStringType : NubType
public class NubFuncType(NubType returnType, List<NubType> parameters) : NubType
{
public override bool ValueIsPointer => false;
public NubType ReturnType { get; } = returnType;
public List<NubType> Parameters { get; } = parameters;
@@ -111,8 +88,6 @@ public class NubFuncType(NubType returnType, List<NubType> parameters) : NubType
public class NubStructType(string @namespace, string name) : NubType
{
public override bool ValueIsPointer => true;
public string Namespace { get; } = @namespace;
public string Name { get; } = name;
@@ -134,8 +109,6 @@ public class NubStructType(string @namespace, string name) : NubType
public class NubPointerType(NubType baseType) : NubType
{
public override bool ValueIsPointer => false;
public NubType BaseType { get; } = baseType;
public override bool Equals(object? obj)
@@ -156,8 +129,6 @@ public class NubPointerType(NubType baseType) : NubType
public class NubArrayType(NubType elementType) : NubType
{
public override bool ValueIsPointer => true;
public NubType ElementType { get; } = elementType;
public override bool Equals(object? obj)
@@ -166,6 +137,7 @@ public class NubArrayType(NubType elementType) : NubType
{
return ElementType.Equals(other.ElementType);
}
return false;
}
@@ -182,8 +154,6 @@ public class NubArrayType(NubType elementType) : NubType
public class NubAnyType : NubType
{
public override bool ValueIsPointer => false;
public override string ToString() => "any";
public override bool Equals(object? obj)
@@ -199,8 +169,6 @@ public class NubAnyType : NubType
public class NubVoidType : NubType
{
public override bool ValueIsPointer => false;
public override string ToString() => "void";
public override bool Equals(object? obj)
@@ -216,8 +184,6 @@ public class NubVoidType : NubType
public class NubPrimitiveType(PrimitiveTypeKind kind) : NubType
{
public override bool ValueIsPointer => false;
public PrimitiveTypeKind Kind { get; } = kind;
public static NubPrimitiveType I64 => new(PrimitiveTypeKind.I64);

View File

@@ -5,5 +5,6 @@
_start:
mov rdi, rsp
call main
mov rdi, rax
mov rax, 60
syscall