Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions Cesium.CodeGen/Extensions/BlockItemEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using Cesium.CodeGen.Ir.BlockItems;
using Cesium.CodeGen.Ir.Declarations;
using Cesium.Core;
using System.Diagnostics;
using AmbiguousBlockItem = Cesium.Ast.AmbiguousBlockItem;
using BreakStatement = Cesium.Ast.BreakStatement;
using CaseStatement = Cesium.Ast.CaseStatement;
Expand Down Expand Up @@ -57,4 +58,130 @@ private static IBlockItem ToIntermediate(Declaration d, IDeclarationScope scope)
}).ToList(), null)
{ InheritScope = true };
}

public static void Dump(this IBlockItem blockItem, TextWriter writer, int indentLevel)
{
var indent = new string(' ', indentLevel * 4);
switch (blockItem)
{
case Ir.BlockItems.CompoundStatement compoundStatement:
writer.WriteLine($"{indent}{{");
foreach (var item in compoundStatement.Statements)
{
Dump(item, writer, indentLevel + 1);
}
Console.WriteLine($"{indent}}}");
break;
case Ir.BlockItems.ExpressionStatement expressionStatement:
writer.Write(indent + " ");
expressionStatement.Expression?.Dump(writer);
writer.WriteLine(";");
break;
case Ir.BlockItems.IfElseStatement ifElseStatement:
writer.Write($"{indent} if (");
ifElseStatement.Expression?.Dump(writer);
writer.WriteLine(")");
ifElseStatement.TrueBranch.Dump(writer, indentLevel + 1);
if (ifElseStatement.FalseBranch is { } falseBranch)
{
writer.WriteLine($"{indent} else");
falseBranch.Dump(writer, indentLevel + 1);
}
break;
case Ir.BlockItems.GoToStatement gotoStatement:
writer.Write($"{indent} goto ");
writer.Write(gotoStatement.Identifier);
writer.WriteLine(";");
break;
case Ir.BlockItems.LabelStatement labelStatement:
writer.WriteLine($"{indent}{labelStatement.Identifier}:");
labelStatement.Expression.Dump(writer, indentLevel + 1);
break;
case Ir.BlockItems.ReturnStatement returnStatement:
writer.Write($"{indent}return ");
returnStatement.Expression?.Dump(writer);
writer.WriteLine(";");
break;
default:
Debug.Assert(false, $"Dumping {blockItem.GetType().Name} not implemented");
break;
}
}
public static void Dump(this Ir.Expressions.IExpression expression, TextWriter writer)
{
switch (expression)
{
case Ir.Expressions.DiscardResultExpression discardResultExpression:
discardResultExpression.Expression.Dump(writer);
break;
case Ir.Expressions.SetValueExpression setValueExpression:
setValueExpression.Value.Dump(writer);
writer.Write(" = ");
setValueExpression.Expression.Dump(writer);
break;
case Ir.Expressions.GetValueExpression getValueExpression:
getValueExpression.Value.Dump(writer);
break;
case Ir.Expressions.BinaryOperators.BinaryOperatorExpression binaryExpression:
binaryExpression.Left.Dump(writer);
binaryExpression.Operator.Dump(writer);
binaryExpression.Right.Dump(writer);
break;
case Ir.Expressions.ConstantLiteralExpression constLiteralExpression:
constLiteralExpression.Constant.Dump(writer);
break;
case Ir.Expressions.PostfixIncrementDecrementExpression.DuplicateValueExpression duplicateValueExpression:
duplicateValueExpression.Value.Dump(writer);
break;
case Ir.Expressions.PostfixIncrementDecrementExpression.ValuePreservationExpression valuePreservationExpression:
valuePreservationExpression.Expression.Dump(writer);
break;
default:
Debug.Assert(false, $"Dumping {expression.GetType().Name} not implemented");
break;
}
}
public static void Dump(this Ir.Expressions.Values.IValue expression, TextWriter writer)
{
switch (expression)
{
case Ir.Expressions.Values.LValueLocalVariable localValueVariable:
if (localValueVariable.Definition is { })
{
writer.Write(localValueVariable.Definition.ToString());
}
else
{
writer.Write($"<var #{localValueVariable.VarIndex}>");
}

break;
default:
Debug.Assert(false, $"Dumping {expression.GetType().Name} not implemented");
break;
}
}
public static void Dump(this Ir.Expressions.Constants.IConstant expression, TextWriter writer)
{
switch (expression)
{
case Ir.Expressions.Constants.IntegerConstant integerConstant:
writer.Write(integerConstant.Value.ToString());

break;
default:
Debug.Assert(false, $"Dumping {expression.GetType().Name} not implemented");
break;
}
}
public static void Dump(this Ir.Expressions.BinaryOperators.BinaryOperator expression, TextWriter writer)
{
var operatorString = expression switch
{
Ir.Expressions.BinaryOperators.BinaryOperator.Add => "+",
Ir.Expressions.BinaryOperators.BinaryOperator.EqualTo => "==",
_ => throw new InvalidOperationException($"Dumping BinaryOperator.{expression} not implemented"),
};
writer.Write(operatorString);
}
}
10 changes: 5 additions & 5 deletions Cesium.CodeGen/Ir/Expressions/DiscardResultExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,20 @@ namespace Cesium.CodeGen.Ir.Expressions;

