Пример #1
0
        private Result RewriteIndexAssignment(BinaryExpression node, Stack stack)
        {
            IndexExpression index = (IndexExpression)node.Left;

            ChildRewriter cr = new ChildRewriter(this, stack, 2 + index.Arguments.Count);

            cr.Add(index.Object);
            cr.Add(index.Arguments);
            cr.Add(node.Right);

            if (cr.Action == RewriteAction.SpillStack)
            {
#if LINQ
                RequireNotRefInstance(index.Object);
#else
                MarkRefInstance(cr, index.Object);
#endif
            }

            if (cr.Rewrite)
            {
                node = CreateAssignBinaryExpression(
                    CreateIndexExpression(
                        cr[0],                              // Object
                        index.Indexer,
                        cr[1, -2]                           // arguments
                        ),
                    cr[-1]                                  // value
                    );
            }

            return(cr.Finish(node));
        }
Пример #2
0
        //RewriteIndexExpression
        private Result RewriteIndexExpression(Expression expr, Stack stack)
        {
            var node = (IndexExpression)expr;

            var cr = new ChildRewriter(this, stack, node.Arguments.Count + 1);

            // For instance methods, the instance executes on the
            // stack as is, but stays on the stack, making it non-empty.
            cr.Add(node.Object);
            cr.Add(node.Arguments);

            if (cr.Action == RewriteAction.SpillStack)
            {
                RequireNotRefInstance(node.Object);
            }

            if (cr.Rewrite)
            {
                expr = new IndexExpression(
                    cr[0],
                    node.Indexer,
                    cr[1, -1]
                    );
            }

            return(cr.Finish(expr));
        }
Пример #3
0
        private Result RewriteMemberAssignment(BinaryExpression node, Stack stack)
        {
            var lvalue = (MemberExpression)node.Left;

            var cr = new ChildRewriter(this, stack, 2);

            // If there's an instance, it executes on the stack in current state
            // and rest is executed on non-empty stack.
            // Otherwise the stack is left unchanged.
            cr.Add(lvalue.Expression);

            cr.Add(node.Right);

            if (cr.Action == RewriteAction.SpillStack)
            {
                cr.MarkRefInstance(lvalue.Expression);
            }

            if (cr.Rewrite)
            {
                return(cr.Finish(
                           new AssignBinaryExpression(
                               MemberExpression.Make(cr[0], lvalue.Member),
                               cr[1]
                               )
                           ));
            }

            return(new Result(RewriteAction.None, node));
        }
Пример #4
0
        private Result RewriteIndexAssignment(BinaryExpression node, Stack stack)
        {
            var index = (IndexExpression)node.Left;

            var cr = new ChildRewriter(this, stack, 2 + index.ArgumentCount);

            cr.Add(index.Object);
            cr.AddArguments(index);
            cr.Add(node.Right);

            if (cr.Action == RewriteAction.SpillStack)
            {
                cr.MarkRefInstance(index.Object);
            }

            if (cr.Rewrite)
            {
                node = new AssignBinaryExpression(
                    new IndexExpression(
                        cr[0],                              // Object
                        index.Indexer,
                        cr[1, -2] !                         // arguments
                        ),
                    cr[-1] !                                // value
                    );
            }

            return(cr.Finish(node));
        }
Пример #5
0
        private Result RewriteBinaryExpression(Expression expr, Stack stack)
        {
            var node = (BinaryExpression)expr;

            var cr = new ChildRewriter(this, stack, 3);

            // Left expression executes on the stack as left by parent
            cr.Add(node.Left);
            // Right expression always has non-empty stack (left is on it)
            cr.Add(node.Right);
            // conversion is a lambda, stack state will be ignored
            cr.Add(node.Conversion);

            if (cr.Action == RewriteAction.SpillStack)
            {
                RequireNoRefArgs(node.Method);
            }

            return(cr.Finish(cr.Rewrite ?
                             BinaryExpression.Create(
                                 node.NodeType,
                                 cr[0] !,
                                 cr[1] !,
                                 node.Type,
                                 node.Method,
                                 (LambdaExpression?)cr[2]) :
                             expr));
        }
