private AstNode EmitMultiDimensionalArrayInitializer()
        {
            List <int>       dimensions     = null;
            MethodInfo       arraySetMethod = null;
            AstNodeDecorator nodeDecorator  = null;
            var arrayCreation = Node.Parent as ArrayCreateExpression;
            var specifier     = arrayCreation.AdditionalArraySpecifiers.First();

            Type[] types            = new Type[specifier.Dimensions + 1];
            Type[] constructorTypes = new Type[specifier.Dimensions];

            Enumerable.Range(0, specifier.Dimensions)
            .ForEach(i => types[i] = constructorTypes[i] = TypeSystem.Int);

            types[types.Length - 1] = _typeToEmit;
            arraySetMethod          = Type.GetMethod("Set", types);
            dimensions = BuildDimsnsions(arrayCreation);
            dimensions.ForEach(d => ILGenerator.EmitPushInteger(d));
            ILGenerator.Emit(OpCodes.Newobj, Type.GetConstructor(constructorTypes));
            ILGenerator.EmitStoreLocal(_localBuilder);

            BuildIndexesRecursively(Node, new List <int>()).ForEach((tuple, i) => {
                ILGenerator.EmitLoadLocal(_localBuilder);
                tuple.Item2.ForEach(index => ILGenerator.EmitPushInteger(index));
                nodeDecorator = tuple.Item1.AcceptVisitor(ILGenerator, Visitor);
                ILGenerator.EmitCastIfNeeded(nodeDecorator.Type, _typeToEmit);
                ILGenerator.Emit(OpCodes.Call, arraySetMethod);
            });

            ILGenerator.EmitLoadLocal(_localBuilder, true);

            return(new AstNodeDecorator(Node, Type));
        }
        private void EmitElementRef(AstNode node, int index)
        {
            AstNodeDecorator nodeDecorator = null;

            ILGenerator.EmitLoadLocal(_localBuilder);
            ILGenerator.EmitPushInteger(index);
            nodeDecorator = node.AcceptVisitor(ILGenerator, Visitor);
            ILGenerator.EmitCastIfNeeded(nodeDecorator.Type, _typeToEmit);
            ILGenerator.Emit(OpCodes.Stelem_Ref);
        }
        private void EmitPrimitiveElement(AstNode node, int index)
        {
            AstNodeDecorator astDecorator = null;

            ILGenerator.EmitLoadLocal(_localBuilder);
            ILGenerator.EmitPushInteger(index);
            ILGenerator.EmitLoadElementArrayIfNeeded(_typeToEmit);
            astDecorator = node.AcceptVisitor(ILGenerator, Visitor);
            ILGenerator.EmitStoreElementByType(astDecorator.Type);
        }
Exemple #4
0
        public override AstNode VisitInvocationExpression(InvocationExpression invocationExpression, ILGenerator data)
        {
            var localBuilder = Locals[Locals.Count - 1];

            invocationExpression.Arguments.ForEach((arg, i) => {
                AstNodeDecorator decorator = null;

                ILGenerator.EmitLoadLocal(localBuilder);
                ILGenerator.EmitPushInteger(i);
                decorator = arg.AcceptVisitor(data, this);
                ILGenerator.EmitCastIfNeeded(decorator.Type, TypeSystem.Object);
                ILGenerator.Emit(OpCodes.Stelem_Ref);
            });

            return(invocationExpression);
        }