internal class DiscardResultExpression : IExpression
{
private IExpression _expression;
internal IExpression Expression { get; set; }

public DiscardResultExpression(IExpression expression)
{
_expression = expression;
Expression = expression;
}

public IExpression Lower(IDeclarationScope scope) => new DiscardResultExpression(_expression.Lower(scope));
public IExpression Lower(IDeclarationScope scope) => new DiscardResultExpression(Expression.Lower(scope));

public void EmitTo(IEmitScope scope)
{
if (_expression is SetValueExpression sv)
if (Expression is SetValueExpression sv)
sv.NoReturn().EmitTo(scope);
else _expression.EmitTo(scope);
else Expression.EmitTo(scope);

var processor = scope.Method.Body.GetILProcessor();
processor.Emit(OpCodes.Pop);
Expand Down
10 changes: 5 additions & 5 deletions Cesium.CodeGen/Ir/Expressions/GetValueExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ namespace Cesium.CodeGen.Ir.Expressions;

internal sealed class GetValueExpression : IValueExpression
{
private readonly IValue _value;
internal IValue Value { get; }

public GetValueExpression(IValue value)
{
_value = value;
Value = value;
}

public IExpression Lower(IDeclarationScope scope) => this;

public void EmitTo(IEmitScope scope) => _value.EmitGetValue(scope);
public void EmitTo(IEmitScope scope) => Value.EmitGetValue(scope);

public IType GetExpressionType(IDeclarationScope scope) => _value.GetValueType();
public IType GetExpressionType(IDeclarationScope scope) => Value.GetValueType();

public IValue Resolve(IDeclarationScope scope) => _value;
public IValue Resolve(IDeclarationScope scope) => Value;
}
Original file line number Diff line number Diff line change
Expand Up @@ -70,38 +70,40 @@ public IExpression Lower(IDeclarationScope scope)
/// <summary>
/// Emits the <c>dup</c> opcode for the passed value. Thus, leaves two values on the stack. Use with caution.
/// </summary>
private class DuplicateValueExpression : IExpression
internal class DuplicateValueExpression : IExpression
{
private readonly IValue _value;
internal IValue Value { get; }

internal DuplicateValueExpression(IValue value)
{
_value = value;
Value = value;
}

public IExpression Lower(IDeclarationScope scope) => this;

public void EmitTo(IEmitScope scope)
{
_value.EmitGetValue(scope);
Value.EmitGetValue(scope);
scope.Dup();
}

public IType GetExpressionType(IDeclarationScope scope) => _value.GetValueType();
public IType GetExpressionType(IDeclarationScope scope) => Value.GetValueType();
}

/// <summary>
/// Provides access to already loaded value (already stored on stack before this expression).
/// </summary>
private class ValuePreservationExpression(IValue value, IExpression expression) : IExpression
internal class ValuePreservationExpression(IValue value, IExpression expression) : IExpression
{
public IExpression Expression { get; } = expression;

public IExpression Lower(IDeclarationScope scope) =>
new ValuePreservationExpression(value, expression.Lower(scope));
new ValuePreservationExpression(value, Expression.Lower(scope));

public void EmitTo(IEmitScope scope)
{
if (expression is not SetValueExpression sv)
throw new AssertException($"{expression} should be a {nameof(SetValueExpression)}.");
if (Expression is not SetValueExpression sv)
throw new AssertException($"{Expression} should be a {nameof(SetValueExpression)}.");

sv
.NoReturn() // thus exposes the previously set value
Expand Down
12 changes: 8 additions & 4 deletions Cesium.CodeGen/Ir/Expressions/SetValueExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ internal sealed class SetValueExpression : IExpression
private readonly IExpression _expression;
private readonly bool _doReturn;

internal ILValue Value => _value;

internal IExpression Expression => _expression;

public SetValueExpression(ILValue value, IExpression expression, bool doReturn = true)
{
_value = value;
Expand All @@ -25,15 +29,15 @@ public SetValueExpression(ILValue value, IExpression expression, bool doReturn =

public void EmitTo(IEmitScope scope)
{
_value.EmitSetValue(scope, _expression);
Value.EmitSetValue(scope, Expression);

if (_doReturn)
_value.EmitGetValue(scope);
Value.EmitGetValue(scope);
}

public IType GetExpressionType(IDeclarationScope scope) => _doReturn
? _value.GetValueType()
? Value.GetValueType()
: new PrimitiveType(PrimitiveTypeKind.Void);

public IExpression NoReturn() => new SetValueExpression(_value, _expression, false);
public IExpression NoReturn() => new SetValueExpression(Value, Expression, false);
}
12 changes: 8 additions & 4 deletions Cesium.CodeGen/Ir/Expressions/Values/LValueLocalVariable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ internal sealed class LValueLocalVariable : ILValue
private readonly int _varIndex;
private VariableDefinition? _definition;

public int VarIndex => _varIndex;

public VariableDefinition? Definition { get => _definition; set => _definition = value; }

public LValueLocalVariable(IType variableType, int varIndex)
{
_variableType = variableType;
Expand All @@ -30,8 +34,8 @@ public void EmitGetValue(IEmitScope scope)
1 => Instruction.Create(OpCodes.Ldloc_1),
2 => Instruction.Create(OpCodes.Ldloc_2),
3 => Instruction.Create(OpCodes.Ldloc_3),
<= sbyte.MaxValue => Instruction.Create(OpCodes.Ldloc_S, _definition),
_ => Instruction.Create(OpCodes.Ldloc, _definition)
<= sbyte.MaxValue => Instruction.Create(OpCodes.Ldloc_S, Definition),
_ => Instruction.Create(OpCodes.Ldloc, Definition)
});
}

Expand All @@ -49,7 +53,7 @@ public void EmitGetAddress(IEmitScope scope)
variable.Index <= sbyte.MaxValue
? OpCodes.Ldloca_S
: OpCodes.Ldloca,
_definition
Definition
)
);
}
Expand Down Expand Up @@ -80,5 +84,5 @@ public void EmitSetValue(IEmitScope scope, IExpression value)
public IType GetValueType() => _variableType;

private VariableDefinition GetVariableDefinition(IEmitScope scope) =>
_definition ??= scope.ResolveVariable(_varIndex);
Definition ??= scope.ResolveVariable(VarIndex);
}
Loading