...
This commit is contained in:
@@ -16,18 +16,18 @@ struct Human : Printable, Stringable
|
|||||||
|
|
||||||
func str(): cstring
|
func str(): cstring
|
||||||
{
|
{
|
||||||
return this^.name
|
return this.name
|
||||||
}
|
}
|
||||||
|
|
||||||
func print()
|
func print()
|
||||||
{
|
{
|
||||||
puts(this^.str())
|
puts(this.str())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main(args: []cstring): i64
|
func main(args: []cstring): i64
|
||||||
{
|
{
|
||||||
let human: Stringable = alloc Human {
|
let human = alloc Human {
|
||||||
name = "oliver"
|
name = "oliver"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,9 +117,10 @@ var typedDefinitionTable = new TypedDefinitionTable(typedSyntaxTrees);
|
|||||||
|
|
||||||
var objectFiles = new List<string>();
|
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 generator = new QBEGenerator(syntaxTree, typedDefinitionTable);
|
||||||
var ssa = generator.Emit();
|
var ssa = generator.Emit();
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ public partial class QBEGenerator
|
|||||||
var value = EmitExpression(addressOf.Expression);
|
var value = EmitExpression(addressOf.Expression);
|
||||||
if (value.Kind != ValKind.Pointer)
|
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);
|
return new Val(value.Name, addressOf.Type, ValKind.Direct);
|
||||||
@@ -333,11 +333,6 @@ public partial class QBEGenerator
|
|||||||
_writer.Indented($"{destination} =l alloc8 {size}");
|
_writer.Indented($"{destination} =l alloc8 {size}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (structDef.InterfaceImplementations.Any())
|
|
||||||
// {
|
|
||||||
// _writer.Indented($"storel {destination}, {StructVtableName(structDef.Name)}");
|
|
||||||
// }
|
|
||||||
|
|
||||||
foreach (var field in structDef.Fields)
|
foreach (var field in structDef.Fields)
|
||||||
{
|
{
|
||||||
if (!structInitializer.Initializers.TryGetValue(field.Name, out var valueExpression))
|
if (!structInitializer.Initializers.TryGetValue(field.Name, out var valueExpression))
|
||||||
@@ -345,7 +340,10 @@ public partial class QBEGenerator
|
|||||||
valueExpression = field.Value.Value;
|
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();
|
var offset = TmpName();
|
||||||
_writer.Indented($"{offset} =l add {destination}, {OffsetOf(structDef, field.Name)}");
|
_writer.Indented($"{offset} =l add {destination}, {OffsetOf(structDef, field.Name)}");
|
||||||
@@ -423,13 +421,12 @@ public partial class QBEGenerator
|
|||||||
|
|
||||||
private Val EmitStructFuncAccess(StructFuncAccessNode structFuncAccess)
|
private Val EmitStructFuncAccess(StructFuncAccessNode structFuncAccess)
|
||||||
{
|
{
|
||||||
var target = EmitExpression(structFuncAccess.Target);
|
var target = EmitUnwrap(EmitExpression(structFuncAccess.Target));
|
||||||
Debug.Assert(target.Kind == ValKind.Pointer);
|
|
||||||
|
|
||||||
var structDef = _definitionTable.LookupStruct(structFuncAccess.StructType.Name);
|
var structDef = _definitionTable.LookupStruct(structFuncAccess.StructType.Name);
|
||||||
var func = StructFuncName(structDef.Name, structFuncAccess.Func);
|
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)
|
private Val EmitInterfaceFuncAccess(InterfaceFuncAccessNode interfaceFuncAccess)
|
||||||
@@ -449,13 +446,16 @@ public partial class QBEGenerator
|
|||||||
var func = TmpName();
|
var func = TmpName();
|
||||||
_writer.Indented($"{func} =l loadl {funcOffset}");
|
_writer.Indented($"{func} =l loadl {funcOffset}");
|
||||||
|
|
||||||
|
var dataPointer = TmpName();
|
||||||
|
_writer.Indented($"{dataPointer} =l add {target}, 8");
|
||||||
|
|
||||||
var data = TmpName();
|
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);
|
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));
|
var implementation = EmitUnwrap(EmitExpression(interfaceInitializer.Implementation));
|
||||||
|
|
||||||
@@ -470,27 +470,28 @@ public partial class QBEGenerator
|
|||||||
vtableOffset += interfaceImplementation.Functions.Count * 8;
|
vtableOffset += interfaceImplementation.Functions.Count * 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = TmpName();
|
if (destination == null)
|
||||||
_writer.Indented($"{result} =l alloc8 16");
|
{
|
||||||
|
destination = TmpName();
|
||||||
|
_writer.Indented($"{destination} =l alloc8 {SizeOf(interfaceInitializer.InterfaceType)}");
|
||||||
|
}
|
||||||
|
|
||||||
var interfaceVtablePointer = TmpName();
|
var interfaceVtablePointer = TmpName();
|
||||||
_writer.Indented($"{interfaceVtablePointer} =l add {StructVtableName(interfaceInitializer.StructType.Name)}, {vtableOffset}");
|
_writer.Indented($"{interfaceVtablePointer} =l add {StructVtableName(interfaceInitializer.StructType.Name)}, {vtableOffset}");
|
||||||
_writer.Indented($"storel {interfaceVtablePointer}, {result}");
|
_writer.Indented($"storel {interfaceVtablePointer}, {destination}");
|
||||||
|
|
||||||
var objectPointer = TmpName();
|
var objectPointer = TmpName();
|
||||||
_writer.Indented($"{objectPointer} =l add {result}, 8");
|
_writer.Indented($"{objectPointer} =l add {destination}, 8");
|
||||||
_writer.Indented($"storel {implementation}, {objectPointer}");
|
_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)
|
private Val EmitFuncCall(FuncCallNode funcCall)
|
||||||
{
|
{
|
||||||
var expression = EmitExpression(funcCall.Expression);
|
var expression = EmitExpression(funcCall.Expression);
|
||||||
var funcPointer = EmitUnwrap(expression);
|
|
||||||
|
|
||||||
var parameterStrings = new List<string>();
|
var parameterStrings = new List<string>();
|
||||||
|
|
||||||
if (expression.ThisArg != null)
|
if (expression.ThisArg != null)
|
||||||
{
|
{
|
||||||
parameterStrings.Add($"l {expression.ThisArg}");
|
parameterStrings.Add($"l {expression.ThisArg}");
|
||||||
@@ -502,6 +503,7 @@ public partial class QBEGenerator
|
|||||||
parameterStrings.Add($"{FuncQBETypeName(parameter.Type)} {copy}");
|
parameterStrings.Add($"{FuncQBETypeName(parameter.Type)} {copy}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var funcPointer = EmitUnwrap(expression);
|
||||||
if (funcCall.Type is VoidTypeNode)
|
if (funcCall.Type is VoidTypeNode)
|
||||||
{
|
{
|
||||||
_writer.Indented($"call {funcPointer}({string.Join(", ", parameterStrings)})");
|
_writer.Indented($"call {funcPointer}({string.Join(", ", parameterStrings)})");
|
||||||
|
|||||||
@@ -41,7 +41,11 @@ public partial class QBEGenerator
|
|||||||
private void EmitAssignment(AssignmentNode assignment)
|
private void EmitAssignment(AssignmentNode assignment)
|
||||||
{
|
{
|
||||||
var destination = EmitExpression(assignment.Target);
|
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);
|
EmitCopyIntoOrInitialize(assignment.Value, destination.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -224,6 +224,11 @@ public partial class QBEGenerator
|
|||||||
EmitStructInitializer(structInitializer, destinationPointer);
|
EmitStructInitializer(structInitializer, destinationPointer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
case InterfaceInitializerNode interfaceInitializer:
|
||||||
|
{
|
||||||
|
EmitInterfaceInitializer(interfaceInitializer, destinationPointer);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
case LiteralNode { Kind: LiteralKind.String } literal:
|
case LiteralNode { Kind: LiteralKind.String } literal:
|
||||||
{
|
{
|
||||||
EmitStore(source.Type, EmitUnwrap(EmitLiteral(literal)), destinationPointer);
|
EmitStore(source.Type, EmitUnwrap(EmitLiteral(literal)), destinationPointer);
|
||||||
@@ -250,9 +255,9 @@ public partial class QBEGenerator
|
|||||||
}
|
}
|
||||||
else
|
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
|
else
|
||||||
{
|
{
|
||||||
@@ -261,7 +266,6 @@ public partial class QBEGenerator
|
|||||||
ArrayTypeNode arrayType => EmitArraySizeInBytes(arrayType, value),
|
ArrayTypeNode arrayType => EmitArraySizeInBytes(arrayType, value),
|
||||||
CStringTypeNode => EmitCStringSizeInBytes(value),
|
CStringTypeNode => EmitCStringSizeInBytes(value),
|
||||||
StringTypeNode => EmitStringSizeInBytes(value),
|
StringTypeNode => EmitStringSizeInBytes(value),
|
||||||
InterfaceTypeNode => 16.ToString(),
|
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(source.Type))
|
_ => throw new ArgumentOutOfRangeException(nameof(source.Type))
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -311,7 +315,7 @@ public partial class QBEGenerator
|
|||||||
ArrayTypeNode arrayType => EmitArraySizeInBytes(arrayType, value),
|
ArrayTypeNode arrayType => EmitArraySizeInBytes(arrayType, value),
|
||||||
CStringTypeNode => EmitCStringSizeInBytes(value),
|
CStringTypeNode => EmitCStringSizeInBytes(value),
|
||||||
StringTypeNode => EmitStringSizeInBytes(value),
|
StringTypeNode => EmitStringSizeInBytes(value),
|
||||||
InterfaceTypeNode => 16.ToString(),
|
InterfaceTypeNode interfaceType => SizeOf(interfaceType).ToString(),
|
||||||
StructTypeNode structType => SizeOf(structType).ToString(),
|
StructTypeNode structType => SizeOf(structType).ToString(),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(source.Type))
|
_ => throw new ArgumentOutOfRangeException(nameof(source.Type))
|
||||||
};
|
};
|
||||||
@@ -486,11 +490,6 @@ public partial class QBEGenerator
|
|||||||
{
|
{
|
||||||
var offset = 0;
|
var offset = 0;
|
||||||
|
|
||||||
// if (structType.InterfaceImplementations.Any())
|
|
||||||
// {
|
|
||||||
// offset = 8;
|
|
||||||
// }
|
|
||||||
|
|
||||||
foreach (var field in structType.Fields)
|
foreach (var field in structType.Fields)
|
||||||
{
|
{
|
||||||
var fieldAlignment = AlignmentOf(field);
|
var fieldAlignment = AlignmentOf(field);
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ public sealed class Parser
|
|||||||
|
|
||||||
if (thisArg != null)
|
if (thisArg != null)
|
||||||
{
|
{
|
||||||
parameters.Add(new FuncParameterSyntax([], "this", new PointerTypeSyntax([], thisArg)));
|
parameters.Add(new FuncParameterSyntax([], "this", thisArg));
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpectSymbol(Symbol.OpenParen);
|
ExpectSymbol(Symbol.OpenParen);
|
||||||
|
|||||||
Reference in New Issue
Block a user