Add void type

This commit is contained in:
nub31
2025-06-07 21:40:35 +02:00
parent 492fa5ffc7
commit 3f8d860e24
8 changed files with 190 additions and 188 deletions

View File

@@ -84,68 +84,6 @@ public class Generator
return _builder.ToString();
}
private enum TypeContext
{
FuncDef,
FuncCall,
}
private static string QBEType(NubType type, TypeContext context)
{
return context switch
{
TypeContext.FuncDef => type switch
{
NubArrayType => "l",
NubPointerType => "l",
NubPrimitiveType primitiveType => primitiveType.Kind switch
{
PrimitiveTypeKind.I64 => "l",
PrimitiveTypeKind.I32 => "w",
PrimitiveTypeKind.I16 => "sh",
PrimitiveTypeKind.I8 => "sb",
PrimitiveTypeKind.U64 => "l",
PrimitiveTypeKind.U32 => "w",
PrimitiveTypeKind.U16 => "uh",
PrimitiveTypeKind.U8 => "ub",
PrimitiveTypeKind.F64 => "d",
PrimitiveTypeKind.F32 => "s",
PrimitiveTypeKind.Bool => "w",
PrimitiveTypeKind.Any => throw new NotSupportedException("any type cannot be used in function definitions"),
_ => throw new ArgumentOutOfRangeException()
},
NubStructType structType => $":{structType.Namespace}_{structType.Name}",
NubFixedArrayType => "l",
_ => throw new ArgumentOutOfRangeException(nameof(type))
},
TypeContext.FuncCall => type switch
{
NubArrayType => "l",
NubPointerType => "l",
NubPrimitiveType pointerType => pointerType.Kind switch
{
PrimitiveTypeKind.I64 => "l",
PrimitiveTypeKind.I32 => "w",
PrimitiveTypeKind.I16 => "sh",
PrimitiveTypeKind.I8 => "sb",
PrimitiveTypeKind.U64 => "l",
PrimitiveTypeKind.U32 => "w",
PrimitiveTypeKind.U16 => "uh",
PrimitiveTypeKind.U8 => "ub",
PrimitiveTypeKind.F64 => "d",
PrimitiveTypeKind.F32 => "s",
PrimitiveTypeKind.Bool => "w",
PrimitiveTypeKind.Any => "l",
_ => throw new ArgumentOutOfRangeException()
},
NubStructType structType => $":{structType.Namespace}_{structType.Name}",
NubFixedArrayType => "l",
_ => throw new ArgumentOutOfRangeException(nameof(type))
},
_ => throw new ArgumentOutOfRangeException(nameof(context), context, null)
};
}
private static string QBEStore(NubType type)
{
return $"store{type switch
@@ -165,12 +103,11 @@ public class Generator
PrimitiveTypeKind.F64 => "d",
PrimitiveTypeKind.F32 => "s",
PrimitiveTypeKind.Bool => "w",
PrimitiveTypeKind.Any => throw new NotSupportedException("any type cannot be used in store instructions"),
_ => throw new ArgumentOutOfRangeException()
_ => throw new UnreachableException()
},
NubStructType => "l",
NubFixedArrayType => "l",
_ => throw new ArgumentOutOfRangeException(nameof(type))
_ => throw new NotSupportedException($"'{type}' type cannot be used in store instructions")
}}";
}
@@ -193,12 +130,11 @@ public class Generator
PrimitiveTypeKind.F64 => "d",
PrimitiveTypeKind.F32 => "s",
PrimitiveTypeKind.Bool => "w",
PrimitiveTypeKind.Any => throw new NotSupportedException("any type cannot be used in load instructions"),
_ => throw new ArgumentOutOfRangeException()
_ => throw new UnreachableException()
},
NubStructType => "l",
NubFixedArrayType => "l",
_ => throw new ArgumentOutOfRangeException(nameof(type))
_ => throw new NotSupportedException($"'{type}' type cannot be used in load instructions")
}}";
}
@@ -221,12 +157,11 @@ public class Generator
PrimitiveTypeKind.F64 => "d",
PrimitiveTypeKind.F32 => "s",
PrimitiveTypeKind.Bool => "w",
PrimitiveTypeKind.Any => throw new NotSupportedException("any type cannot be used in variables"),
_ => throw new ArgumentOutOfRangeException()
_ => throw new UnreachableException()
},
NubStructType => "l",
NubFixedArrayType => "l",
_ => throw new ArgumentOutOfRangeException(nameof(type))
_ => throw new NotSupportedException($"'{type}' type cannot be used in variables")
}}";
}
@@ -240,7 +175,6 @@ public class Generator
{
case PrimitiveTypeKind.I64:
case PrimitiveTypeKind.U64:
case PrimitiveTypeKind.Any:
return 8;
case PrimitiveTypeKind.I32:
case PrimitiveTypeKind.U32:
@@ -304,18 +238,59 @@ public class Generator
}
_builder.Append("function ");
if (node.ReturnType.HasValue)
if (node.ReturnType is not NubVoidType)
{
_builder.Append($"{QBEType(node.ReturnType.Value, TypeContext.FuncDef)} ");
}
else if (!node.ReturnType.HasValue && node.Name == "main")
{
_builder.Append("l ");
_builder.Append(node.ReturnType switch
{
NubArrayType => "l",
NubPointerType => "l",
NubPrimitiveType primitiveType => primitiveType.Kind switch
{
PrimitiveTypeKind.I64 => "l",
PrimitiveTypeKind.I32 => "w",
PrimitiveTypeKind.I16 => "sh",
PrimitiveTypeKind.I8 => "sb",
PrimitiveTypeKind.U64 => "l",
PrimitiveTypeKind.U32 => "w",
PrimitiveTypeKind.U16 => "uh",
PrimitiveTypeKind.U8 => "ub",
PrimitiveTypeKind.F64 => "d",
PrimitiveTypeKind.F32 => "s",
PrimitiveTypeKind.Bool => "w",
_ => throw new UnreachableException()
},
NubStructType structType => $":{structType.Namespace}_{structType.Name}",
NubFixedArrayType => "l",
_ => throw new NotSupportedException($"'{node.ReturnType}' type cannot be used as a function return type")
});
_builder.Append(' ');
}
_builder.Append(_funcNames[node]);
var parameterStrings = node.Parameters.Select(parameter => parameter.Variadic ? "..." : $"{QBEType(parameter.Type, TypeContext.FuncDef)} %{parameter.Name}");
var parameterStrings = node.Parameters.Select(parameter => parameter.Variadic ? "..." : $"{parameter.Type switch
{
NubArrayType => "l",
NubPointerType => "l",
NubPrimitiveType primitiveType => primitiveType.Kind switch
{
PrimitiveTypeKind.I64 => "l",
PrimitiveTypeKind.I32 => "w",
PrimitiveTypeKind.I16 => "sh",
PrimitiveTypeKind.I8 => "sb",
PrimitiveTypeKind.U64 => "l",
PrimitiveTypeKind.U32 => "w",
PrimitiveTypeKind.U16 => "uh",
PrimitiveTypeKind.U8 => "ub",
PrimitiveTypeKind.F64 => "d",
PrimitiveTypeKind.F32 => "s",
PrimitiveTypeKind.Bool => "w",
_ => throw new UnreachableException()
},
NubStructType structType => $":{structType.Namespace}_{structType.Name}",
NubFixedArrayType => "l",
_ => throw new NotSupportedException($"'{parameter.Type}' type cannot be used as a function parameter type")
}} %{parameter.Name}");
_builder.AppendLine($"({string.Join(", ", parameterStrings)}) {{");
_builder.AppendLine("@start");
@@ -324,25 +299,25 @@ public class Generator
{
var parameterName = parameter.Name;
switch (QBEType(parameter.Type, TypeContext.FuncDef))
{
case "sb":
parameterName = GenVarName();
_builder.AppendLine($" {parameterName} =w extsb %{parameter.Name}");
break;
case "ub":
parameterName = GenVarName();
_builder.AppendLine($" {parameterName} =w extub %{parameter.Name}");
break;
case "sh":
parameterName = GenVarName();
_builder.AppendLine($" {parameterName} =w extsh %{parameter.Name}");
break;
case "uh":
parameterName = GenVarName();
_builder.AppendLine($" {parameterName} =w extuh %{parameter.Name}");
break;
}
// switch (QBEType(parameter.Type))
// {
// case "sb":
// parameterName = GenVarName();
// _builder.AppendLine($" {parameterName} =w extsb %{parameter.Name}");
// break;
// case "ub":
// parameterName = GenVarName();
// _builder.AppendLine($" {parameterName} =w extub %{parameter.Name}");
// break;
// case "sh":
// parameterName = GenVarName();
// _builder.AppendLine($" {parameterName} =w extsh %{parameter.Name}");
// break;
// case "uh":
// parameterName = GenVarName();
// _builder.AppendLine($" {parameterName} =w extuh %{parameter.Name}");
// break;
// }
if (IsLargeType(parameter.Type))
{
@@ -364,13 +339,7 @@ public class Generator
if (node.Body.Statements.LastOrDefault() is not ReturnNode)
{
if (!node.ReturnType.HasValue && node.Name == "main")
{
_builder.AppendLine();
_builder.AppendLine(" # Implicit return for main");
_builder.AppendLine(" ret 0");
}
else if (!node.ReturnType.HasValue)
if (node.ReturnType is NubVoidType)
{
_builder.AppendLine();
_builder.AppendLine(" # Implicit return");
@@ -386,40 +355,34 @@ public class Generator
_builder.Append($"type :{structDefinition.Namespace}_{structDefinition.Name} = {{ ");
foreach (var structDefinitionField in structDefinition.Fields)
{
var fieldDefinition = GenerateFieldType(structDefinitionField.Type);
_builder.Append(fieldDefinition + ", ");
var fieldQbeType = structDefinitionField.Type switch
{
NubArrayType => "l",
NubPointerType => "l",
NubPrimitiveType primitiveType => primitiveType.Kind switch
{
PrimitiveTypeKind.I64 => "l",
PrimitiveTypeKind.I32 => "w",
PrimitiveTypeKind.I16 => "h",
PrimitiveTypeKind.I8 => "b",
PrimitiveTypeKind.U64 => "l",
PrimitiveTypeKind.U32 => "w",
PrimitiveTypeKind.U16 => "h",
PrimitiveTypeKind.U8 => "b",
PrimitiveTypeKind.F64 => "d",
PrimitiveTypeKind.F32 => "s",
PrimitiveTypeKind.Bool => "w",
_ => throw new UnreachableException()
},
NubStructType structType => $":{structType.Namespace}_{structType.Name}",
NubFixedArrayType fixedArrayType => $"b {SizeOf(fixedArrayType)}",
_ => throw new NotSupportedException($"'{structDefinitionField.Type}' type cannot be used in structs")
};
_builder.Append(fieldQbeType + ", ");
}
_builder.AppendLine("}");
}
private string GenerateFieldType(NubType type)
{
return type switch
{
NubArrayType => "l",
NubPointerType => "l",
NubPrimitiveType primitiveType => primitiveType.Kind switch
{
PrimitiveTypeKind.I64 => "l",
PrimitiveTypeKind.I32 => "w",
PrimitiveTypeKind.I16 => "h",
PrimitiveTypeKind.I8 => "b",
PrimitiveTypeKind.U64 => "l",
PrimitiveTypeKind.U32 => "w",
PrimitiveTypeKind.U16 => "h",
PrimitiveTypeKind.U8 => "b",
PrimitiveTypeKind.F64 => "d",
PrimitiveTypeKind.F32 => "s",
PrimitiveTypeKind.Bool => "w",
PrimitiveTypeKind.Any => throw new NotSupportedException("any type cannot be used in structs"),
_ => throw new ArgumentOutOfRangeException()
},
NubStructType structType => $":{structType.Namespace}_{structType.Name}",
NubFixedArrayType fixedArrayType => $"b {SizeOf(fixedArrayType)}",
_ => throw new ArgumentOutOfRangeException(nameof(type))
};
}
private void GenerateStatement(StatementNode statement)
{
switch (statement)
@@ -1739,13 +1702,35 @@ public class Generator
var parameter = funcCall.Parameters[i];
var result = GenerateExpression(parameter);
var qbeParameterType = QBEType(parameter.Type, TypeContext.FuncCall);
var qbeParameterType = parameter.Type switch
{
NubArrayType => "l",
NubPointerType => "l",
NubPrimitiveType pointerType => pointerType.Kind switch
{
PrimitiveTypeKind.I64 => "l",
PrimitiveTypeKind.I32 => "w",
PrimitiveTypeKind.I16 => "sh",
PrimitiveTypeKind.I8 => "sb",
PrimitiveTypeKind.U64 => "l",
PrimitiveTypeKind.U32 => "w",
PrimitiveTypeKind.U16 => "uh",
PrimitiveTypeKind.U8 => "ub",
PrimitiveTypeKind.F64 => "d",
PrimitiveTypeKind.F32 => "s",
PrimitiveTypeKind.Bool => "w",
_ => throw new ArgumentOutOfRangeException()
},
NubStructType structType => $":{structType.Namespace}_{structType.Name}",
NubFixedArrayType => "l",
_ => throw new NotSupportedException($"'{parameter.Type}' type cannot be used in function calls")
};
parameterStrings.Add($"{qbeParameterType} {result}");
}
var funcName = _funcNames[funcDefinition];
if (funcDefinition.ReturnType.HasValue)
if (funcDefinition.ReturnType is not NubVoidType)
{
var outputName = GenVarName();
_builder.AppendLine($" {outputName} {QBEAssign(funcCall.Type)} call {funcName}({string.Join(", ", parameterStrings)})");