Пример #6
0
        // InvocationExpression
        private Result RewriteInvocationExpression(Expression expr, Stack stack)
        {
            InvocationExpression node = (InvocationExpression)expr;

            ChildRewriter cr;

#if LINQ // NB: Our compiler doesn't inline; this could still happen at a later stage in the LINQ compiler after lowering async lambdas to sync ones.
            // See if the lambda will be inlined
            LambdaExpression lambda = node.LambdaOperand();
            if (lambda != null)
            {
                // Arguments execute on current stack
                cr = new ChildRewriter(this, stack, node.Arguments.Count);
                cr.Add(node.Arguments);

                if (cr.Action == RewriteAction.SpillStack)
                {
                    RequireNoRefArgs(ExpressionStubs.GetInvokeMethod(node.Expression));
                }

                // Lambda body also executes on current stack
                var spiller = new StackSpiller(stack);
                lambda = lambda.Accept(spiller);

                if (cr.Rewrite || spiller._lambdaRewrite != RewriteAction.None)
                {
                    node = node.Rewrite(lambda, cr[0, -1]);
                }

                Result result = cr.Finish(node);
                return(new Result(result.Action | spiller._lambdaRewrite, result.Node));
            }
#endif

            cr = new ChildRewriter(this, stack, node.Arguments.Count + 1);

            // first argument starts on stack as provided
            cr.Add(node.Expression);

            // rest of arguments have non-empty stack (delegate instance on the stack)
            cr.Add(node.Arguments);

            if (cr.Action == RewriteAction.SpillStack)
            {
#if LINQ
                RequireNoRefArgs(ExpressionStubs.GetInvokeMethod(node.Expression));
#else
                MarkRefArgs(cr, ExpressionStubs.GetInvokeMethod(node.Expression), 1);
#endif
            }

            return(cr.Finish(cr.Rewrite ? node.Rewrite(cr[0], cr[1, -1]) : expr));
        }
Пример #7
0
        // MethodCallExpression
        // TODO: ref parameters!!!
        private Result RewriteMethodCallExpression(Expression expr, Stack stack)
        {
            MethodCallExpression node = (MethodCallExpression)expr;

            ChildRewriter cr = new ChildRewriter(this, stack, node.Arguments.Count + 1);

            // For instance methods, the instance executes on the
            // stack as is, but stays on the stack, making it non-empty.
            cr.Add(node.Object);

            cr.Add(node.Arguments);

            return(cr.Finish(cr.Rewrite ? node.Rewrite(cr[0], cr[1, -1]) : expr));
        }
Пример #8
0
        // InvocationExpression
        private Result RewriteInvocationExpression(Expression expr, Stack stack)
        {
            InvocationExpression node = (InvocationExpression)expr;

            // first argument starts on stack as provided
            ChildRewriter cr = new ChildRewriter(this, stack, node.Arguments.Count + 1);

            cr.Add(node.Expression);

            // rest of arguments have non-empty stack (delegate instance on the stack)
            cr.Add(node.Arguments);

            return(cr.Finish(cr.Rewrite ? new InvocationExpression(cr[0], cr[1, -1], node.Type) : expr));
        }
Пример #9
0
        // InvocationExpression
        private Result RewriteInvocationExpression(Expression expr, Stack stack)
        {
            var node = (InvocationExpression)expr;

            ChildRewriter cr;

            // See if the lambda will be inlined
            var lambda = node.LambdaOperand;

            if (lambda != null)
            {
                // Arguments execute on current stack
                cr = new ChildRewriter(this, stack, node.Arguments.Count);
                cr.Add(node.Arguments);

                if (cr.Action == RewriteAction.SpillStack)
                {
                    RequireNoRefArgs(Expression.GetInvokeMethod(node.Expression));
                }

                // Lambda body also executes on current stack
                var spiller = new StackSpiller(stack);
                lambda = lambda.Accept(spiller);

                if (cr.Rewrite || spiller._lambdaRewrite != RewriteAction.None)
                {
                    node = new InvocationExpression(lambda, cr[0, -1], node.Type);
                }

                var result = cr.Finish(node);
                return(new Result(result.Action | spiller._lambdaRewrite, result.Node));
            }

            cr = new ChildRewriter(this, stack, node.Arguments.Count + 1);

            // first argument starts on stack as provided
            cr.Add(node.Expression);

            // rest of arguments have non-empty stack (delegate instance on the stack)
            cr.Add(node.Arguments);

            if (cr.Action == RewriteAction.SpillStack)
            {
                RequireNoRefArgs(Expression.GetInvokeMethod(node.Expression));
            }

            return(cr.Finish(cr.Rewrite ? new InvocationExpression(cr[0], cr[1, -1], node.Type) : expr));
        }
