...
This commit is contained in:
@@ -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"
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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)})");
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user