public GenericForStatementGenerator(GeneratorFactory factory, BlockGenerator block, GenericForBlockSyntaxNode stat) { //Create a wrapper block. //Actually this is not necessary with the current design. We could add everything to parent block. //But let's still have a separation. //Note that this block does not contain any upvals and statements and won't be used in emit step. _forBlock = new BlockGenerator(factory, block.Stack, stat); var v1g = factory.Function.Locals[stat.HiddenVariableF]; var v2g = factory.Function.Locals[stat.HiddenVariableS]; var v3g = factory.Function.Locals[stat.HiddenVariableV]; //To calculate the f,s,var tuple. //This will be inserted as the first statement of _forBlock. _assignment = new AssignmentStatementGenerator(factory, _forBlock, new() { v1g, v2g, v3g }, stat.ExpressionList); //Store the stack slot for f and var1. var ctrlVarOnStack = v1g.TryGetFromStack(out _hiddenVariableStack); Debug.Assert(ctrlVarOnStack); var var1OnStack = factory.Function.Locals[stat.LoopVariables[0]].TryGetFromStack(out _firstLoopVarStack); Debug.Assert(var1OnStack); //Get the return sig type. var sigWriter = new SignatureWriter(); foreach (var loopVar in stat.LoopVariables) { factory.Function.Locals[loopVar].WritSig(sigWriter); } (_loopVarSigType, _loopVarSig) = sigWriter.GetSignature(factory.Function.SignatureManager); }
public ConditionGenerator(GeneratorFactory factory, BlockGenerator block, ExpressionSyntaxNode expr, LabelStatementSyntaxNode falseLabel, bool reverseCondition) { while (expr is UnaryExpressionSyntaxNode unary && unary.Operator == UnaryOperator.Not) { expr = unary.Operand; reverseCondition = !reverseCondition; } if (expr is BinaryExpressionSyntaxNode bin && IsComparisonExpr(bin, out _opcode, out _exchangeComparison)) { _isComparison = true; //Normally, reverse the cmp (jump to false label if condition is not met). if (!reverseCondition) { ReverseComparisonResult(ref _opcode); } _expr1 = factory.CreateExpression(block, bin.Left); _expr2 = factory.CreateExpression(block, bin.Right); if (!_expr1.TryGetFromStack(out _)) { _expr1Stack = block.TempAllocator.Allocate(_expr1.GetSingleType()); } if (!_expr2.TryGetFromStack(out _)) { _expr2Stack = block.TempAllocator.Allocate(_expr2.GetSingleType()); } }
public RepeatStatementGenerator(GeneratorFactory factory, BlockGenerator block, RepeatBlockSyntaxNode stat) { _repeatLabel = new LabelStatementSyntaxNode(); _block = new BlockGenerator(factory, block.Stack, stat); //Jump to _repeatLabel (falseLabel) if false. _cond = new ConditionGenerator(factory, _block, stat.StopCondition, _repeatLabel, reverseCondition: false); }
//This is used by the public ctor and ComparisonBinaryExpressionGenerator. protected BinaryExpressionGenerator(GeneratorFactory factory, BlockGenerator block, ExpressionGenerator left, ExpressionGenerator right, VMSpecializationType type) : base(factory) { _type = type; _left = left; _right = right; var leftType = left.GetSingleType(); var rightType = right.GetSingleType(); if (leftType != VMSpecializationType.Polymorphic || rightType != VMSpecializationType.Polymorphic || _type != VMSpecializationType.Polymorphic) { throw new NotImplementedException(); } //Determine whether we can share the dest slot with one of the operands. //This saves a stack slot. // ? = (expr) + a //will be generated as // dest = (expr) // dest = dest + a //Note that at this point we have no idea what variable (or temp variable) //will be assigned to this binary expr, so for the code // a = (expr) + a //we will get an invalid code if we use the above pattern: // a = (expr) // a = a + a --> Wrong, the value that was in the second a has been lost! //This special case is handled during emit stage. var leftOnStack = left.TryGetFromStack(out _); var rightOnStack = right.TryGetFromStack(out _); if (leftType == _type && !leftOnStack) { _mode = CalcMode.LeftToDest; _rightTemp = block.TempAllocator.Allocate(rightType); } else if (rightType == _type && !rightOnStack) { _mode = CalcMode.RightToDest; _leftTemp = block.TempAllocator.Allocate(leftType); } else { _mode = CalcMode.Normal; if (!leftOnStack) { _leftTemp = block.TempAllocator.Allocate(leftType); } if (!rightOnStack) { _rightTemp = block.TempAllocator.Allocate(rightType); } } }
public StatementGenerator CreateStatement(BlockGenerator parentBlock, StatementSyntaxNode statement) { switch (statement) { case AssignmentStatementSyntaxNode assignment: return(new AssignmentStatementGenerator(this, parentBlock, assignment.Variables.Select(v => CreateVariable(parentBlock, v)).ToList(), assignment.Values)); case GenericForBlockSyntaxNode genericFor: return(new GenericForStatementGenerator(this, parentBlock, genericFor)); case GotoStatementSyntaxNode @goto: return(new GotoStatementGenerator(@goto.Target.Target)); case IfStatementSyntaxNode @if: return(new IfStatementGenerator(this, parentBlock, @if)); case InvocationStatementSyntaxNode invocation: return(new InvocationStatementGenerator(this, parentBlock, invocation)); case LabelStatementSyntaxNode label: return(new LabelStatementGenerator(label)); case LocalStatementSyntaxNode local: return(new AssignmentStatementGenerator(this, parentBlock, local.Variables.Select(v => Function.Locals[v]).ToList(), local.ExpressionList)); case NumericForBlockSyntaxNode numericFor: return(new NumericForStatementGenerator(this, parentBlock, numericFor)); case RepeatBlockSyntaxNode repeat: return(new RepeatStatementGenerator(this, parentBlock, repeat)); case ReturnStatementSyntaxNode @return: if (@return.Values.Expressions.Count == 0) { return(new ZeroReturnStatementGenerator()); } else { return(new MultiReturnStatementGenerator(this, parentBlock, @return)); } case WhileBlockSyntaxNode @while: return(new WhileStatementGenerator(this, parentBlock, @while)); case BlockSyntaxNode block: //Block as the last (should only match simple block and function definition). return(new BlockGenerator(this, parentBlock?.Stack ?? Function.LocalFragment, block)); default: break; } throw new Exception(); }
public UnaryExpressionGenerator(GeneratorFactory factory, BlockGenerator block, UnaryExpressionSyntaxNode expr) : base(factory) { _operand = factory.CreateExpression(block, expr.Operand); _operator = expr.Operator; _type = expr.SpecializationType.GetVMSpecializationType(); if (!_operand.TryGetFromStack(out _)) { _tmpSlot = block.TempAllocator.Allocate(_operand.GetSingleType()); } }
//This public ctor works for arithmetic binary ops. public BinaryExpressionGenerator(GeneratorFactory factory, BlockGenerator block, BinaryExpressionSyntaxNode expr) : this(factory, block, factory.CreateExpression(block, expr.Left), factory.CreateExpression(block, expr.Right), expr.SpecializationType.GetVMSpecializationType()) { _opcode = expr.Operator.V switch { BinaryOperator.Raw.Add => OpCodes.ADD, BinaryOperator.Raw.Sub => OpCodes.SUB, BinaryOperator.Raw.Mul => OpCodes.MUL, BinaryOperator.Raw.Div => OpCodes.DIV, BinaryOperator.Raw.Mod => OpCodes.MOD, BinaryOperator.Raw.Pow => OpCodes.POW, _ => throw new Exception(), //Should not get here. }; }
public IndexVariableGenerator(GeneratorFactory factory, BlockGenerator block, IndexVariableSyntaxNode expr) : base(factory) { _table = factory.CreateExpression(block, expr.Table); _key = factory.CreateExpression(block, expr.Key); _type = expr.SpecializationType.GetVMSpecializationType(); if (!_table.TryGetFromStack(out _)) { _tableStack = block.TempAllocator.Allocate(expr.Table); } if (!_key.TryGetFromStack(out _)) { _keyStack = block.TempAllocator.Allocate(expr.Key); } }
public AndOrExpressionGenerator(GeneratorFactory factory, BlockGenerator block, BinaryExpressionSyntaxNode expr) : base(factory) { _type = expr.SpecializationType.GetVMSpecializationType(); _left = factory.CreateExpression(block, expr.Left); _right = factory.CreateExpression(block, expr.Right); if (_left.GetSingleType() != _type) { _leftStack = block.TempAllocator.Allocate(_left.GetSingleType()); } if (_right.GetSingleType() != _type) { _rightStack = block.TempAllocator.Allocate(_right.GetSingleType()); } _opcode = expr.Operator.V == BinaryOperator.Raw.And ? OpCodes.ISFC : OpCodes.ISTC; }
public ExpressionGenerator CreateVariable(BlockGenerator parentBlock, VariableSyntaxNode expr) { switch (expr) { case NamedVariableSyntaxNode namedVariable: //Same as expr (LocalVariableExprGen and UpvalueExprGen handles both get and set). return(CreateExpression(parentBlock, namedVariable)); case IndexVariableSyntaxNode indexVariable: return(new IndexVariableGenerator(this, parentBlock, indexVariable)); default: break; } throw new Exception(); }
public NumericForStatementGenerator(GeneratorFactory factory, BlockGenerator block, NumericForBlockSyntaxNode stat) { var stack = new GroupStackFragment(); block.Stack.Add(stack); _e1 = factory.CreateExpression(block, stat.From); _e2 = factory.CreateExpression(block, stat.To); var stepExpr = stat.Step ?? new LiteralExpressionSyntaxNode() { DoubleValue = 1 }; _e3 = factory.CreateExpression(block, stepExpr); var e1t = _e1.GetSingleType(); var e2t = _e2.GetSingleType(); var e3t = _e3.GetSingleType(); if (e1t == VMSpecializationType.Polymorphic && e2t == VMSpecializationType.Polymorphic && e3t == VMSpecializationType.Polymorphic) { _initOp = Opcodes.FORI; _loopOp = Opcodes.FORL; } else { throw new NotImplementedException(); } var ctrlStack = new BlockStackFragment(); stack.Add(ctrlStack); _e1Stack = ctrlStack.AddSpecializedType(e1t); _e2Stack = ctrlStack.AddSpecializedType(e2t); _e3Stack = ctrlStack.AddSpecializedType(e3t); //Use stack (so it's after control variables). //This will also handle the aux block for us. _forBlock = new BlockGenerator(factory, stack, stat); var loopVar = factory.Function.Locals[stat.Variable]; var loopVarOnStack = loopVar.TryGetFromStack(out _loopVar); Debug.Assert(loopVarOnStack); }
public IndexExpressionGenerator(GeneratorFactory factory, BlockGenerator block, IndexVariableSyntaxNode expr) : base(factory, block, GetTable(factory, block, expr, out var key, out var type), key, type)
public WhileStatementGenerator(GeneratorFactory factory, BlockGenerator block, WhileBlockSyntaxNode stat) { _exitLabel = new LabelStatementSyntaxNode(); _cond = new ConditionGenerator(factory, block, stat.Condition, _exitLabel, reverseCondition: false); _block = new BlockGenerator(factory, block.Stack, stat); }
public ExpressionGenerator CreateExpression(BlockGenerator parentBlock, ExpressionSyntaxNode expr) { switch (expr) { case BinaryExpressionSyntaxNode binary: { switch (binary.Operator.V) { case BinaryOperator.Raw.Add: case BinaryOperator.Raw.Sub: case BinaryOperator.Raw.Mul: case BinaryOperator.Raw.Div: case BinaryOperator.Raw.Pow: case BinaryOperator.Raw.Mod: return(new BinaryExpressionGenerator(this, parentBlock, binary)); case BinaryOperator.Raw.Conc: return(new ConcatBinaryExpressionGenerator(this, parentBlock, binary)); case BinaryOperator.Raw.L: case BinaryOperator.Raw.LE: case BinaryOperator.Raw.G: case BinaryOperator.Raw.GE: case BinaryOperator.Raw.E: case BinaryOperator.Raw.NE: return(new ComparisonBinaryExpressionGenerator(this, parentBlock, binary)); case BinaryOperator.Raw.And: case BinaryOperator.Raw.Or: return(new AndOrExpressionGenerator(this, parentBlock, binary)); default: break; } break; } case FunctionExpressionSyntaxNode function: return(new FunctionExpressionGenerator(this, function)); case IndexVariableSyntaxNode indexVariable: return(new IndexExpressionGenerator(this, parentBlock, indexVariable)); case InvocationExpressionSyntaxNode invocation: return(new InvocationExpressionGenerator(this, parentBlock, invocation)); case LiteralExpressionSyntaxNode literal: return(new LiteralExpressionGenerator(Function, literal)); case NamedVariableSyntaxNode nameVariable: { //We don't create from the expr syntax node, so confirm the type is correct. var ret = Function.Locals[nameVariable.Variable.Target]; Debug.Assert(nameVariable.SpecializationType.GetVMSpecializationType() == ret.GetSingleType()); return(ret); } case TableExpressionSyntaxNode table: return(new TableExpressionGenerator(this, parentBlock, table)); case UnaryExpressionSyntaxNode unary: return(new UnaryExpressionGenerator(this, parentBlock, unary)); case VarargExpressionSyntaxNode vararg: return(new VarargExpressionGenerator(Function.FunctionDefinition, vararg)); default: break; } throw new Exception(); }
public InvocationStatementGenerator(GeneratorFactory factory, BlockGenerator block, InvocationStatementSyntaxNode stat) { _expr = factory.CreateExpression(block, stat.Invocation); }
public ComparisonBinaryExpressionGenerator(GeneratorFactory factory, BlockGenerator block, BinaryExpressionSyntaxNode expr) : base(factory, block, CheckSwap(factory, block, expr, out var right, out var op, out var r), right,