Пример #10
0
        // MethodCallExpression
        private Result RewriteMethodCallExpression(Expression expr, Stack stack)
        {
            MethodCallExpression node = (MethodCallExpression)expr;

            ChildRewriter cr = new ChildRewriter(this, stack, node.Arguments.Count + 1);

            // For instance methods, the instance executes on the
            // stack as is, but stays on the stack, making it non-empty.
            cr.Add(node.Object);

            cr.AddArguments(node);

            if (cr.Action == RewriteAction.SpillStack)
            {
#if LINQ
                RequireNotRefInstance(node.Object);
                RequireNoRefArgs(node.Method);
#else
                MarkRefInstance(cr, node.Object);
                MarkRefArgs(cr, node.Method, 1);
#endif
            }

            return(cr.Finish(cr.Rewrite ? node.Rewrite(cr[0], cr[1, -1]) : expr));
        }
Пример #11
0
        private Result RewriteNewArrayExpression(Expression expr, Stack stack)
        {
            var node = (NewArrayExpression)expr;

            if (node.NodeType == ExpressionType.NewArrayInit)
            {
                // In a case of array construction with element initialization
                // the element expressions are never emitted on an empty stack because
                // the array reference and the index are on the stack.
                stack = Stack.NonEmpty;
            }
            else
            {
                // In a case of NewArrayBounds we make no modifications to the stack
                // before emitting bounds expressions.
            }

            var cr = new ChildRewriter(this, stack, node.Expressions.Count);

            cr.Add(node.Expressions);

            if (cr.Rewrite)
            {
                expr = NewArrayExpression.Make(node.NodeType, node.Type, new TrueReadOnlyCollection <Expression>(cr[0, -1]));
            }

            return(cr.Finish(expr));
        }
Пример #12
0
        private Result RewriteMethodCallExpression(Expression expr, Stack stack)
        {
            MethodCallExpression node = (MethodCallExpression)expr;

            var cr = new ChildRewriter(this, stack, node.ArgumentCount + 1);

            // For instance methods, the instance executes on the
            // stack as is, but stays on the stack, making it non-empty.
            cr.Add(node.Object);

            cr.AddArguments(node);

            if (cr.Action == RewriteAction.SpillStack)
            {
                cr.MarkRefInstance(node.Object);
                cr.MarkRefArgs(node.Method, startIndex: 1);
            }

            if (cr.Rewrite)
            {
                if (node.Object != null)
                {
                    expr = new InstanceMethodCallExpressionN(node.Method, cr[0], cr[1, -1]);
                }
                else
                {
                    expr = new MethodCallExpressionN(node.Method, cr[1, -1]);
                }
            }

            return(cr.Finish(expr));
        }
Пример #13
0
        private Result RewriteMemberExpression(Expression expr, Stack stack)
        {
            MemberExpression node = (MemberExpression)expr;

            ChildRewriter cr = new ChildRewriter(this, stack, 1);

            cr.Add(node.Expression);

            if (cr.Rewrite)
            {
                if (cr.Action == RewriteAction.SpillStack && node.Member is PropertyInfo)
                {
                    // Only need to validate propreties because reading a field
                    // is always side-effect free.
#if LINQ
                    RequireNotRefInstance(node.Expression);
#else
                    MarkRefInstance(cr, node.Expression);
#endif
                }

                expr = MemberExpressionStubs.Make(cr[0], node.Member);
            }

            return(cr.Finish(expr));
        }
