Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
 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;
 }
Ejemplo n.º 3
0
        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());
                }
            }
Ejemplo n.º 4
0
        //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);
                }
            }
        }
Ejemplo n.º 5
0
 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());
     }
 }
Ejemplo n.º 6
0
        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);
        }