improve addressof

This commit is contained in:
nub31
2025-06-08 13:54:10 +02:00
parent 6ea9cc0d54
commit 72eb3c89d8
12 changed files with 131 additions and 668 deletions

View File

@@ -5,15 +5,19 @@ struct Human {
}
export func main(args: []^string): i64 {
let x = [3]f64
let age: u64 = 23
x[0] = 1
x[1] = 2
x[2] = 3
let me = alloc Human {
age = &age
}
c::printf("%f\n", x[0])
c::printf("%f\n", x[1])
c::printf("%f\n", x[2])
me.age^ = 24.5
test(me.age^)
return 0
}
func test(me: u64) {
c::printf("%d\n", me)
}

View File

@@ -49,7 +49,7 @@ error = error || typeCheckResult.HasErrors;
if (error) return 1;
var generator = new Generator();
var generator = new QBEGenerator();
var result = generator.Generate(files);
Console.Out.Write(result);

View File

@@ -10,7 +10,7 @@ using Nub.Lang.Frontend.Typing;
namespace Nub.Lang.Frontend.Generation;
public class Generator
public class QBEGenerator
{
private const string OutOfBoundsMessage = "Index is out of bounds\\n";
@@ -297,7 +297,7 @@ public class Generator
foreach (var parameter in node.Parameters)
{
var parameterName = parameter.Name;
var parameterName = "%" + parameter.Name;
if (parameter.Type is NubPrimitiveType primitiveType)
{
@@ -319,24 +319,18 @@ public class Generator
parameterName = GenVarName();
_builder.AppendLine($" {parameterName} =w extub %{parameter.Name}");
break;
default:
throw new ArgumentOutOfRangeException();
}
}
_variables[parameter.Name] = parameterName;
}
_builder.AppendLine();
GenerateBlock(node.Body);
if (node.Body.Statements.LastOrDefault() is not ReturnNode)
{
if (node.ReturnType is NubVoidType)
{
_builder.AppendLine();
_builder.AppendLine(" # Implicit return");
_builder.AppendLine(" ret");
}
}
@@ -436,17 +430,10 @@ public class Generator
var adjustedIndex = GenVarName();
_builder.AppendLine($" {adjustedIndex} =l mul {index}, {SizeOf(arrayType.ElementType)}");
var offsetName = GenVarName();
_builder.AppendLine($" {offsetName} =l add {startName}, {adjustedIndex}");
var pointer = GenVarName();
_builder.AppendLine($" {pointer} =l add {startName}, {adjustedIndex}");
if (IsLargeType(arrayType.ElementType))
{
_builder.AppendLine($" blit {value}, {offsetName}, {SizeOf(arrayType.ElementType)}");
}
else
{
_builder.AppendLine($" {QBEStore(arrayType.ElementType)} {value}, {offsetName}");
}
GenerateCopy(arrayType.ElementType, value, pointer);
break;
}
case NubFixedArrayType fixedArrayType:
@@ -457,17 +444,10 @@ public class Generator
var adjustedIndex = GenVarName();
_builder.AppendLine($" {adjustedIndex} =l mul {index}, {SizeOf(fixedArrayType.ElementType)}");
var offsetName = GenVarName();
_builder.AppendLine($" {offsetName} =l add {startName}, {adjustedIndex}");
var pointer = GenVarName();
_builder.AppendLine($" {pointer} =l add {startName}, {adjustedIndex}");
if (IsLargeType(fixedArrayType.ElementType))
{
_builder.AppendLine($" blit {value}, {offsetName}, {SizeOf(fixedArrayType.ElementType)}");
}
else
{
_builder.AppendLine($" {QBEStore(fixedArrayType.ElementType)} {value}, {offsetName}");
}
GenerateCopy(fixedArrayType.ElementType, value, pointer);
break;
}
default:
@@ -501,17 +481,9 @@ public class Generator
private void GenerateDereferenceAssignment(DereferenceAssignmentNode dereferenceAssignment)
{
var location = GenerateExpression(dereferenceAssignment.Dereference.Expression);
var pointer = GenerateExpression(dereferenceAssignment.Dereference.Expression);
var value = GenerateExpression(dereferenceAssignment.Value);
if (IsLargeType(dereferenceAssignment.Value.Type))
{
_builder.AppendLine($" blit {value}, {location}, {SizeOf(dereferenceAssignment.Value.Type)}");
}
else
{
_builder.AppendLine($" {QBEStore(dereferenceAssignment.Value.Type)} {value}, {location}");
}
GenerateCopy(dereferenceAssignment.Value.Type, value, pointer);
}
private void GenerateIf(IfNode ifStatement)
@@ -547,20 +519,13 @@ public class Generator
var offset = LookupMemberOffset(structDefinition, memberAssignment.MemberAccess.Member);
var item = GenerateExpression(memberAssignment.MemberAccess.Expression);
var offsetName = GenVarName();
var pointer = GenVarName();
_builder.AppendLine($" {offsetName} =l add {item}, {offset}");
_builder.AppendLine($" {pointer} =l add {item}, {offset}");
var value = GenerateExpression(memberAssignment.Value);
if (IsLargeType(memberAssignment.Value.Type))
{
_builder.AppendLine($" blit {value}, {offsetName}, {SizeOf(memberAssignment.Value.Type)}");
}
else
{
_builder.AppendLine($" {QBEStore(memberAssignment.Value.Type)} {value}, {offsetName}");
}
GenerateCopy(memberAssignment.Value.Type, value, pointer);
}
private void GenerateReturn(ReturnNode @return)
@@ -575,48 +540,32 @@ public class Generator
_builder.AppendLine(" ret");
}
}
private void GenerateVariableAssignment(VariableAssignmentNode variableAssignment)
{
var result = GenerateExpression(variableAssignment.Value);
_builder.AppendLine($" storel {result}, {_variables[variableAssignment.Identifier.Identifier]}");
var value = GenerateExpression(variableAssignment.Value);
var pointer = _variables[variableAssignment.Identifier.Identifier];
GenerateCopy(variableAssignment.Value.Type, value, pointer);
}
private void GenerateVariableDeclaration(VariableDeclarationNode variableDeclaration)
{
var type = variableDeclaration.ExplicitType.Value ?? variableDeclaration.Value.Value?.Type!;
string pointerName;
var type = variableDeclaration.ExplicitType.Value ?? variableDeclaration.Value.Value!.Type;
var pointer = GenVarName();
_builder.AppendLine($" {pointer} =l alloc8 {SizeOf(type)}");
if (variableDeclaration.Value.HasValue)
{
var result = GenerateExpression(variableDeclaration.Value.Value);
if (IsLargeType(type))
{
pointerName = result;
}
else
{
pointerName = GenVarName();
_builder.AppendLine($" {pointerName} =l alloc8 {SizeOf(type)}");
_builder.AppendLine($" {QBEStore(type)} {result}, {pointerName}");
}
var value = GenerateExpression(variableDeclaration.Value.Value);
GenerateCopy(variableDeclaration.Value.Value.Type, value, pointer);
}
else
{
pointerName = GenVarName();
_builder.AppendLine($" {pointerName} =l alloc8 {SizeOf(type)}");
if (IsLargeType(type))
{
_builder.AppendLine($" call $nub_memset(l {pointerName}, ub 0, l {SizeOf(type)})");
}
else
{
_builder.AppendLine($" {QBEStore(type)} 0, {pointerName}");
}
var pointerName = GenVarName();
_variables[variableDeclaration.Name] = pointerName;
}
_variables[variableDeclaration.Name] = pointerName;
_variables[variableDeclaration.Name] = pointer;
}
private void GenerateWhile(WhileNode whileStatement)
@@ -645,10 +594,9 @@ public class Generator
return expression switch
{
AddressOfNode addressOf => GenerateAddressOf(addressOf),
ArrayIndexAccessNode arrayIndex => GenerateArrayIndex(arrayIndex),
ArrayIndexAccessNode arrayIndex => GenerateArrayAccessIndex(arrayIndex),
ArrayInitializerNode arrayInitializer => GenerateArrayInitializer(arrayInitializer),
BinaryExpressionNode binaryExpression => GenerateBinaryExpression(binaryExpression),
// CastNode cast => GenerateCast(cast),
DereferenceNode dereference => GenerateDereference(dereference),
FixedArrayInitializerNode fixedArrayInitializer => GenerateFixedArrayInitializer(fixedArrayInitializer),
FuncCallNode funcCallExpression => GenerateFuncCall(funcCallExpression),
@@ -661,12 +609,12 @@ public class Generator
};
}
private string GenerateArrayIndex(ArrayIndexAccessNode arrayIndexAccess)
private string GenerateArrayIndexPointer(ArrayIndexAccessNode arrayIndexAccess)
{
var array = GenerateExpression(arrayIndexAccess.Array);
var index = GenerateExpression(arrayIndexAccess.Index);
GenerateArrayBoundsCheck(array, index);
switch (arrayIndexAccess.Array.Type)
{
case NubArrayType arrayType:
@@ -677,17 +625,7 @@ public class Generator
_builder.AppendLine($" {offsetPointerName} =l mul {index}, {SizeOf(arrayType.ElementType)}");
var resultPointerName = GenVarName();
_builder.AppendLine($" {resultPointerName} =l add {firstItemPointerName}, {offsetPointerName}");
if (IsLargeType(arrayType.ElementType))
{
return resultPointerName;
}
else
{
var outputName = GenVarName();
_builder.AppendLine($" {outputName} {QBEAssign(arrayType.ElementType)} {QBELoad(arrayType.ElementType)} {resultPointerName}");
return outputName;
}
return resultPointerName;
}
case NubFixedArrayType fixedArrayType:
{
@@ -697,17 +635,7 @@ public class Generator
_builder.AppendLine($" {offsetPointerName} =l mul {index}, {SizeOf(fixedArrayType.ElementType)}");
var resultPointerName = GenVarName();
_builder.AppendLine($" {resultPointerName} =l add {firstItemPointerName}, {offsetPointerName}");
if (IsLargeType(fixedArrayType.ElementType))
{
return resultPointerName;
}
else
{
var outputName = GenVarName();
_builder.AppendLine($" {outputName} {QBEAssign(fixedArrayType.ElementType)} {QBELoad(fixedArrayType.ElementType)} {resultPointerName}");
return outputName;
}
return resultPointerName;
}
default:
{
@@ -715,6 +643,22 @@ public class Generator
}
}
}
private string GenerateArrayAccessIndex(ArrayIndexAccessNode arrayIndexAccess)
{
var pointerName = GenerateArrayIndexPointer(arrayIndexAccess);
if (IsLargeType(arrayIndexAccess.Type))
{
return pointerName;
}
else
{
var outputName = GenVarName();
_builder.AppendLine($" {outputName} {QBEAssign(arrayIndexAccess.Type)} {QBELoad(arrayIndexAccess.Type)} {pointerName}");
return outputName;
}
}
private void GenerateArrayBoundsCheck(string array, string index)
{
@@ -768,30 +712,18 @@ public class Generator
private string GenerateAddressOf(AddressOfNode addressOf)
{
var result = GenerateExpression(addressOf.Expression);
var outputName = GenVarName();
switch (addressOf.Expression.Type)
switch (addressOf.Expression)
{
case NubPointerType:
case NubStructType:
case NubPrimitiveType { Kind: PrimitiveTypeKind.I64 }:
case NubPrimitiveType { Kind: PrimitiveTypeKind.F64 }:
case NubPrimitiveType { Kind: PrimitiveTypeKind.U64 }:
_builder.AppendLine($" {outputName} =l alloc8 8");
_builder.AppendLine($" storel {result}, {outputName}");
return outputName;
case NubPrimitiveType { Kind: PrimitiveTypeKind.I32 }:
case NubPrimitiveType { Kind: PrimitiveTypeKind.U32 }:
case NubPrimitiveType { Kind: PrimitiveTypeKind.I16 }:
case NubPrimitiveType { Kind: PrimitiveTypeKind.U16 }:
case NubPrimitiveType { Kind: PrimitiveTypeKind.I8 }:
case NubPrimitiveType { Kind: PrimitiveTypeKind.U8 }:
case NubPrimitiveType { Kind: PrimitiveTypeKind.F32 }:
_builder.AppendLine($" {outputName} =l alloc8 4");
_builder.AppendLine($" storew {result}, {outputName}");
return outputName;
case ArrayIndexAccessNode arrayIndexAccess:
return GenerateArrayIndexPointer(arrayIndexAccess);
case DereferenceNode dereference:
return GenerateExpression(dereference.Expression);
case IdentifierNode identifier:
return _variables[identifier.Identifier];
case MemberAccessNode memberAccess:
return GenerateMemberAccessPointer(memberAccess);
default:
throw new ArgumentOutOfRangeException();
throw new UnreachableException();
}
}
@@ -1021,462 +953,9 @@ public class Generator
throw new NotSupportedException($"Binary operator {binaryExpression.Operator} for types {binaryExpression.Left.Type} and {binaryExpression.Right.Type} not supported");
}
// private string GenerateCast(CastNode cast)
// {
// var input = GenerateExpression(cast.Expression);
// var outputType = cast.TargetType;
// var inputType = cast.Expression.Type;
//
// if (inputType.Equals(outputType))
// {
// return input;
// }
//
// if (outputType is not NubPrimitiveType primitiveOutputType || inputType is not NubPrimitiveType primitiveInputType)
// {
// throw new NotSupportedException("Casting is only supported for primitive types");
// }
//
// var outputName = GenVarName();
//
// switch (primitiveInputType.Kind)
// {
// case PrimitiveTypeKind.I64:
// switch (primitiveOutputType.Kind)
// {
// case PrimitiveTypeKind.I64:
// case PrimitiveTypeKind.U64:
// case PrimitiveTypeKind.I32:
// case PrimitiveTypeKind.U32:
// case PrimitiveTypeKind.I16:
// case PrimitiveTypeKind.U16:
// case PrimitiveTypeKind.I8:
// case PrimitiveTypeKind.Any:
// case PrimitiveTypeKind.U8:
// return input;
// case PrimitiveTypeKind.F64:
// _builder.AppendLine($" {outputName} =d sltof {input}");
// return outputName;
// case PrimitiveTypeKind.F32:
// _builder.AppendLine($" {outputName} =s sltof {input}");
// return outputName;
// case PrimitiveTypeKind.String:
// _builder.AppendLine($" {outputName} =l call $nub_i64_to_string(l {input})");
// return outputName;
// case PrimitiveTypeKind.Bool:
// default:
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
// }
// case PrimitiveTypeKind.I32:
// switch (primitiveOutputType.Kind)
// {
// case PrimitiveTypeKind.I64:
// case PrimitiveTypeKind.U64:
// _builder.AppendLine($" {outputName} =l extsw {input}");
// return outputName;
// case PrimitiveTypeKind.I32:
// case PrimitiveTypeKind.U32:
// case PrimitiveTypeKind.I16:
// case PrimitiveTypeKind.U16:
// case PrimitiveTypeKind.I8:
// case PrimitiveTypeKind.U8:
// return input;
// case PrimitiveTypeKind.F64:
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =l extsw {input}");
// _builder.AppendLine($" {outputName} =d sltof {extName}");
// return outputName;
// case PrimitiveTypeKind.F32:
// _builder.AppendLine($" {outputName} =s swtof {input}");
// return outputName;
// case PrimitiveTypeKind.String:
// _builder.AppendLine($" {outputName} =l call $nub_i32_to_string(w {input})");
// return outputName;
// case PrimitiveTypeKind.Any:
// var extAnyName = GenVarName();
// _builder.AppendLine($" {extAnyName} =l extsw {input}");
// return extAnyName;
// case PrimitiveTypeKind.Bool:
// default:
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
// }
// case PrimitiveTypeKind.I16:
// switch (primitiveOutputType.Kind)
// {
// case PrimitiveTypeKind.I64:
// case PrimitiveTypeKind.U64:
// _builder.AppendLine($" {outputName} =l extsh {input}");
// return outputName;
// case PrimitiveTypeKind.I32:
// case PrimitiveTypeKind.U32:
// _builder.AppendLine($" {outputName} =w extsh {input}");
// return outputName;
// case PrimitiveTypeKind.I16:
// case PrimitiveTypeKind.U16:
// case PrimitiveTypeKind.I8:
// case PrimitiveTypeKind.U8:
// return input;
// case PrimitiveTypeKind.F64:
// {
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =l extsh {input}");
// _builder.AppendLine($" {outputName} =d sltof {extName}");
// return outputName;
// }
// case PrimitiveTypeKind.F32:
// {
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =w extsh {input}");
// _builder.AppendLine($" {outputName} =s swtof {extName}");
// return outputName;
// }
// case PrimitiveTypeKind.String:
// {
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =w extsh {input}");
// _builder.AppendLine($" {outputName} =l call $nub_i32_to_string(w {extName})");
// return outputName;
// }
// case PrimitiveTypeKind.Any:
// {
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =l extsh {input}");
// return extName;
// }
// case PrimitiveTypeKind.Bool:
// default:
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
// }
// case PrimitiveTypeKind.I8:
// switch (primitiveOutputType.Kind)
// {
// case PrimitiveTypeKind.I64:
// case PrimitiveTypeKind.U64:
// _builder.AppendLine($" {outputName} =l extsb {input}");
// return outputName;
// case PrimitiveTypeKind.I32:
// case PrimitiveTypeKind.U32:
// case PrimitiveTypeKind.I16:
// case PrimitiveTypeKind.U16:
// _builder.AppendLine($" {outputName} =w extsb {input}");
// return outputName;
// case PrimitiveTypeKind.I8:
// case PrimitiveTypeKind.U8:
// return input;
// case PrimitiveTypeKind.F64:
// {
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =l extsb {input}");
// _builder.AppendLine($" {outputName} =d sltof {extName}");
// return outputName;
// }
// case PrimitiveTypeKind.F32:
// {
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =w extsb {input}");
// _builder.AppendLine($" {outputName} =s swtof {extName}");
// return outputName;
// }
// case PrimitiveTypeKind.String:
// {
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =w extsb {input}");
// _builder.AppendLine($" {outputName} =l call $nub_i32_to_string(w {extName})");
// return outputName;
// }
// case PrimitiveTypeKind.Any:
// {
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =l extsb {input}");
// return extName;
// }
// case PrimitiveTypeKind.Bool:
// default:
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
// }
// case PrimitiveTypeKind.U64:
// switch (primitiveOutputType.Kind)
// {
// case PrimitiveTypeKind.I64:
// case PrimitiveTypeKind.U64:
// case PrimitiveTypeKind.I32:
// case PrimitiveTypeKind.U32:
// case PrimitiveTypeKind.I16:
// case PrimitiveTypeKind.U16:
// case PrimitiveTypeKind.I8:
// case PrimitiveTypeKind.U8:
// return input;
// case PrimitiveTypeKind.F64:
// _builder.AppendLine($" {outputName} =d ultof {input}");
// return outputName;
// case PrimitiveTypeKind.F32:
// _builder.AppendLine($" {outputName} =s ultof {input}");
// return outputName;
// case PrimitiveTypeKind.String:
// _builder.AppendLine($" {outputName} =l call $nub_u64_to_string(l {input})");
// return outputName;
// case PrimitiveTypeKind.Any:
// return input;
// case PrimitiveTypeKind.Bool:
// default:
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
// }
// case PrimitiveTypeKind.U32:
// switch (primitiveOutputType.Kind)
// {
// case PrimitiveTypeKind.I64:
// case PrimitiveTypeKind.U64:
// _builder.AppendLine($" {outputName} =l extuw {input}");
// return outputName;
// case PrimitiveTypeKind.I32:
// case PrimitiveTypeKind.U32:
// case PrimitiveTypeKind.I16:
// case PrimitiveTypeKind.U16:
// case PrimitiveTypeKind.I8:
// case PrimitiveTypeKind.U8:
// return input;
// case PrimitiveTypeKind.F64:
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =l extuw {input}");
// _builder.AppendLine($" {outputName} =d ultof {extName}");
// return outputName;
// case PrimitiveTypeKind.F32:
// _builder.AppendLine($" {outputName} =s uwtof {input}");
// return outputName;
// case PrimitiveTypeKind.String:
// _builder.AppendLine($" {outputName} =l call $nub_u32_to_string(w {input})");
// return outputName;
// case PrimitiveTypeKind.Any:
// var extAnyName = GenVarName();
// _builder.AppendLine($" {extAnyName} =l extuw {input}");
// return extAnyName;
// case PrimitiveTypeKind.Bool:
// default:
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
// }
// case PrimitiveTypeKind.U16:
// switch (primitiveOutputType.Kind)
// {
// case PrimitiveTypeKind.I64:
// case PrimitiveTypeKind.U64:
// _builder.AppendLine($" {outputName} =l extuh {input}");
// return outputName;
// case PrimitiveTypeKind.I32:
// case PrimitiveTypeKind.U32:
// _builder.AppendLine($" {outputName} =w extuh {input}");
// return outputName;
// case PrimitiveTypeKind.I16:
// case PrimitiveTypeKind.U16:
// case PrimitiveTypeKind.I8:
// case PrimitiveTypeKind.U8:
// return input;
// case PrimitiveTypeKind.F64:
// {
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =l extuh {input}");
// _builder.AppendLine($" {outputName} =d ultof {extName}");
// return outputName;
// }
// case PrimitiveTypeKind.F32:
// {
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =w extuh {input}");
// _builder.AppendLine($" {outputName} =s uwtof {extName}");
// return outputName;
// }
// case PrimitiveTypeKind.String:
// {
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =w extuh {input}");
// _builder.AppendLine($" {outputName} =l call $nub_u32_to_string(w {extName})");
// return outputName;
// }
// case PrimitiveTypeKind.Any:
// {
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =l extuh {input}");
// return extName;
// }
// case PrimitiveTypeKind.Bool:
// default:
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
// }
// case PrimitiveTypeKind.U8:
// switch (primitiveOutputType.Kind)
// {
// case PrimitiveTypeKind.I64:
// case PrimitiveTypeKind.U64:
// _builder.AppendLine($" {outputName} =l extub {input}");
// return outputName;
// case PrimitiveTypeKind.I32:
// case PrimitiveTypeKind.U32:
// case PrimitiveTypeKind.I16:
// case PrimitiveTypeKind.U16:
// _builder.AppendLine($" {outputName} =w extub {input}");
// return outputName;
// case PrimitiveTypeKind.I8:
// case PrimitiveTypeKind.U8:
// return input;
// case PrimitiveTypeKind.F64:
// {
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =l extub {input}");
// _builder.AppendLine($" {outputName} =d ultof {extName}");
// return outputName;
// }
// case PrimitiveTypeKind.F32:
// {
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =w extub {input}");
// _builder.AppendLine($" {outputName} =s uwtof {extName}");
// return outputName;
// }
// case PrimitiveTypeKind.String:
// {
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =w extub {input}");
// _builder.AppendLine($" {outputName} =l call $nub_u32_to_string(w {extName})");
// return outputName;
// }
// case PrimitiveTypeKind.Any:
// {
// var extName = GenVarName();
// _builder.AppendLine($" {extName} =l extub {input}");
// return extName;
// }
// case PrimitiveTypeKind.Bool:
// default:
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
// }
// case PrimitiveTypeKind.F64:
// switch (primitiveOutputType.Kind)
// {
// case PrimitiveTypeKind.F64:
// case PrimitiveTypeKind.Any:
// return input;
// case PrimitiveTypeKind.F32:
// _builder.AppendLine($" {outputName} =s dtos {input}");
// return outputName;
// case PrimitiveTypeKind.I64:
// _builder.AppendLine($" {outputName} =l dtosi {input}");
// return outputName;
// case PrimitiveTypeKind.I32:
// case PrimitiveTypeKind.I16:
// case PrimitiveTypeKind.I8:
// _builder.AppendLine($" {outputName} =w dtosi {input}");
// return outputName;
// case PrimitiveTypeKind.U64:
// _builder.AppendLine($" {outputName} =l dtoui {input}");
// return outputName;
// case PrimitiveTypeKind.U32:
// case PrimitiveTypeKind.U16:
// case PrimitiveTypeKind.U8:
// _builder.AppendLine($" {outputName} =w dtoui {input}");
// return outputName;
// case PrimitiveTypeKind.String:
// _builder.AppendLine($" {outputName} =l call $nub_f64_to_string(d {input})");
// return outputName;
// case PrimitiveTypeKind.Bool:
// default:
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
// }
// case PrimitiveTypeKind.F32:
// switch (primitiveOutputType.Kind)
// {
// case PrimitiveTypeKind.F64:
// _builder.AppendLine($" {outputName} =d stod {input}");
// return outputName;
// case PrimitiveTypeKind.F32:
// return input;
// case PrimitiveTypeKind.I64:
// _builder.AppendLine($" {outputName} =l stosi {input}");
// return outputName;
// case PrimitiveTypeKind.I32:
// case PrimitiveTypeKind.I16:
// case PrimitiveTypeKind.I8:
// _builder.AppendLine($" {outputName} =w stosi {input}");
// return outputName;
// case PrimitiveTypeKind.U64:
// _builder.AppendLine($" {outputName} =l stoui {input}");
// return outputName;
// case PrimitiveTypeKind.U32:
// case PrimitiveTypeKind.U16:
// case PrimitiveTypeKind.U8:
// _builder.AppendLine($" {outputName} =w stoui {input}");
// return outputName;
// case PrimitiveTypeKind.String:
// _builder.AppendLine($" {outputName} =l call $nub_f32_to_string(s {input})");
// return outputName;
// case PrimitiveTypeKind.Any:
// throw new NotImplementedException();
// case PrimitiveTypeKind.Bool:
// default:
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
// }
// case PrimitiveTypeKind.Bool:
// switch (primitiveOutputType.Kind)
// {
// case PrimitiveTypeKind.Bool:
// return input;
// case PrimitiveTypeKind.Any:
// _builder.AppendLine($" {outputName} =l extsw {input}");
// return outputName;
// case PrimitiveTypeKind.String:
// _builder.AppendLine($" {outputName} =l call $nub_bool_to_string(s {input})");
// return outputName;
// case PrimitiveTypeKind.I64:
// case PrimitiveTypeKind.I32:
// case PrimitiveTypeKind.I16:
// case PrimitiveTypeKind.I8:
// case PrimitiveTypeKind.U64:
// case PrimitiveTypeKind.U32:
// case PrimitiveTypeKind.U16:
// case PrimitiveTypeKind.U8:
// case PrimitiveTypeKind.F64:
// case PrimitiveTypeKind.F32:
// default:
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
// }
// case PrimitiveTypeKind.String:
// switch (primitiveOutputType.Kind)
// {
// case PrimitiveTypeKind.String:
// case PrimitiveTypeKind.Any:
// return input;
// case PrimitiveTypeKind.I64:
// case PrimitiveTypeKind.I32:
// case PrimitiveTypeKind.I16:
// case PrimitiveTypeKind.I8:
// case PrimitiveTypeKind.U64:
// case PrimitiveTypeKind.U32:
// case PrimitiveTypeKind.U16:
// case PrimitiveTypeKind.U8:
// case PrimitiveTypeKind.F64:
// case PrimitiveTypeKind.F32:
// case PrimitiveTypeKind.Bool:
// default:
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
// }
// case PrimitiveTypeKind.Any:
// return input;
// default:
// throw new NotSupportedException($"Casting from {primitiveInputType.Kind} to {primitiveOutputType.Kind} is not supported");
// }
// }
private string GenerateIdentifier(IdentifierNode identifier)
{
var variable = _variables[identifier.Identifier];
if (IsLargeType(identifier.Type))
{
return variable;
}
else
{
var outputName = GenVarName();
_builder.AppendLine($" {outputName} {QBEAssign(identifier.Type)} {QBELoad(identifier.Type)} {variable}");
return outputName;
}
return _variables[identifier.Identifier];
}
private string GenerateLiteral(LiteralNode literal)
@@ -1534,33 +1013,17 @@ public class Generator
if (structInitializer.Initializers.TryGetValue(field.Name, out var fieldValue))
{
var var = GenerateExpression(fieldValue);
var offsetName = GenVarName();
_builder.AppendLine($" {offsetName} =l add {structVar}, {offset}");
if (IsLargeType(field.Type))
{
_builder.AppendLine($" blit {var}, {offsetName}, {SizeOf(field.Type)}");
}
else
{
_builder.AppendLine($" {QBEStore(field.Type)} {var}, {offsetName}");
}
var value = GenerateExpression(fieldValue);
var pointer = GenVarName();
_builder.AppendLine($" {pointer} =l add {structVar}, {offset}");
GenerateCopy(field.Type, value, pointer);
}
else if (field.Value.HasValue)
{
var var = GenerateExpression(field.Value.Value);
var offsetName = GenVarName();
_builder.AppendLine($" {offsetName} =l add {structVar}, {offset}");
if (IsLargeType(field.Type))
{
_builder.AppendLine($" blit {var}, {offsetName}, {SizeOf(field.Type)}");
}
else
{
_builder.AppendLine($" {QBEStore(field.Type)} {var}, {offsetName}");
}
var value = GenerateExpression(field.Value.Value);
var pointer = GenVarName();
_builder.AppendLine($" {pointer} =l add {structVar}, {offset}");
GenerateCopy(field.Type, value, pointer);
}
else
{
@@ -1618,22 +1081,19 @@ public class Generator
throw new NotSupportedException($"Unary operator {unaryExpression.Operator} for type {unaryExpression.Operand.Type} not supported");
}
private string GenerateMemberAccess(MemberAccessNode memberAccess)
private string GenerateMemberAccessPointer(MemberAccessNode memberAccess)
{
var item = GenerateExpression(memberAccess.Expression);
switch (memberAccess.Expression.Type)
{
case NubArrayType:
{
if (memberAccess.Member == "count")
{
var outputName = GenVarName();
_builder.AppendLine($" {outputName} =l loadl {item}");
return outputName;
return item;
}
throw new ArgumentOutOfRangeException(nameof(memberAccess.Member));
throw new UnreachableException(nameof(memberAccess.Member));
}
case NubStructType structType:
{
@@ -1642,26 +1102,31 @@ public class Generator
var offsetName = GenVarName();
_builder.AppendLine($" {offsetName} =l add {item}, {offset}");
if (IsLargeType(memberAccess.Type))
{
return offsetName;
}
else
{
var outputName = GenVarName();
_builder.AppendLine($" {outputName} {QBEAssign(memberAccess.Type)} {QBELoad(memberAccess.Type)} {offsetName}");
return outputName;
}
return offsetName;
}
default:
{
throw new ArgumentOutOfRangeException(nameof(memberAccess.Expression.Type));
throw new UnreachableException(nameof(memberAccess.Expression.Type));
}
}
}
private string GenerateMemberAccess(MemberAccessNode memberAccess)
{
var pointer = GenerateMemberAccessPointer(memberAccess);
if (IsLargeType(memberAccess.Type))
{
return pointer;
}
else
{
var outputName = GenVarName();
_builder.AppendLine($" {outputName} {QBEAssign(memberAccess.Type)} {QBELoad(memberAccess.Type)} {pointer}");
return outputName;
}
}
private string GenerateFixedArrayInitializer(FixedArrayInitializerNode fixedArrayInitializer)
{
var capacityInBytes = SizeOf(fixedArrayInitializer.Type);
@@ -1737,6 +1202,18 @@ public class Generator
}
}
private void GenerateCopy(NubType type, string value, string destinationPointer)
{
if (IsLargeType(type))
{
_builder.AppendLine($" blit {value}, {destinationPointer}, {SizeOf(type)}");
}
else
{
_builder.AppendLine($" {QBEStore(type)} {value}, {destinationPointer}");
}
}
private string GenVarName()
{
return $"%v{++_variableIndex}";

View File

@@ -2,7 +2,7 @@ using Nub.Lang.Frontend.Lexing;
namespace Nub.Lang.Frontend.Parsing.Expressions;
public class AddressOfNode(IReadOnlyList<Token> tokens, ExpressionNode expression) : ExpressionNode(tokens)
public class AddressOfNode(IReadOnlyList<Token> tokens, LValueNode expression) : ExpressionNode(tokens)
{
public ExpressionNode Expression { get; } = expression;
public LValueNode Expression { get; } = expression;
}

View File

@@ -2,7 +2,7 @@ using Nub.Lang.Frontend.Lexing;
namespace Nub.Lang.Frontend.Parsing.Expressions;
public class ArrayIndexAccessNode(IReadOnlyList<Token> tokens, ExpressionNode array, ExpressionNode index) : ExpressionNode(tokens)
public class ArrayIndexAccessNode(IReadOnlyList<Token> tokens, ExpressionNode array, ExpressionNode index) : LValueNode(tokens)
{
public ExpressionNode Array { get; } = array;
public ExpressionNode Index { get; } = index;

View File

@@ -1,10 +0,0 @@
// using Nub.Lang.Frontend.Lexing;
// using Nub.Lang.Frontend.Typing;
//
// namespace Nub.Lang.Frontend.Parsing.Expressions;
//
// public class CastNode(IReadOnlyList<Token> tokens, NubType targetType, ExpressionNode expression) : ExpressionNode(tokens)
// {
// public NubType TargetType { get; } = targetType;
// public ExpressionNode Expression { get; } = expression;
// }

View File

@@ -2,7 +2,7 @@ using Nub.Lang.Frontend.Lexing;
namespace Nub.Lang.Frontend.Parsing.Expressions;
public class DereferenceNode(IReadOnlyList<Token> tokens, ExpressionNode expression) : ExpressionNode(tokens)
public class DereferenceNode(IReadOnlyList<Token> tokens, ExpressionNode expression) : LValueNode(tokens)
{
public ExpressionNode Expression { get; } = expression;
}

View File

@@ -11,4 +11,6 @@ public abstract class ExpressionNode(IReadOnlyList<Token> tokens) : Node(tokens)
get => _type ?? throw new Exception("Tried to access expression type before type was populated");
set => _type = value;
}
}
}
public abstract class LValueNode(IReadOnlyList<Token> tokens) : ExpressionNode(tokens);