Пример #14
0
        // NewArrayExpression
        private Result RewriteNewArrayExpression(Expression expr, Stack stack)
        {
            var node = (NewArrayExpression)expr;

            if (node.NodeType == ExpressionType.NewArrayInit)
            {
                // In a case of array construction with element initialization
                // the element expressions are never emitted on an empty stack because
                // the array reference and the index are on the stack.
                stack = Stack.NonEmpty;
            }

            var cr = new ChildRewriter(this, stack, node.Expressions.Count);

            cr.Add(node.Expressions);

            if (cr.Rewrite)
            {
                var element = node.Type.GetElementType();
                if (node.NodeType == ExpressionType.NewArrayInit)
                {
                    expr = Expression.NewArrayInit(element, cr[0, -1]);
                }
                else
                {
                    expr = Expression.NewArrayBounds(element, cr[0, -1]);
                }
            }

            return(cr.Finish(expr));
        }
Пример #15
0
        // NewExpression
        private Result RewriteNewExpression(Expression expr, Stack stack)
        {
            NewExpression node = (NewExpression)expr;

            // The first expression starts on a stack as provided by parent,
            // rest are definitely non-emtpy (which ChildRewriter guarantees)
            ChildRewriter cr = new ChildRewriter(this, stack, node.Arguments.Count);

            cr.Add(node.Arguments);

            return(cr.Finish(cr.Rewrite ? new NewExpression(node.Constructor, cr[0, -1], node.Members) : expr));
        }
        private Result RewriteAwaitExpression(Expression expr, Stack stack)
        {
            var node = (AwaitCSharpExpression)expr;

            ChildRewriter cr = new ChildRewriter(this, stack, 1);

            cr.Add(node.Operand);

            // NB: We always spill the stack for await, so unconditionally rewrite.

            var res = cr.Finish(node.Rewrite(cr[0]));

            return new Result(RewriteAction.SpillStack, res.Node);
        }
Пример #17
0
        // BinaryExpression
        private Result RewriteBinaryExpression(Expression expr, Stack stack)
        {
            BinaryExpression node = (BinaryExpression)expr;

            ChildRewriter cr = new ChildRewriter(this, stack, 3);

            // Left expression executes on the stack as left by parent
            cr.Add(node.Left);
            // Right expression always has non-empty stack (left is on it)
            cr.Add(node.Right);
            // conversion is a lambda, stack state will be ignored
            cr.Add(node.Conversion);

            return(cr.Finish(cr.Rewrite ?
                             BinaryExpression.Create(
                                 node.NodeType,
                                 cr[0],
                                 cr[1],
                                 node.Type,
                                 node.Method,
                                 (LambdaExpression)cr[2]) :
                             expr));
        }
        private Result RewriteAwaitExpression(Expression expr, Stack stack)
        {
            var node = (AwaitCSharpExpression)expr;

            ChildRewriter cr = new ChildRewriter(this, stack, 1);

            cr.Add(node.Operand);

            // NB: We always spill the stack for await, so unconditionally rewrite.

            var res = cr.Finish(node.Rewrite(cr[0], node.Info));

            return(new Result(RewriteAction.SpillStack, res.Node));
        }
Пример #19
0
        private Result RewriteArrayIndexAssignment(BinaryExpression node, Stack stack)
        {
            Debug.Assert(node.NodeType == ExpressionType.ArrayIndex);
            BinaryExpression arrayIndex = (BinaryExpression)node.Left;

            ChildRewriter cr = new ChildRewriter(this, stack, 3);

            cr.Add(arrayIndex.Left);
            cr.Add(arrayIndex.Right);
            cr.Add(node.Right);

            if (cr.Rewrite)
            {
                node = new AssignBinaryExpression(
                    Expression.ArrayIndex(
                        cr[0],   // array
                        cr[1]    // index
                        ),
                    cr[2]        // value
                    );
            }

            return(cr.Finish(node));
        }
