public override void EmitGet(InstructionWriter writer, AllocatedLocal dest) { var leftStack = _leftStack ?? dest; var rightStack = _rightStack ?? dest; if (_left.GetSingleType() != _type || _right.GetSingleType() != _type) { //Needs conversion in MOV and ISTC. throw new NotImplementedException(); } if (leftStack.Offset > 255 || rightStack.Offset > 255 || dest.Offset > 255) { throw new NotImplementedException(); } // emit leftStack = _left // ISFC/ISTC dest, leftStack, exitLabel // emit rightStack = _right // MOV dest, rightStack //exitLabel: var exitLabel = new LabelStatementSyntaxNode(); _left.EmitPrep(writer); _left.EmitGet(writer, leftStack); writer.WriteUUS(_opcode, dest.Offset, leftStack.Offset, 0); writer.AddLabelFix(exitLabel, InstructionWriter.FixUUSJump); _right.EmitPrep(writer); _right.EmitGet(writer, rightStack); //We already wrote to dest. No need to MOV. Debug.Assert(rightStack.Offset == dest.Offset); writer.MarkLabel(exitLabel); }
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 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()); } }
//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()); } }
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); }