View File

@@ -2,7 +2,7 @@
namespace Nub.Lang.Frontend.Parsing.Expressions;
public class IdentifierNode(IReadOnlyList<Token> tokens, string identifier) : ExpressionNode(tokens)
public class IdentifierNode(IReadOnlyList<Token> tokens, string identifier) : LValueNode(tokens)
{
public string Identifier { get; } = identifier;

View File

@@ -2,7 +2,7 @@
namespace Nub.Lang.Frontend.Parsing.Expressions;
public class MemberAccessNode(IReadOnlyList<Token> tokens, ExpressionNode expression, string member) : ExpressionNode(tokens)
public class MemberAccessNode(IReadOnlyList<Token> tokens, ExpressionNode expression, string member) : LValueNode(tokens)
{
public ExpressionNode Expression { get; } = expression;
public string Member { get; } = member;

View File

@@ -495,20 +495,18 @@ public class Parser
expr = expression;
break;
}
// case Symbol.LessThan:
// {
// var type = ParseType();
// ExpectSymbol(Symbol.GreaterThan);
// ExpectSymbol(Symbol.OpenParen);
// var expressionToCast = ParseExpression();
// ExpectSymbol(Symbol.CloseParen);
// expr = new CastNode(GetTokensForNode(startIndex), type, expressionToCast);
// break;
// }
case Symbol.Ampersand:
{
var expression = ParsePrimaryExpression();
expr = new AddressOfNode(GetTokensForNode(startIndex), expression);
if (expression is not LValueNode lValue)
{
throw new ParseException(Diagnostic
.Error("& symbol can only be used on lvalues")
.At(expression)
.Build());
}
expr = new AddressOfNode(GetTokensForNode(startIndex), lValue);
break;
}
case Symbol.Minus:

View File

@@ -362,7 +362,6 @@ public class TypeChecker
LiteralNode literal => TypeCheckLiteral(literal, expectedType),
IdentifierNode identifier => TypeCheckIdentifier(identifier),
BinaryExpressionNode binaryExpr => TypeCheckBinaryExpression(binaryExpr),
// CastNode cast => TypeCheckCast(cast),
DereferenceNode dereference => TypeCheckDereference(dereference),
FixedArrayInitializerNode fixedArray => TypeCheckFixedInitializerArray(fixedArray),
FuncCallNode funcCallExpr => TypeCheckFuncCall(funcCallExpr, funcCallExpr),
@@ -394,7 +393,7 @@ public class TypeChecker
{
if (literal.Kind == LiteralKind.Float)
{
ReportWarning("Possible loss of precision when using float in integer context", literal);
ReportWarning("Float used in integer context. Everything after the '.' will be ignored", literal);
}
}
@@ -517,13 +516,6 @@ public class TypeChecker
}
}
// private NubType? TypeCheckCast(CastNode cast)
// {
// TypeCheckExpression(cast.Expression, cast.TargetType);
// // TODO: Check if castable
// return cast.TargetType;
// }
private NubType? TypeCheckStructInitializer(StructInitializerNode structInit)
{
var initialized = new HashSet<string>();