Пример #20
0
        private Result RewriteIndexAssignment(BinaryExpression node, Stack stack)
        {
            IndexExpression index = (IndexExpression)node.Left;

            ChildRewriter cr = new ChildRewriter(this, stack, 2 + index.Arguments.Count);

            cr.Add(index.Object);
            cr.Add(index.Arguments);
            cr.Add(node.Right);

            if (cr.Rewrite)
            {
                node = new AssignBinaryExpression(
                    new IndexExpression(
                        cr[0],                              // Object
                        index.Indexer,
                        cr[1, -2]                           // arguments
                        ),
                    cr[-1]                                  // value
                    );
            }

            return(cr.Finish(node));
        }
Пример #21
0
        private Result RewriteDynamicExpression(Expression expr, Stack stack)
        {
            var node = (DynamicExpression)expr;

            // CallSite is on the stack
            IArgumentProvider argNode = (IArgumentProvider)node;
            int           argCount    = argNode.ArgumentCount;
            ChildRewriter cr          = new ChildRewriter(this, Stack.NonEmpty, argCount);

            for (int i = 0; i < argCount; i++)
            {
                cr.Add(argNode.GetArgument(i));
            }
            return(cr.Finish(cr.Rewrite ? node.Rewrite(cr[0, -1]) : expr));
        }
Пример #22
0
            internal ListBindingRewriter(MemberListBinding binding, StackSpiller spiller, Stack stack) :
                base(binding, spiller)
            {
                _inits = binding.Initializers;

                _childRewriters = new ChildRewriter[_inits.Count];
                for (int i = 0; i < _inits.Count; i++)
                {
                    ElementInit init = _inits[i];

                    ChildRewriter cr = new ChildRewriter(spiller, stack, init.Arguments.Count);
                    cr.Add(init.Arguments);

                    _action           |= cr.Action;
                    _childRewriters[i] = cr;
                }
            }
            internal ListBindingRewriter(MemberListBinding memberBinding, StackSpiller stackSpiller, Stack stack) :
                base(memberBinding, stackSpiller)
            {
                _inits = memberBinding.Initializers;

                _childRewriters = new ChildRewriter[_inits.Count];
                for (var i = 0; i < _inits.Count; i++)
                {
                    var init = _inits[i];

                    var cr = new ChildRewriter(stackSpiller, stack, init.Arguments.Count);
                    cr.Add(init.Arguments);

                    RewriteAction     |= cr.Action;
                    _childRewriters[i] = cr;
                }
            }
Пример #24
0
            internal ListBindingRewriter(MemberListBinding binding, StackSpiller spiller, Stack stack) :
                base(binding, spiller)
            {
                _initializers = binding.Initializers;

                var count = _initializers.Count;

                _childRewriters = new ChildRewriter[count];

                for (var i = 0; i < count; i++)
                {
                    var init = _initializers[i];

                    var cr = new ChildRewriter(spiller, stack, init.Arguments.Count);
                    cr.Add(init.Arguments);

                    Action            |= cr.Action;
                    _childRewriters[i] = cr;
                }
            }
Пример #25
0
        private Result RewriteTypeBinaryExpression(Expression expr, Stack stack)
        {
            TypeBinaryExpression node = (TypeBinaryExpression)expr;

            ChildRewriter cr = new ChildRewriter(this, stack, 1);

            cr.Add(node.Expression);

            if (cr.Rewrite)
            {
                if (node.NodeType == ExpressionType.TypeIs)
                {
                    expr = Expression.TypeIs(cr[0], node.TypeOperand);
                }
                else
                {
                    expr = Expression.TypeEqual(cr[0], node.TypeOperand);
                }
            }
            return(cr.Finish(expr));
        }
Пример #26
0
        private Result RewriteUnaryExpression(Expression expr, Stack stack)
        {
            UnaryExpression node = (UnaryExpression)expr;

            Debug.Assert(node.NodeType != ExpressionType.Quote, "unexpected Quote");
            Debug.Assert(node.NodeType != ExpressionType.Throw, "unexpected Throw");

            ChildRewriter cr = new ChildRewriter(this, stack, 1);

            cr.Add(node.Operand);

            if (cr.Action == RewriteAction.SpillStack)
            {
#if LINQ
                RequireNoRefArgs(node.Method);
#else
                MarkRefArgs(cr, node.Method, 0);
#endif
            }

            return(cr.Finish(cr.Rewrite ? CreateUnaryExpression(node.NodeType, cr[0], node.Type, node.Method) : expr));
        }
