This commit is contained in:
nub31
2025-08-13 20:01:09 +02:00
parent 9c69c39cff
commit ca3394b9bd
6 changed files with 41 additions and 35 deletions

View File

@@ -16,18 +16,18 @@ struct Human : Printable, Stringable
func str(): cstring
{
return this^.name
return this.name
}
func print()
{
puts(this^.str())
puts(this.str())
}
}
func main(args: []cstring): i64
{
let human: Stringable = alloc Human {
let human = alloc Human {
name = "oliver"
}

View File

@@ -117,9 +117,10 @@ var typedDefinitionTable = new TypedDefinitionTable(typedSyntaxTrees);
var objectFiles = new List<string>();
foreach (var syntaxTree in typedSyntaxTrees)
for (var i = 0; i < typedSyntaxTrees.Count; i++)
{
var outFileName = HexString.CreateUnique(8);
var syntaxTree = typedSyntaxTrees[i];
var outFileName = Path.GetFileNameWithoutExtension(options.Files[i].Path);
var generator = new QBEGenerator(syntaxTree, typedDefinitionTable);
var ssa = generator.Emit();

View File

@@ -110,7 +110,7 @@ public partial class QBEGenerator
var value = EmitExpression(addressOf.Expression);
if (value.Kind != ValKind.Pointer)
{
throw new UnreachableException("Tried to take address of non-pointer type. This should have been causht in the type checker");
throw new UnreachableException("Tried to take address of non-pointer type. This should have been caught in the type checker");
}
return new Val(value.Name, addressOf.Type, ValKind.Direct);
@@ -333,11 +333,6 @@ public partial class QBEGenerator
_writer.Indented($"{destination} =l alloc8 {size}");
}
// if (structDef.InterfaceImplementations.Any())
// {
// _writer.Indented($"storel {destination}, {StructVtableName(structDef.Name)}");
// }
foreach (var field in structDef.Fields)
{
if (!structInitializer.Initializers.TryGetValue(field.Name, out var valueExpression))
@@ -345,7 +340,10 @@ public partial class QBEGenerator
valueExpression = field.Value.Value;
}
Debug.Assert(valueExpression != null);
if (valueExpression == null)
{
throw new UnreachableException("Value of field in uninitialized. This should have been caught in the type checker");
}
var offset = TmpName();
_writer.Indented($"{offset} =l add {destination}, {OffsetOf(structDef, field.Name)}");
@@ -423,13 +421,12 @@ public partial class QBEGenerator
private Val EmitStructFuncAccess(StructFuncAccessNode structFuncAccess)
{
var target = EmitExpression(structFuncAccess.Target);
Debug.Assert(target.Kind == ValKind.Pointer);
var target = EmitUnwrap(EmitExpression(structFuncAccess.Target));
var structDef = _definitionTable.LookupStruct(structFuncAccess.StructType.Name);
var func = StructFuncName(structDef.Name, structFuncAccess.Func);
return new Val(func, structFuncAccess.Type, ValKind.Direct, target.Name);
return new Val(func, structFuncAccess.Type, ValKind.Direct, target);
}
private Val EmitInterfaceFuncAccess(InterfaceFuncAccessNode interfaceFuncAccess)
@@ -449,13 +446,16 @@ public partial class QBEGenerator
var func = TmpName();
_writer.Indented($"{func} =l loadl {funcOffset}");
var dataPointer = TmpName();
_writer.Indented($"{dataPointer} =l add {target}, 8");
var data = TmpName();
_writer.Indented($"{data} =l add {target}, 8");
_writer.Indented($"{data} =l loadl {dataPointer}");
return new Val(func, interfaceFuncAccess.Type, ValKind.Direct, data);
}
private Val EmitInterfaceInitializer(InterfaceInitializerNode interfaceInitializer)
private Val EmitInterfaceInitializer(InterfaceInitializerNode interfaceInitializer, string? destination = null)
{
var implementation = EmitUnwrap(EmitExpression(interfaceInitializer.Implementation));
@@ -470,27 +470,28 @@ public partial class QBEGenerator
vtableOffset += interfaceImplementation.Functions.Count * 8;
}
var result = TmpName();
_writer.Indented($"{result} =l alloc8 16");
if (destination == null)
{
destination = TmpName();
_writer.Indented($"{destination} =l alloc8 {SizeOf(interfaceInitializer.InterfaceType)}");
}
var interfaceVtablePointer = TmpName();
_writer.Indented($"{interfaceVtablePointer} =l add {StructVtableName(interfaceInitializer.StructType.Name)}, {vtableOffset}");
_writer.Indented($"storel {interfaceVtablePointer}, {result}");
_writer.Indented($"storel {interfaceVtablePointer}, {destination}");
var objectPointer = TmpName();
_writer.Indented($"{objectPointer} =l add {result}, 8");
_writer.Indented($"{objectPointer} =l add {destination}, 8");
_writer.Indented($"storel {implementation}, {objectPointer}");
return new Val(result, interfaceInitializer.InterfaceType, ValKind.Direct);
return new Val(destination, interfaceInitializer.InterfaceType, ValKind.Direct);
}
private Val EmitFuncCall(FuncCallNode funcCall)
{
var expression = EmitExpression(funcCall.Expression);
var funcPointer = EmitUnwrap(expression);
var parameterStrings = new List<string>();
if (expression.ThisArg != null)
{
parameterStrings.Add($"l {expression.ThisArg}");
@@ -502,6 +503,7 @@ public partial class QBEGenerator
parameterStrings.Add($"{FuncQBETypeName(parameter.Type)} {copy}");
}
var funcPointer = EmitUnwrap(expression);
if (funcCall.Type is VoidTypeNode)
{
_writer.Indented($"call {funcPointer}({string.Join(", ", parameterStrings)})");

View File

@@ -41,7 +41,11 @@ public partial class QBEGenerator
private void EmitAssignment(AssignmentNode assignment)
{
var destination = EmitExpression(assignment.Target);
Debug.Assert(destination.Kind == ValKind.Pointer);
if (destination.Kind != ValKind.Pointer)
{
throw new UnreachableException("Destination of assignment must be a pointer. This should be caught in the type checker");
}
EmitCopyIntoOrInitialize(assignment.Value, destination.Name);
}

View File

@@ -224,6 +224,11 @@ public partial class QBEGenerator
EmitStructInitializer(structInitializer, destinationPointer);
return true;
}
case InterfaceInitializerNode interfaceInitializer:
{
EmitInterfaceInitializer(interfaceInitializer, destinationPointer);
return true;
}
case LiteralNode { Kind: LiteralKind.String } literal:
{
EmitStore(source.Type, EmitUnwrap(EmitLiteral(literal)), destinationPointer);
@@ -250,9 +255,9 @@ public partial class QBEGenerator
}
else
{
if (complexType is StructTypeNode structType)
if (complexType is StructTypeNode or InterfaceTypeNode)
{
EmitMemcpy(value, destinationPointer, SizeOf(structType).ToString());
EmitMemcpy(value, destinationPointer, SizeOf(complexType).ToString());
}
else
{
@@ -261,7 +266,6 @@ public partial class QBEGenerator
ArrayTypeNode arrayType => EmitArraySizeInBytes(arrayType, value),
CStringTypeNode => EmitCStringSizeInBytes(value),
StringTypeNode => EmitStringSizeInBytes(value),
InterfaceTypeNode => 16.ToString(),
_ => throw new ArgumentOutOfRangeException(nameof(source.Type))
};
@@ -311,7 +315,7 @@ public partial class QBEGenerator
ArrayTypeNode arrayType => EmitArraySizeInBytes(arrayType, value),
CStringTypeNode => EmitCStringSizeInBytes(value),
StringTypeNode => EmitStringSizeInBytes(value),
InterfaceTypeNode => 16.ToString(),
InterfaceTypeNode interfaceType => SizeOf(interfaceType).ToString(),
StructTypeNode structType => SizeOf(structType).ToString(),
_ => throw new ArgumentOutOfRangeException(nameof(source.Type))
};
@@ -486,11 +490,6 @@ public partial class QBEGenerator
{
var offset = 0;
// if (structType.InterfaceImplementations.Any())
// {
// offset = 8;
// }
foreach (var field in structType.Fields)
{
var fieldAlignment = AlignmentOf(field);

View File

@@ -73,7 +73,7 @@ public sealed class Parser
if (thisArg != null)
{
parameters.Add(new FuncParameterSyntax([], "this", new PointerTypeSyntax([], thisArg)));
parameters.Add(new FuncParameterSyntax([], "this", thisArg));
}
ExpectSymbol(Symbol.OpenParen);