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 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 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 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 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 VarargExpressionGenerator(GeneratorFactory factory, FunctionDefinitionSyntaxNode func, VarargExpressionSyntaxNode expr) : base(0) { _isVararg = expr.ReceiverMultiRetState == ExpressionReceiverMultiRetState.Variable; _type = func.VarargType.GetVMSpecializationType(); _funcVarargSig = factory.Function.VarargSignature; }
public InvocationStatementGenerator(GeneratorFactory factory, BlockGenerator block, InvocationStatementSyntaxNode stat) { _expr = factory.CreateExpression(block, stat.Invocation); }
protected ExpressionGenerator(GeneratorFactory factory) { _null = factory.Function.NullSlot; }
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,