Пример #27
0
        private Result RewriteListInitExpression(Expression expr, Stack stack)
        {
            var node = (ListInitExpression)expr;

            // Constructor runs on initial stack.
            Result        newResult    = RewriteExpression(node.NewExpression, stack);
            Expression    rewrittenNew = newResult.Node;
            RewriteAction action       = newResult.Action;

            ReadOnlyCollection <ElementInit> inits = node.Initializers;
            int count = inits.Count;

            ChildRewriter[] cloneCrs = new ChildRewriter[count];

            for (int i = 0; i < count; i++)
            {
                ElementInit init = inits[i];

                // Initializers all run on non-empty stack (the list instance is on it).
                var cr = new ChildRewriter(this, Stack.NonEmpty, init.Arguments.Count);
                cr.Add(init.Arguments);

                action     |= cr.Action;
                cloneCrs[i] = cr;
            }

            switch (action)
            {
            case RewriteAction.None:
                break;

            case RewriteAction.Copy:
                ElementInit[] newInits = new ElementInit[count];
                for (int i = 0; i < count; i++)
                {
                    ChildRewriter cr = cloneCrs[i];
                    if (cr.Action == RewriteAction.None)
                    {
                        newInits[i] = inits[i];
                    }
                    else
                    {
                        newInits[i] = new ElementInit(inits[i].AddMethod, new TrueReadOnlyCollection <Expression>(cr[0, -1]));
                    }
                }
                expr = new ListInitExpression((NewExpression)rewrittenNew, new TrueReadOnlyCollection <ElementInit>(newInits));
                break;

            case RewriteAction.SpillStack:
                bool isRefNew = IsRefInstance(node.NewExpression);

                var comma = new ArrayBuilder <Expression>(count + 2 + (isRefNew ? 1 : 0));

                ParameterExpression tempNew = MakeTemp(rewrittenNew.Type);
                comma.UncheckedAdd(new AssignBinaryExpression(tempNew, rewrittenNew));

                ParameterExpression refTempNew = tempNew;
                if (isRefNew)
                {
                    refTempNew = MakeTemp(tempNew.Type.MakeByRefType());
                    comma.UncheckedAdd(new ByRefAssignBinaryExpression(refTempNew, tempNew));
                }

                for (int i = 0; i < count; i++)
                {
                    ChildRewriter cr  = cloneCrs[i];
                    Result        add = cr.Finish(new InstanceMethodCallExpressionN(inits[i].AddMethod, refTempNew, cr[0, -1]));
                    comma.UncheckedAdd(add.Node);
                }

                comma.UncheckedAdd(tempNew);

                expr = MakeBlock(comma);
                break;

            default:
                throw ContractUtils.Unreachable;
            }

            return(new Result(action, expr));
        }
