...
This commit is contained in:
@@ -1,19 +1,30 @@
|
|||||||
// c
|
// c
|
||||||
extern func puts(text: cstring)
|
extern func puts(text: cstring)
|
||||||
|
|
||||||
struct Human {
|
interface Printable
|
||||||
|
{
|
||||||
|
func print()
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Human : Printable
|
||||||
|
{
|
||||||
name: cstring
|
name: cstring
|
||||||
age: u32
|
age: u32
|
||||||
|
|
||||||
|
func print()
|
||||||
|
{
|
||||||
|
puts(this.name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main(args: []cstring): i64
|
func main(args: []cstring): i64
|
||||||
{
|
{
|
||||||
let x: Human = struct {
|
let x: Printable = struct Human {
|
||||||
name = "Oliver"
|
name = "Oliver"
|
||||||
age = 23
|
age = 23
|
||||||
}
|
}
|
||||||
|
|
||||||
puts(x.name)
|
x.print()
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ public class QBEGenerator
|
|||||||
_writer.Indented($"{store} {value}, {destination}");
|
_writer.Indented($"{store} {value}, {destination}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitLoad(TypeNode type, string from)
|
private string EmitLoad(TypeNode type, string from)
|
||||||
{
|
{
|
||||||
string load;
|
string load;
|
||||||
|
|
||||||
@@ -164,7 +164,7 @@ public class QBEGenerator
|
|||||||
|
|
||||||
_writer.Indented($"{into} {QBEAssign(type)} {load} {from}");
|
_writer.Indented($"{into} {QBEAssign(type)} {load} {from}");
|
||||||
|
|
||||||
return new Val(into, type, ValKind.Direct);
|
return into;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EmitMemcpy(string source, string destination, string length)
|
private void EmitMemcpy(string source, string destination, string length)
|
||||||
@@ -203,7 +203,7 @@ public class QBEGenerator
|
|||||||
{
|
{
|
||||||
case ArrayInitializerNode arrayInitializer:
|
case ArrayInitializerNode arrayInitializer:
|
||||||
{
|
{
|
||||||
EmitStore(source.Type, EmitUnwrap(EmitArrayInitializer(arrayInitializer)), destinationPointer);
|
EmitStore(source.Type, EmitArrayInitializer(arrayInitializer), destinationPointer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case StructInitializerNode structInitializer:
|
case StructInitializerNode structInitializer:
|
||||||
@@ -218,7 +218,7 @@ public class QBEGenerator
|
|||||||
}
|
}
|
||||||
case LiteralNode { Kind: LiteralKind.String } literal:
|
case LiteralNode { Kind: LiteralKind.String } literal:
|
||||||
{
|
{
|
||||||
EmitStore(source.Type, EmitUnwrap(EmitLiteral(literal)), destinationPointer);
|
EmitStore(source.Type, EmitLiteral(literal), destinationPointer);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -368,7 +368,7 @@ public class QBEGenerator
|
|||||||
|
|
||||||
foreach (var parameter in funcDef.Signature.Parameters)
|
foreach (var parameter in funcDef.Signature.Parameters)
|
||||||
{
|
{
|
||||||
scope.Declare(parameter.Name, new Val("%" + parameter.Name, parameter.Type, ValKind.Direct));
|
scope.Declare(parameter.Name, new Val("%" + parameter.Name, parameter.Type, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
EmitBlock(funcDef.Body, scope);
|
EmitBlock(funcDef.Body, scope);
|
||||||
@@ -410,10 +410,10 @@ public class QBEGenerator
|
|||||||
|
|
||||||
var scope = new Scope();
|
var scope = new Scope();
|
||||||
|
|
||||||
scope.Declare("this", new Val("%this", structDef.Type, ValKind.Direct));
|
scope.Declare("this", new Val("%this", structDef.Type, false));
|
||||||
foreach (var parameter in function.Signature.Parameters)
|
foreach (var parameter in function.Signature.Parameters)
|
||||||
{
|
{
|
||||||
scope.Declare(parameter.Name, new Val("%" + parameter.Name, parameter.Type, ValKind.Direct));
|
scope.Declare(parameter.Name, new Val("%" + parameter.Name, parameter.Type, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
EmitBlock(function.Body, scope);
|
EmitBlock(function.Body, scope);
|
||||||
@@ -531,12 +531,12 @@ public class QBEGenerator
|
|||||||
|
|
||||||
private void EmitAssignment(AssignmentNode assignment)
|
private void EmitAssignment(AssignmentNode assignment)
|
||||||
{
|
{
|
||||||
var destination = EmitExpression(assignment.Target);
|
if (!assignment.Target.IsLValue)
|
||||||
if (destination.Kind != ValKind.Pointer)
|
|
||||||
{
|
{
|
||||||
throw new UnreachableException("Destination of assignment must be a pointer. This should be caught in the type checker");
|
throw new UnreachableException("Destination of assignment must be an lvalue. This should have been caught in the type checker");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var destination = EmitExpression(assignment.Target);
|
||||||
EmitCopyIntoOrInitialize(assignment.Value, destination.Name);
|
EmitCopyIntoOrInitialize(assignment.Value, destination.Name);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -600,7 +600,7 @@ public class QBEGenerator
|
|||||||
EmitStore(variableDeclaration.Assignment.Value.Type, value, name);
|
EmitStore(variableDeclaration.Assignment.Value.Type, value, name);
|
||||||
}
|
}
|
||||||
|
|
||||||
Scope.Declare(variableDeclaration.Name, new Val(name, variableDeclaration.Type, ValKind.Pointer));
|
Scope.Declare(variableDeclaration.Name, new Val(name, variableDeclaration.Type, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EmitWhile(WhileNode whileStatement)
|
private void EmitWhile(WhileNode whileStatement)
|
||||||
@@ -626,7 +626,7 @@ public class QBEGenerator
|
|||||||
|
|
||||||
private Val EmitExpression(ExpressionNode expression)
|
private Val EmitExpression(ExpressionNode expression)
|
||||||
{
|
{
|
||||||
return expression switch
|
var value = expression switch
|
||||||
{
|
{
|
||||||
ArrayInitializerNode arrayInitializer => EmitArrayInitializer(arrayInitializer),
|
ArrayInitializerNode arrayInitializer => EmitArrayInitializer(arrayInitializer),
|
||||||
StructInitializerNode structInitializer => EmitStructInitializer(structInitializer),
|
StructInitializerNode structInitializer => EmitStructInitializer(structInitializer),
|
||||||
@@ -646,9 +646,11 @@ public class QBEGenerator
|
|||||||
ArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex),
|
ArrayIndexAccessNode arrayIndex => EmitArrayIndexAccess(arrayIndex),
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(expression))
|
_ => throw new ArgumentOutOfRangeException(nameof(expression))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
return new Val(value, expression.Type, expression.IsLValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess)
|
private string EmitArrayIndexAccess(ArrayIndexAccessNode arrayIndexAccess)
|
||||||
{
|
{
|
||||||
var array = EmitUnwrap(EmitExpression(arrayIndexAccess.Target));
|
var array = EmitUnwrap(EmitExpression(arrayIndexAccess.Target));
|
||||||
var index = EmitUnwrap(EmitExpression(arrayIndexAccess.Index));
|
var index = EmitUnwrap(EmitExpression(arrayIndexAccess.Index));
|
||||||
@@ -661,7 +663,7 @@ public class QBEGenerator
|
|||||||
_writer.Indented($"{pointer} =l mul {index}, {SizeOf(elementType)}");
|
_writer.Indented($"{pointer} =l mul {index}, {SizeOf(elementType)}");
|
||||||
_writer.Indented($"{pointer} =l add {pointer}, 8");
|
_writer.Indented($"{pointer} =l add {pointer}, 8");
|
||||||
_writer.Indented($"{pointer} =l add {array}, {pointer}");
|
_writer.Indented($"{pointer} =l add {array}, {pointer}");
|
||||||
return new Val(pointer, arrayIndexAccess.Type, ValKind.Pointer);
|
return pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EmitArraysCheck(string array, string index)
|
private void EmitArraysCheck(string array, string index)
|
||||||
@@ -688,7 +690,7 @@ public class QBEGenerator
|
|||||||
_writer.Indented(notOobLabel);
|
_writer.Indented(notOobLabel);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitArrayInitializer(ArrayInitializerNode arrayInitializer)
|
private string EmitArrayInitializer(ArrayInitializerNode arrayInitializer)
|
||||||
{
|
{
|
||||||
var capacity = EmitUnwrap(EmitExpression(arrayInitializer.Capacity));
|
var capacity = EmitUnwrap(EmitExpression(arrayInitializer.Capacity));
|
||||||
var elementSize = SizeOf(arrayInitializer.ElementType);
|
var elementSize = SizeOf(arrayInitializer.ElementType);
|
||||||
@@ -706,26 +708,26 @@ public class QBEGenerator
|
|||||||
_writer.Indented($"{dataPointer} =l add {arrayPointer}, 8");
|
_writer.Indented($"{dataPointer} =l add {arrayPointer}, 8");
|
||||||
_writer.Indented($"call $nub_memset(l {dataPointer}, w 0, l {capacityInBytes})");
|
_writer.Indented($"call $nub_memset(l {dataPointer}, w 0, l {capacityInBytes})");
|
||||||
|
|
||||||
return new Val(arrayPointer, arrayInitializer.Type, ValKind.Direct);
|
return arrayPointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitDereference(DereferenceNode dereference)
|
private string EmitDereference(DereferenceNode dereference)
|
||||||
{
|
{
|
||||||
return EmitLoad(dereference.Type, EmitUnwrap(EmitExpression(dereference.Expression)));
|
return EmitLoad(dereference.Type, EmitUnwrap(EmitExpression(dereference.Expression)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitAddressOf(AddressOfNode addressOf)
|
private string EmitAddressOf(AddressOfNode addressOf)
|
||||||
{
|
{
|
||||||
var value = EmitExpression(addressOf.Expression);
|
var value = EmitExpression(addressOf.Expression);
|
||||||
if (value.Kind != ValKind.Pointer)
|
if (!value.IsLValue)
|
||||||
{
|
{
|
||||||
throw new UnreachableException("Tried to take address of non-pointer type. This should have been caught in the type checker");
|
throw new UnreachableException("Tried to take address of rvalue. This should have been caught in the type checker");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Val(value.Name, addressOf.Type, ValKind.Direct);
|
return value.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitBinaryExpression(BinaryExpressionNode binaryExpression)
|
private string EmitBinaryExpression(BinaryExpressionNode binaryExpression)
|
||||||
{
|
{
|
||||||
var left = EmitUnwrap(EmitExpression(binaryExpression.Left));
|
var left = EmitUnwrap(EmitExpression(binaryExpression.Left));
|
||||||
var right = EmitUnwrap(EmitExpression(binaryExpression.Right));
|
var right = EmitUnwrap(EmitExpression(binaryExpression.Right));
|
||||||
@@ -735,7 +737,7 @@ public class QBEGenerator
|
|||||||
var instruction = EmitBinaryInstructionFor(binaryExpression.Operator, binaryExpression.Left.Type, left, right);
|
var instruction = EmitBinaryInstructionFor(binaryExpression.Operator, binaryExpression.Left.Type, left, right);
|
||||||
|
|
||||||
_writer.Indented($"{outputName} {QBEAssign(binaryExpression.Left.Type)} {instruction} {left}, {right}");
|
_writer.Indented($"{outputName} {QBEAssign(binaryExpression.Left.Type)} {instruction} {left}, {right}");
|
||||||
return new Val(outputName, binaryExpression.Type, ValKind.Direct);
|
return outputName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitBinaryInstructionFor(BinaryOperator op, TypeNode type, string left, string right)
|
private string EmitBinaryInstructionFor(BinaryOperator op, TypeNode type, string left, string right)
|
||||||
@@ -832,24 +834,24 @@ public class QBEGenerator
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitExternFuncIdent(ExternFuncIdentNode externFuncIdent)
|
private string EmitExternFuncIdent(ExternFuncIdentNode externFuncIdent)
|
||||||
{
|
{
|
||||||
var func = _definitionTable.LookupExternFunc(externFuncIdent.Name);
|
var func = _definitionTable.LookupExternFunc(externFuncIdent.Name);
|
||||||
return new Val(ExternFuncName(func), externFuncIdent.Type, ValKind.Direct);
|
return ExternFuncName(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitLocalFuncIdent(LocalFuncIdentNode localFuncIdent)
|
private string EmitLocalFuncIdent(LocalFuncIdentNode localFuncIdent)
|
||||||
{
|
{
|
||||||
var func = _definitionTable.LookupLocalFunc(localFuncIdent.Name);
|
var func = _definitionTable.LookupLocalFunc(localFuncIdent.Name);
|
||||||
return new Val(LocalFuncName(func), localFuncIdent.Type, ValKind.Direct);
|
return LocalFuncName(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitVariableIdent(VariableIdentNode variableIdent)
|
private string EmitVariableIdent(VariableIdentNode variableIdent)
|
||||||
{
|
{
|
||||||
return Scope.Lookup(variableIdent.Name);
|
return variableIdent.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitLiteral(LiteralNode literal)
|
private string EmitLiteral(LiteralNode literal)
|
||||||
{
|
{
|
||||||
switch (literal.Kind)
|
switch (literal.Kind)
|
||||||
{
|
{
|
||||||
@@ -859,19 +861,19 @@ public class QBEGenerator
|
|||||||
{
|
{
|
||||||
var value = float.Parse(literal.Value, CultureInfo.InvariantCulture);
|
var value = float.Parse(literal.Value, CultureInfo.InvariantCulture);
|
||||||
var bits = BitConverter.SingleToInt32Bits(value);
|
var bits = BitConverter.SingleToInt32Bits(value);
|
||||||
return new Val(bits.ToString(), literal.Type, ValKind.Direct);
|
return bits.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (literal.Type is FloatTypeNode { Width: 64 })
|
if (literal.Type is FloatTypeNode { Width: 64 })
|
||||||
{
|
{
|
||||||
var value = double.Parse(literal.Value, CultureInfo.InvariantCulture);
|
var value = double.Parse(literal.Value, CultureInfo.InvariantCulture);
|
||||||
var bits = BitConverter.DoubleToInt64Bits(value);
|
var bits = BitConverter.DoubleToInt64Bits(value);
|
||||||
return new Val(bits.ToString(), literal.Type, ValKind.Direct);
|
return bits.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (literal.Type is IntTypeNode)
|
if (literal.Type is IntTypeNode)
|
||||||
{
|
{
|
||||||
return new Val(literal.Value, literal.Type, ValKind.Direct);
|
return literal.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -880,21 +882,21 @@ public class QBEGenerator
|
|||||||
{
|
{
|
||||||
if (literal.Type is IntTypeNode)
|
if (literal.Type is IntTypeNode)
|
||||||
{
|
{
|
||||||
return new Val(literal.Value.Split(".").First(), literal.Type, ValKind.Direct);
|
return literal.Value.Split(".").First();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (literal.Type is FloatTypeNode { Width: 32 })
|
if (literal.Type is FloatTypeNode { Width: 32 })
|
||||||
{
|
{
|
||||||
var value = float.Parse(literal.Value, CultureInfo.InvariantCulture);
|
var value = float.Parse(literal.Value, CultureInfo.InvariantCulture);
|
||||||
var bits = BitConverter.SingleToInt32Bits(value);
|
var bits = BitConverter.SingleToInt32Bits(value);
|
||||||
return new Val(bits.ToString(), literal.Type, ValKind.Direct);
|
return bits.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (literal.Type is FloatTypeNode { Width: 64 })
|
if (literal.Type is FloatTypeNode { Width: 64 })
|
||||||
{
|
{
|
||||||
var value = double.Parse(literal.Value, CultureInfo.InvariantCulture);
|
var value = double.Parse(literal.Value, CultureInfo.InvariantCulture);
|
||||||
var bits = BitConverter.DoubleToInt64Bits(value);
|
var bits = BitConverter.DoubleToInt64Bits(value);
|
||||||
return new Val(bits.ToString(), literal.Type, ValKind.Direct);
|
return bits.ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -905,14 +907,14 @@ public class QBEGenerator
|
|||||||
{
|
{
|
||||||
var stringLiteral = new StringLiteral(literal.Value, StringName());
|
var stringLiteral = new StringLiteral(literal.Value, StringName());
|
||||||
_stringLiterals.Add(stringLiteral);
|
_stringLiterals.Add(stringLiteral);
|
||||||
return new Val(stringLiteral.Name, literal.Type, ValKind.Direct);
|
return stringLiteral.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (literal.Type is CStringTypeNode)
|
if (literal.Type is CStringTypeNode)
|
||||||
{
|
{
|
||||||
var cStringLiteral = new CStringLiteral(literal.Value, CStringName());
|
var cStringLiteral = new CStringLiteral(literal.Value, CStringName());
|
||||||
_cStringLiterals.Add(cStringLiteral);
|
_cStringLiterals.Add(cStringLiteral);
|
||||||
return new Val(cStringLiteral.Name, literal.Type, ValKind.Direct);
|
return cStringLiteral.Name;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -921,7 +923,7 @@ public class QBEGenerator
|
|||||||
{
|
{
|
||||||
if (literal.Type is BoolTypeNode)
|
if (literal.Type is BoolTypeNode)
|
||||||
{
|
{
|
||||||
return new Val(bool.Parse(literal.Value) ? "1" : "0", literal.Type, ValKind.Direct);
|
return bool.Parse(literal.Value) ? "1" : "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -931,7 +933,7 @@ public class QBEGenerator
|
|||||||
throw new NotSupportedException($"Cannot create literal of kind '{literal.Kind}' for type {literal.Type}");
|
throw new NotSupportedException($"Cannot create literal of kind '{literal.Kind}' for type {literal.Type}");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitStructInitializer(StructInitializerNode structInitializer, string? destination = null)
|
private string EmitStructInitializer(StructInitializerNode structInitializer, string? destination = null)
|
||||||
{
|
{
|
||||||
var structDef = _definitionTable.LookupStruct(structInitializer.StructType.Name);
|
var structDef = _definitionTable.LookupStruct(structInitializer.StructType.Name);
|
||||||
|
|
||||||
@@ -959,10 +961,10 @@ public class QBEGenerator
|
|||||||
EmitCopyIntoOrInitialize(valueExpression, offset);
|
EmitCopyIntoOrInitialize(valueExpression, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Val(destination, structInitializer.StructType, ValKind.Direct);
|
return destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitUnaryExpression(UnaryExpressionNode unaryExpression)
|
private string EmitUnaryExpression(UnaryExpressionNode unaryExpression)
|
||||||
{
|
{
|
||||||
var operand = EmitUnwrap(EmitExpression(unaryExpression.Operand));
|
var operand = EmitUnwrap(EmitExpression(unaryExpression.Operand));
|
||||||
var outputName = TmpName();
|
var outputName = TmpName();
|
||||||
@@ -975,16 +977,16 @@ public class QBEGenerator
|
|||||||
{
|
{
|
||||||
case IntTypeNode { Signed: true, Width: 64 }:
|
case IntTypeNode { Signed: true, Width: 64 }:
|
||||||
_writer.Indented($"{outputName} =l neg {operand}");
|
_writer.Indented($"{outputName} =l neg {operand}");
|
||||||
return new Val(outputName, unaryExpression.Type, ValKind.Direct);
|
return outputName;
|
||||||
case IntTypeNode { Signed: true, Width: 8 or 16 or 32 }:
|
case IntTypeNode { Signed: true, Width: 8 or 16 or 32 }:
|
||||||
_writer.Indented($"{outputName} =w neg {operand}");
|
_writer.Indented($"{outputName} =w neg {operand}");
|
||||||
return new Val(outputName, unaryExpression.Type, ValKind.Direct);
|
return outputName;
|
||||||
case FloatTypeNode { Width: 64 }:
|
case FloatTypeNode { Width: 64 }:
|
||||||
_writer.Indented($"{outputName} =d neg {operand}");
|
_writer.Indented($"{outputName} =d neg {operand}");
|
||||||
return new Val(outputName, unaryExpression.Type, ValKind.Direct);
|
return outputName;
|
||||||
case FloatTypeNode { Width: 32 }:
|
case FloatTypeNode { Width: 32 }:
|
||||||
_writer.Indented($"{outputName} =s neg {operand}");
|
_writer.Indented($"{outputName} =s neg {operand}");
|
||||||
return new Val(outputName, unaryExpression.Type, ValKind.Direct);
|
return outputName;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -995,7 +997,7 @@ public class QBEGenerator
|
|||||||
{
|
{
|
||||||
case BoolTypeNode:
|
case BoolTypeNode:
|
||||||
_writer.Indented($"{outputName} =w xor {operand}, 1");
|
_writer.Indented($"{outputName} =w xor {operand}, 1");
|
||||||
return new Val(outputName, unaryExpression.Type, ValKind.Direct);
|
return outputName;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@@ -1009,7 +1011,7 @@ public class QBEGenerator
|
|||||||
throw new NotSupportedException($"Unary operator {unaryExpression.Operator} for type {unaryExpression.Operand.Type} not supported");
|
throw new NotSupportedException($"Unary operator {unaryExpression.Operator} for type {unaryExpression.Operand.Type} not supported");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitStructFieldAccess(StructFieldAccessNode structFieldAccess)
|
private string EmitStructFieldAccess(StructFieldAccessNode structFieldAccess)
|
||||||
{
|
{
|
||||||
var target = EmitUnwrap(EmitExpression(structFieldAccess.Target));
|
var target = EmitUnwrap(EmitExpression(structFieldAccess.Target));
|
||||||
|
|
||||||
@@ -1019,16 +1021,10 @@ public class QBEGenerator
|
|||||||
var output = TmpName();
|
var output = TmpName();
|
||||||
_writer.Indented($"{output} =l add {target}, {offset}");
|
_writer.Indented($"{output} =l add {target}, {offset}");
|
||||||
|
|
||||||
// If the accessed member is an inline struct, it will not be a pointer
|
return output;
|
||||||
if (structFieldAccess.Type is StructTypeNode)
|
|
||||||
{
|
|
||||||
return new Val(output, structFieldAccess.Type, ValKind.Direct);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new Val(output, structFieldAccess.Type, ValKind.Pointer);
|
private string EmitStructFuncCall(StructFuncCallNode structFuncCall)
|
||||||
}
|
|
||||||
|
|
||||||
private Val EmitStructFuncCall(StructFuncCallNode structFuncCall)
|
|
||||||
{
|
{
|
||||||
var structDef = _definitionTable.LookupStruct(structFuncCall.StructType.Name);
|
var structDef = _definitionTable.LookupStruct(structFuncCall.StructType.Name);
|
||||||
var func = StructFuncName(structDef.Name, structFuncCall.Name);
|
var func = StructFuncName(structDef.Name, structFuncCall.Name);
|
||||||
@@ -1046,17 +1042,17 @@ public class QBEGenerator
|
|||||||
if (structFuncCall.Type is VoidTypeNode)
|
if (structFuncCall.Type is VoidTypeNode)
|
||||||
{
|
{
|
||||||
_writer.Indented($"call {func}({string.Join(", ", parameterStrings)})");
|
_writer.Indented($"call {func}({string.Join(", ", parameterStrings)})");
|
||||||
return new Val(string.Empty, structFuncCall.Type, ValKind.Direct);
|
return string.Empty;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var outputName = TmpName();
|
var outputName = TmpName();
|
||||||
_writer.Indented($"{outputName} {QBEAssign(structFuncCall.Type)} call {func}({string.Join(", ", parameterStrings)})");
|
_writer.Indented($"{outputName} {QBEAssign(structFuncCall.Type)} call {func}({string.Join(", ", parameterStrings)})");
|
||||||
return new Val(outputName, structFuncCall.Type, ValKind.Direct);
|
return outputName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitInterfaceFuncCall(InterfaceFuncCallNode interfaceFuncCall)
|
private string EmitInterfaceFuncCall(InterfaceFuncCallNode interfaceFuncCall)
|
||||||
{
|
{
|
||||||
var target = EmitUnwrap(EmitExpression(interfaceFuncCall.InterfaceExpression));
|
var target = EmitUnwrap(EmitExpression(interfaceFuncCall.InterfaceExpression));
|
||||||
|
|
||||||
@@ -1087,17 +1083,17 @@ public class QBEGenerator
|
|||||||
if (interfaceFuncCall.Type is VoidTypeNode)
|
if (interfaceFuncCall.Type is VoidTypeNode)
|
||||||
{
|
{
|
||||||
_writer.Indented($"call {func}({string.Join(", ", parameterStrings)})");
|
_writer.Indented($"call {func}({string.Join(", ", parameterStrings)})");
|
||||||
return new Val(string.Empty, interfaceFuncCall.Type, ValKind.Direct);
|
return string.Empty;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var outputName = TmpName();
|
var outputName = TmpName();
|
||||||
_writer.Indented($"{outputName} {QBEAssign(interfaceFuncCall.Type)} call {func}({string.Join(", ", parameterStrings)})");
|
_writer.Indented($"{outputName} {QBEAssign(interfaceFuncCall.Type)} call {func}({string.Join(", ", parameterStrings)})");
|
||||||
return new Val(outputName, interfaceFuncCall.Type, ValKind.Direct);
|
return outputName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitInterfaceInitializer(InterfaceInitializerNode interfaceInitializer, string? destination = null)
|
private string EmitInterfaceInitializer(InterfaceInitializerNode interfaceInitializer, string? destination = null)
|
||||||
{
|
{
|
||||||
var implementation = EmitUnwrap(EmitExpression(interfaceInitializer.Implementation));
|
var implementation = EmitUnwrap(EmitExpression(interfaceInitializer.Implementation));
|
||||||
|
|
||||||
@@ -1126,10 +1122,10 @@ public class QBEGenerator
|
|||||||
_writer.Indented($"{objectPointer} =l add {destination}, 8");
|
_writer.Indented($"{objectPointer} =l add {destination}, 8");
|
||||||
_writer.Indented($"storel {implementation}, {objectPointer}");
|
_writer.Indented($"storel {implementation}, {objectPointer}");
|
||||||
|
|
||||||
return new Val(destination, interfaceInitializer.InterfaceType, ValKind.Direct);
|
return destination;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Val EmitFuncCall(FuncCallNode funcCall)
|
private string EmitFuncCall(FuncCallNode funcCall)
|
||||||
{
|
{
|
||||||
var expression = EmitExpression(funcCall.Expression);
|
var expression = EmitExpression(funcCall.Expression);
|
||||||
|
|
||||||
@@ -1145,24 +1141,19 @@ public class QBEGenerator
|
|||||||
if (funcCall.Type is VoidTypeNode)
|
if (funcCall.Type is VoidTypeNode)
|
||||||
{
|
{
|
||||||
_writer.Indented($"call {funcPointer}({string.Join(", ", parameterStrings)})");
|
_writer.Indented($"call {funcPointer}({string.Join(", ", parameterStrings)})");
|
||||||
return new Val(string.Empty, funcCall.Type, ValKind.Direct);
|
return string.Empty;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var outputName = TmpName();
|
var outputName = TmpName();
|
||||||
_writer.Indented($"{outputName} {QBEAssign(funcCall.Type)} call {funcPointer}({string.Join(", ", parameterStrings)})");
|
_writer.Indented($"{outputName} {QBEAssign(funcCall.Type)} call {funcPointer}({string.Join(", ", parameterStrings)})");
|
||||||
return new Val(outputName, funcCall.Type, ValKind.Direct);
|
return outputName;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private string EmitUnwrap(Val val)
|
private string EmitUnwrap(Val val)
|
||||||
{
|
{
|
||||||
return val.Kind switch
|
return val.Name;
|
||||||
{
|
|
||||||
ValKind.Direct => val.Name,
|
|
||||||
ValKind.Pointer => EmitLoad(val.Type, val.Name).Name,
|
|
||||||
_ => throw new ArgumentOutOfRangeException()
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int SizeOf(TypeNode type)
|
private static int SizeOf(TypeNode type)
|
||||||
@@ -1329,7 +1320,7 @@ public class CStringLiteral(string value, string name)
|
|||||||
public string Name { get; } = name;
|
public string Name { get; } = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Val(string Name, TypeNode Type, ValKind Kind);
|
public record Val(string Name, TypeNode Type, bool IsLValue);
|
||||||
|
|
||||||
public class Scope(Scope? parent = null)
|
public class Scope(Scope? parent = null)
|
||||||
{
|
{
|
||||||
@@ -1356,9 +1347,3 @@ public class Scope(Scope? parent = null)
|
|||||||
return new Scope(this);
|
return new Scope(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public enum ValKind
|
|
||||||
{
|
|
||||||
Pointer,
|
|
||||||
Direct,
|
|
||||||
}
|
|
||||||
@@ -22,36 +22,36 @@ public enum BinaryOperator
|
|||||||
Divide
|
Divide
|
||||||
}
|
}
|
||||||
|
|
||||||
public abstract record ExpressionNode(TypeNode Type) : Node;
|
public abstract record ExpressionNode(TypeNode Type, bool IsLValue) : Node;
|
||||||
|
|
||||||
public record BinaryExpressionNode(TypeNode Type, ExpressionNode Left, BinaryOperator Operator, ExpressionNode Right) : ExpressionNode(Type);
|
public record BinaryExpressionNode(TypeNode Type, ExpressionNode Left, BinaryOperator Operator, ExpressionNode Right) : ExpressionNode(Type, false);
|
||||||
|
|
||||||
public record UnaryExpressionNode(TypeNode Type, UnaryOperator Operator, ExpressionNode Operand) : ExpressionNode(Type);
|
public record UnaryExpressionNode(TypeNode Type, UnaryOperator Operator, ExpressionNode Operand) : ExpressionNode(Type, false);
|
||||||
|
|
||||||
public record FuncCallNode(TypeNode Type, ExpressionNode Expression, IReadOnlyList<ExpressionNode> Parameters) : ExpressionNode(Type);
|
public record FuncCallNode(TypeNode Type, ExpressionNode Expression, IReadOnlyList<ExpressionNode> Parameters) : ExpressionNode(Type, false);
|
||||||
|
|
||||||
public record StructFuncCallNode(TypeNode Type, string Name, StructTypeNode StructType, ExpressionNode StructExpression, IReadOnlyList<ExpressionNode> Parameters) : ExpressionNode(Type);
|
public record StructFuncCallNode(TypeNode Type, string Name, StructTypeNode StructType, ExpressionNode StructExpression, IReadOnlyList<ExpressionNode> Parameters) : ExpressionNode(Type, false);
|
||||||
|
|
||||||
public record InterfaceFuncCallNode(TypeNode Type, string Name, InterfaceTypeNode InterfaceType, ExpressionNode InterfaceExpression, IReadOnlyList<ExpressionNode> Parameters) : ExpressionNode(Type);
|
public record InterfaceFuncCallNode(TypeNode Type, string Name, InterfaceTypeNode InterfaceType, ExpressionNode InterfaceExpression, IReadOnlyList<ExpressionNode> Parameters) : ExpressionNode(Type, false);
|
||||||
|
|
||||||
public record VariableIdentNode(TypeNode Type, string Name) : ExpressionNode(Type);
|
public record VariableIdentNode(TypeNode Type, string Name) : ExpressionNode(Type, true);
|
||||||
|
|
||||||
public record LocalFuncIdentNode(TypeNode Type, string Name) : ExpressionNode(Type);
|
public record LocalFuncIdentNode(TypeNode Type, string Name) : ExpressionNode(Type, false);
|
||||||
|
|
||||||
public record ExternFuncIdentNode(TypeNode Type, string Name) : ExpressionNode(Type);
|
public record ExternFuncIdentNode(TypeNode Type, string Name) : ExpressionNode(Type, false);
|
||||||
|
|
||||||
public record ArrayInitializerNode(TypeNode Type, ExpressionNode Capacity, TypeNode ElementType) : ExpressionNode(Type);
|
public record ArrayInitializerNode(TypeNode Type, ExpressionNode Capacity, TypeNode ElementType) : ExpressionNode(Type, true);
|
||||||
|
|
||||||
public record ArrayIndexAccessNode(TypeNode Type, ExpressionNode Target, ExpressionNode Index) : ExpressionNode(Type);
|
public record ArrayIndexAccessNode(TypeNode Type, ExpressionNode Target, ExpressionNode Index) : ExpressionNode(Type, true);
|
||||||
|
|
||||||
public record AddressOfNode(TypeNode Type, ExpressionNode Expression) : ExpressionNode(Type);
|
public record AddressOfNode(TypeNode Type, ExpressionNode Expression) : ExpressionNode(Type, false);
|
||||||
|
|
||||||
public record LiteralNode(TypeNode Type, string Value, LiteralKind Kind) : ExpressionNode(Type);
|
public record LiteralNode(TypeNode Type, string Value, LiteralKind Kind) : ExpressionNode(Type, false);
|
||||||
|
|
||||||
public record StructFieldAccessNode(TypeNode Type, StructTypeNode StructType, ExpressionNode Target, string Field) : ExpressionNode(Type);
|
public record StructFieldAccessNode(TypeNode Type, StructTypeNode StructType, ExpressionNode Target, string Field) : ExpressionNode(Type, true);
|
||||||
|
|
||||||
public record StructInitializerNode(StructTypeNode StructType, Dictionary<string, ExpressionNode> Initializers) : ExpressionNode(StructType);
|
public record StructInitializerNode(StructTypeNode StructType, Dictionary<string, ExpressionNode> Initializers) : ExpressionNode(StructType, true);
|
||||||
|
|
||||||
public record DereferenceNode(TypeNode Type, ExpressionNode Expression) : ExpressionNode(Type);
|
public record DereferenceNode(TypeNode Type, ExpressionNode Expression) : ExpressionNode(Type, false);
|
||||||
|
|
||||||
public record InterfaceInitializerNode(TypeNode Type, InterfaceTypeNode InterfaceType, StructTypeNode StructType, ExpressionNode Implementation) : ExpressionNode(Type);
|
public record InterfaceInitializerNode(TypeNode Type, InterfaceTypeNode InterfaceType, StructTypeNode StructType, ExpressionNode Implementation) : ExpressionNode(Type, true);
|
||||||
Reference in New Issue
Block a user