Exemple #5
0
        public override AstNode Emit()
        {
            var falseLabel = ILGenerator.DefineLabel();
            var trueLabel  = ILGenerator.DefineLabel();
            AstNodeDecorator falseExpressionDecorator = null;

            Node.Condition.AcceptVisitor(ILGenerator, Visitor);
            ILGenerator.Emit(OpCodes.Brtrue_S, trueLabel);
            falseExpressionDecorator = Node.FalseExpression.AcceptVisitor(ILGenerator, Visitor);
            ILGenerator.EmitCastIfNeeded(falseExpressionDecorator.Type, Type);
            ILGenerator.Emit(OpCodes.Br_S, falseLabel);
            ILGenerator.MarkLabel(trueLabel);
            Node.TrueExpression.AcceptVisitor(ILGenerator, Visitor);
            ILGenerator.MarkLabel(falseLabel);

            return(base.Emit());
        }
        private AstNode EmitNewObjectInitializer()
        {
            Type             parameterType = null;
            bool             requiresPop   = false;
            MethodInfo       methodInfo    = null;
            AstNodeDecorator nodeDecorator = null;
            var callOpCode      = _isPrimitive ? OpCodes.Call : OpCodes.Callvirt;
            var firstChild      = Node.Elements.First();
            var methodReference = Node.Elements.First().Annotation <MethodReference>();

            if (methodReference == null)
            {
                Cil.Instruction instruction;
                InstructionsIndexer.TryGetCallInstruction(firstChild, out instruction);
                methodReference = instruction.Operand as MethodReference;
            }

            methodInfo    = methodReference.GetActualMethod <MethodInfo>();
            parameterType = methodInfo.GetParameters()[0].ParameterType;
            requiresPop   = !methodInfo.ReturnType.Equals(TypeSystem.Void);

            Node.Elements.ForEach((node, i) => {
                ILGenerator.EmitLoadLocal(_localBuilder);
                nodeDecorator = node.AcceptVisitor(ILGenerator, Visitor);
                ILGenerator.EmitCastIfNeeded(nodeDecorator.Type, parameterType);
                ILGenerator.Emit(callOpCode, methodInfo);

                if (requiresPop)
                {
                    ILGenerator.Emit(OpCodes.Pop);
                }
            });

            ILGenerator.EmitLoadLocal(_localBuilder, true);

            return(new AstNodeDecorator(Node, Type));
        }
        public void EmitBinaryExpression()
        {
            AstNodeDecorator node = null;
            var checkedUnchecked  = Node.Annotations.First();
            var isChecked         = checkedUnchecked == AddCheckedBlocks.CheckedAnnotation;
            var leftDecision      = _promotionDecisions.LeftType;
            var rightDecision     = _promotionDecisions.RightType;

            node = Node.Left.AcceptVisitor(ILGenerator, Visitor);

            if (!node.Type.Equals(leftDecision.To) && leftDecision.IsPromoted)
            {
                ILGenerator.EmitConversion(leftDecision.To, leftDecision.From);
            }

            if (Node.Operator != BinaryOperatorType.ConditionalAnd &&
                Node.Operator != BinaryOperatorType.ConditionalOr &&
                Node.Operator != BinaryOperatorType.NullCoalescing)
            {
                node = Node.Right.AcceptVisitor(ILGenerator, Visitor);

                if (!(Node.Right is NullReferenceExpression) && !node.Type.Equals(rightDecision.To) && rightDecision.IsPromoted)
                {
                    ILGenerator.EmitConversion(rightDecision.To, rightDecision.From);
                }
            }

            switch (Node.Operator)
            {
            case BinaryOperatorType.BitwiseAnd:

                ILGenerator.Emit(OpCodes.And);
                break;

            case BinaryOperatorType.BitwiseOr:

                ILGenerator.Emit(OpCodes.Or);
                break;

            case BinaryOperatorType.ConditionalAnd: {
                var falseLabel = ILGenerator.DefineLabel();
                var trueLabel  = ILGenerator.DefineLabel();

                ILGenerator.Emit(OpCodes.Brfalse_S, falseLabel);
                Node.Right.AcceptVisitor(Visitor, ILGenerator);
                ILGenerator.Emit(OpCodes.Br_S, trueLabel);
                ILGenerator.MarkLabel(falseLabel);
                ILGenerator.Emit(OpCodes.Ldc_I4_0);
                ILGenerator.MarkLabel(trueLabel);
                break;
            }

            case BinaryOperatorType.ConditionalOr: {
                var trueLabel  = ILGenerator.DefineLabel();
                var falseLabel = ILGenerator.DefineLabel();

                ILGenerator.Emit(OpCodes.Brtrue_S, trueLabel);
                Node.Right.AcceptVisitor(Visitor, ILGenerator);
                ILGenerator.Emit(OpCodes.Br_S, falseLabel);
                ILGenerator.MarkLabel(trueLabel);
                ILGenerator.Emit(OpCodes.Ldc_I4_1);
                ILGenerator.MarkLabel(falseLabel);
                break;
            }

            case BinaryOperatorType.ExclusiveOr:

                ILGenerator.Emit(OpCodes.Xor);
                break;

            case BinaryOperatorType.Equality:

                ILGenerator.Emit(OpCodes.Ceq);
                break;

            case BinaryOperatorType.InEquality:

                ILGenerator.Emit(OpCodes.Ceq);
                ILGenerator.Emit(OpCodes.Ldc_I4_0);
                ILGenerator.Emit(OpCodes.Ceq);
                break;

            case BinaryOperatorType.LessThan:

                ILGenerator.EmitLessThen(_leftType);
                break;

            case BinaryOperatorType.LessThanOrEqual:

                ILGenerator.EmitLessThanOrEqual(_leftType, _rightType);
                break;

            case BinaryOperatorType.GreaterThan:
                ILGenerator.EmitGreaterThan(_leftType);
                break;

            case BinaryOperatorType.GreaterThanOrEqual:

                ILGenerator.EmitGreaterThanOrEqual(_leftType, _rightType);
                break;

            case BinaryOperatorType.Add:

                ILGenerator.EmitAddition(_leftType, _rightType, isChecked);

                if (IsPreCondition(Node.Right))
                {
                    ILGenerator.Emit(OpCodes.Dup);
                    _storeArgumentShouldBeEmitted = true;
                }

                break;

            case BinaryOperatorType.Subtract: {
                if (isChecked && IsNegation(Node.Left))
                {
                    if (rightDecision.IsPromoted)
                    {
                        ILGenerator.EmitConversion(rightDecision.To, rightDecision.From);
                        ILGenerator.Emit(OpCodes.Sub_Ovf);
                    }
                }
                else
                {
                    ILGenerator.EmitSubtraction(_leftType, _rightType, isChecked);

                    if (IsPreCondition(Node.Right))
                    {
                        ILGenerator.Emit(OpCodes.Dup);
                        _storeArgumentShouldBeEmitted = true;
                    }
                }

                break;
            }

            case BinaryOperatorType.Multiply:

                ILGenerator.EmitMultiplication(_leftType, _rightType, isChecked);
                break;

            case BinaryOperatorType.Divide:

                ILGenerator.EmitDivision(_leftType);
                break;

            case BinaryOperatorType.Modulus:

                ILGenerator.EmitModulu(_leftType);
                break;

            case BinaryOperatorType.ShiftLeft:
            case BinaryOperatorType.ShiftRight: {
                int result = _leftType.Equals(TypeSystem.Int) ? 0x1f : 0x3f;
                ILGenerator.Emit(OpCodes.Ldc_I4_S, result);
                ILGenerator.Emit(OpCodes.And);

                if (Node.Operator == BinaryOperatorType.ShiftRight)
                {
                    ILGenerator.EmitRightShift(_leftType);
                }
                else
                {
                    ILGenerator.Emit(OpCodes.Shl);
                }
                break;
            }

            case BinaryOperatorType.NullCoalescing: {
                var trueLabel = ILGenerator.DefineLabel();

                ILGenerator.Emit(OpCodes.Dup);
                ILGenerator.Emit(OpCodes.Brtrue_S, trueLabel);
                ILGenerator.Emit(OpCodes.Pop);
                Node.Right.AcceptVisitor(Visitor, ILGenerator);
                ILGenerator.MarkLabel(trueLabel);
                break;
            }
            }

            if (_storeArgumentShouldBeEmitted)
            {
                var memberReference = Node.Left as MemberReferenceExpression;

                EmitStoreByArgumentIfNeeded(memberReference);
            }
        }