Пример #28
0
        // RewriteListInitExpression
        private Result RewriteListInitExpression(Expression expr, Stack stack)
        {
            var node = (ListInitExpression)expr;

            //ctor runs on initial stack
            var newResult    = RewriteExpression(node.NewExpression, stack);
            var rewrittenNew = newResult.Node;
            var action       = newResult.Action;

            var inits = node.Initializers;

            var cloneCrs = new ChildRewriter[inits.Count];

            for (var i = 0; i < inits.Count; i++)
            {
                var init = inits[i];

                //initializers all run on nonempty stack
                var cr = new ChildRewriter(this, Stack.NonEmpty, init.Arguments.Count);
                cr.Add(init.Arguments);

                action     |= cr.Action;
                cloneCrs[i] = cr;
            }

            switch (action)
            {
            case RewriteAction.None:
                break;

            case RewriteAction.Copy:
                var newInits = new ElementInit[inits.Count];
                for (var i = 0; i < inits.Count; i++)
                {
                    var cr = cloneCrs[i];
                    if (cr.Action == RewriteAction.None)
                    {
                        newInits[i] = inits[i];
                    }
                    else
                    {
                        newInits[i] = Expression.ElementInit(inits[i].AddMethod, cr[0, -1]);
                    }
                }
                expr = Expression.ListInit((NewExpression)rewrittenNew, new TrueReadOnlyCollection <ElementInit>(newInits));
                break;

            case RewriteAction.SpillStack:
                RequireNotRefInstance(node.NewExpression);

                var tempNew = MakeTemp(rewrittenNew.Type);
                var comma   = new Expression[inits.Count + 2];
                comma[0] = Expression.Assign(tempNew, rewrittenNew);

                for (var i = 0; i < inits.Count; i++)
                {
                    var cr  = cloneCrs[i];
                    var add = cr.Finish(Expression.Call(tempNew, inits[i].AddMethod, cr[0, -1]));
                    comma[i + 1] = add.Node;
                }
                comma[inits.Count + 1] = tempNew;
                expr = MakeBlock(comma);
                break;

            default:
                throw ContractUtils.Unreachable;
            }

            return(new Result(action, expr));
        }
Пример #29
0
            internal ListBindingRewriter(MemberListBinding binding, StackSpiller spiller, Stack stack) :
                base(binding, spiller)
            {
                _inits = binding.Initializers;

                _childRewriters = new ChildRewriter[_inits.Count];
                for (int i = 0; i < _inits.Count; i++)
                {
                    ElementInit init = _inits[i];

                    ChildRewriter cr = new ChildRewriter(spiller, stack, init.Arguments.Count);
                    cr.Add(init.Arguments);

                    _action |= cr.Action;
                    _childRewriters[i] = cr;
                }
            }
Пример #30
0
        // RewriteListInitExpression
        private Result RewriteListInitExpression(Expression expr, Stack stack)
        {
            ListInitExpression node = (ListInitExpression)expr;

            //ctor runs on initial stack
            Result        newResult    = RewriteExpression(node.NewExpression, stack);
            Expression    rewrittenNew = newResult.Node;
            RewriteAction action       = newResult.Action;

            ReadOnlyCollection <ElementInit> inits = node.Initializers;

            ChildRewriter[] cloneCrs = new ChildRewriter[inits.Count];

            for (int i = 0; i < inits.Count; i++)
            {
                ElementInit init = inits[i];

                //initializers all run on nonempty stack
                ChildRewriter cr = new ChildRewriter(this, Stack.NonEmpty, init.Arguments.Count);
                cr.Add(init.Arguments);

                action     |= cr.Action;
                cloneCrs[i] = cr;
            }

            switch (action)
            {
            case RewriteAction.None:
                break;

            case RewriteAction.Copy:
                ElementInit[] newInits = new ElementInit[inits.Count];
                for (int i = 0; i < inits.Count; i++)
                {
                    ChildRewriter cr = cloneCrs[i];
                    if (cr.Action == RewriteAction.None)
                    {
                        newInits[i] = inits[i];
                    }
                    else
                    {
                        newInits[i] = Expression.ElementInit(inits[i].AddMethod, cr[0, -1]);
                    }
                }
                expr = Expression.ListInit((NewExpression)rewrittenNew, new ReadOnlyCollection <ElementInit>(newInits));
                break;

            case RewriteAction.SpillStack:
                ParameterExpression tempNew = MakeTemp(rewrittenNew.Type);
                Expression[]        comma   = new Expression[inits.Count + 2];
                comma[0] = Expression.Assign(tempNew, rewrittenNew);

                for (int i = 0; i < inits.Count; i++)
                {
                    ChildRewriter cr  = cloneCrs[i];
                    Result        add = cr.Finish(Expression.Call(tempNew, inits[i].AddMethod, cr[0, -1]));
                    comma[i + 1] = add.Node;
                }
                comma[inits.Count + 1] = tempNew;
                expr = Expression.Block(comma);
                break;

            default:
                throw Assert.Unreachable;
            }

            return(new Result(action, expr));
        }