public override BoundNode VisitBinaryOperator(BoundBinaryOperator node)
        {
            BoundExpression left  = (BoundExpression)this.Visit(node.Left);
            BoundExpression right = (BoundExpression)this.Visit(node.Right);
            TypeSymbol      type  = this.VisitType(node.Type);

            if (!RequiresSpill(left, right))
            {
                return(node.Update(node.OperatorKind, left, right, node.ConstantValueOpt, node.MethodOpt, node.ResultKind, type));
            }

            var subExprs = ReadOnlyArray <BoundExpression> .CreateFrom(left, right);

            var spillBuilder = new SpillBuilder();
            var newArgs      = SpillExpressionList(spillBuilder, subExprs);

            Debug.Assert(newArgs.Count == 2);

            var newBinaryOperator = node.Update(
                node.OperatorKind,
                newArgs[0],
                newArgs[1],
                node.ConstantValueOpt,
                node.MethodOpt,
                node.ResultKind,
                type);

            return(spillBuilder.BuildSequenceAndFree(F, newBinaryOperator));
        }
 private BoundNode SpillAssignmentOperator(BoundAssignmentOperator node, BoundExpression left, BoundSpillSequence right)
 {
     var spillBuilder = new SpillBuilder();
     var spilledLeftNode = SpillLValue(left, spillBuilder);
     var innerSpill = node.Update(spilledLeftNode, right.Value, node.RefKind, node.Type);
     spillBuilder.AddSpill(right);
     return spillBuilder.BuildSequenceAndFree(F, innerSpill);
 }
        private BoundNode SpillAssignmentOperator(BoundAssignmentOperator node, BoundExpression left, BoundSpillSequence right)
        {
            var spillBuilder    = new SpillBuilder();
            var spilledLeftNode = SpillLValue(left, spillBuilder);
            var innerSpill      = node.Update(spilledLeftNode, right.Value, node.RefKind, node.Type);

            spillBuilder.AddSpill(right);
            return(spillBuilder.BuildSequenceAndFree(F, innerSpill));
        }
        public override BoundNode VisitArrayAccess(BoundArrayAccess node)
        {
            BoundExpression expression = (BoundExpression)this.Visit(node.Expression);
            ReadOnlyArray <BoundExpression> indices = (ReadOnlyArray <BoundExpression>) this.VisitList(node.Indices);
            TypeSymbol type = this.VisitType(node.Type);

            if (!RequiresSpill(indices) && expression.Kind != BoundKind.SpillSequence)
            {
                return(node.Update(expression, indices, type));
            }

            var             spillBuilder        = new SpillBuilder();
            var             spillResult         = SpillExpressionsWithReceiver(expression, indices, spillBuilder, refKindsOpt: ReadOnlyArray <RefKind> .Empty);
            BoundExpression newBoundArrayAccess = node.Update(spillResult.Item1, spillResult.Item2, type);

            return(spillBuilder.BuildSequenceAndFree(F, newBoundArrayAccess));
        }
        public override BoundNode VisitArrayCreation(BoundArrayCreation node)
        {
            ReadOnlyArray <BoundExpression> bounds             = this.VisitList(node.Bounds);
            BoundArrayInitialization        visitedInitializer = (BoundArrayInitialization)this.Visit(node.InitializerOpt);
            TypeSymbol type = this.VisitType(node.Type);

            if (!RequiresSpill(bounds) && (visitedInitializer == null || !RequiresSpill(visitedInitializer.Initializers)))
            {
                return(node.Update(bounds, visitedInitializer, type));
            }

            var spillBuilder = new SpillBuilder();
            ReadOnlyArray <BoundExpression> newBounds         = SpillExpressionList(spillBuilder, bounds);
            BoundArrayInitialization        newInitializerOpt = (visitedInitializer == null) ? visitedInitializer :
                                                                visitedInitializer.Update(SpillExpressionList(spillBuilder, visitedInitializer.Initializers));
            BoundArrayCreation newArrayCreation = node.Update(newBounds, newInitializerOpt, type);

            return(spillBuilder.BuildSequenceAndFree(F, newArrayCreation));
        }
        public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpression node)
        {
            ReadOnlyArray <BoundExpression> arguments = (ReadOnlyArray <BoundExpression>) this.VisitList(node.Arguments);
            BoundExpression initializerExpressionOpt  = (BoundExpression)this.Visit(node.InitializerExpressionOpt);
            TypeSymbol      type = this.VisitType(node.Type);

            if (!RequiresSpill(arguments) && (initializerExpressionOpt == null || initializerExpressionOpt.Kind != BoundKind.SpillSequence))
            {
                return(node.Update(node.Constructor, arguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.Expanded, node.ArgsToParamsOpt, node.ConstantValueOpt, initializerExpressionOpt, type));
            }

            var spillBuilder = new SpillBuilder();
            ReadOnlyArray <BoundExpression> newArguments = SpillExpressionList(spillBuilder, arguments);

            BoundExpression newInitializerExpressionOpt;

            if (initializerExpressionOpt != null && initializerExpressionOpt.Kind == BoundKind.SpillSequence)
            {
                var spill = (BoundSpillSequence)initializerExpressionOpt;
                spillBuilder.AddSpill(spill);
                newInitializerExpressionOpt = spill.Value;
            }
            else
            {
                newInitializerExpressionOpt = initializerExpressionOpt;
            }

            BoundObjectCreationExpression newObjectCreation = node.Update(
                node.Constructor,
                newArguments,
                node.ArgumentNamesOpt,
                node.ArgumentRefKindsOpt,
                node.Expanded,
                node.ArgsToParamsOpt,
                node.ConstantValueOpt,
                newInitializerExpressionOpt,
                type);

            return(spillBuilder.BuildSequenceAndFree(F, newObjectCreation));
        }
        public override BoundNode VisitConditionalOperator(BoundConditionalOperator node)
        {
            BoundExpression condition   = (BoundExpression)this.Visit(node.Condition);
            BoundExpression consequence = (BoundExpression)this.Visit(node.Consequence);
            BoundExpression alternative = (BoundExpression)this.Visit(node.Alternative);
            TypeSymbol      type        = this.VisitType(node.Type);

            if (!RequiresSpill(condition, consequence, alternative))
            {
                return(node.Update(condition, consequence, alternative, node.ConstantValueOpt, type));
            }

            var spillBuilder = new SpillBuilder();

            LocalSymbol resultLocal = F.SynthesizedLocal(type, null);

            spillBuilder.Locals.Add(resultLocal);

            BoundExpression newCondition;

            if (condition.Kind == BoundKind.SpillSequence)
            {
                var spill = (BoundSpillSequence)condition;
                spillBuilder.AddSpill(spill);
                newCondition = spill.Value;
            }
            else
            {
                newCondition = condition;
            }

            spillBuilder.Statements.Add(
                F.If(
                    condition: newCondition,
                    thenClause: CrushExpression(consequence, resultLocal),
                    elseClause: CrushExpression(alternative, resultLocal)));

            return(spillBuilder.BuildSequenceAndFree(F, F.Local(resultLocal)));
        }
        public override BoundNode VisitCall(BoundCall node)
        {
            BoundExpression receiverOpt = (BoundExpression)this.Visit(node.ReceiverOpt);
            ReadOnlyArray <BoundExpression> arguments = this.VisitList(node.Arguments);
            TypeSymbol type = this.VisitType(node.Type);

            if (!RequiresSpill(arguments) && !RequiresSpill(receiverOpt))
            {
                return(node.Update(
                           receiverOpt,
                           node.Method,
                           arguments,
                           node.ArgumentNamesOpt,
                           node.ArgumentRefKindsOpt,
                           node.IsDelegateCall,
                           node.Expanded,
                           node.InvokedAsExtensionMethod,
                           node.ArgsToParamsOpt,
                           node.ResultKind, type));
            }

            var spillBuilder = new SpillBuilder();
            var spillResult  = SpillExpressionsWithReceiver(receiverOpt, arguments, spillBuilder, node.Method.ParameterRefKinds);

            var newCall = node.Update(
                spillResult.Item1,
                node.Method,
                spillResult.Item2,
                node.ArgumentNamesOpt,
                node.ArgumentRefKindsOpt,
                node.IsDelegateCall,
                node.Expanded,
                node.InvokedAsExtensionMethod,
                node.ArgsToParamsOpt,
                node.ResultKind,
                type);

            return(spillBuilder.BuildSequenceAndFree(F, newCall));
        }
Ejemplo n.º 9
0
        public override BoundNode VisitSequence(BoundSequence node)
        {
            ReadOnlyArray <BoundExpression> sideEffects = (ReadOnlyArray <BoundExpression>) this.VisitList(node.SideEffects);
            BoundExpression value = (BoundExpression)this.Visit(node.Value);
            TypeSymbol      type  = this.VisitType(node.Type);

            if (!RequiresSpill(sideEffects) && value.Kind != BoundKind.SpillSequence)
            {
                return(node.Update(node.Locals, sideEffects, value, type));
            }

            var spillBuilder = new SpillBuilder();

            spillBuilder.Locals.AddRange(node.Locals);

            foreach (var sideEffect in sideEffects)
            {
                spillBuilder.Statements.Add(
                    (sideEffect.Kind == BoundKind.SpillSequence)
                    ? RewriteSpillSequenceAsBlock((BoundSpillSequence)sideEffect)
                    : F.ExpressionStatement(sideEffect));
            }

            BoundExpression newValue;

            if (value.Kind == BoundKind.SpillSequence)
            {
                var awaitEffect = (BoundSpillSequence)value;
                spillBuilder.AddSpill(awaitEffect);
                newValue = awaitEffect.Value;
            }
            else
            {
                newValue = value;
            }

            return(spillBuilder.BuildSequenceAndFree(F, newValue));
        }
        public override BoundNode VisitSequence(BoundSequence node)
        {
            ReadOnlyArray<BoundExpression> sideEffects = (ReadOnlyArray<BoundExpression>)this.VisitList(node.SideEffects);
            BoundExpression value = (BoundExpression)this.Visit(node.Value);
            TypeSymbol type = this.VisitType(node.Type);

            if (!RequiresSpill(sideEffects) && value.Kind != BoundKind.SpillSequence)
            {
                return node.Update(node.Locals, sideEffects, value, type);
            }

            var spillBuilder = new SpillBuilder();

            spillBuilder.Locals.AddRange(node.Locals);

            foreach (var sideEffect in sideEffects)
            {
                spillBuilder.Statements.Add(
                    (sideEffect.Kind == BoundKind.SpillSequence)
                    ? RewriteSpillSequenceAsBlock((BoundSpillSequence)sideEffect)
                    : F.ExpressionStatement(sideEffect));
            }

            BoundExpression newValue;
            if (value.Kind == BoundKind.SpillSequence)
            {
                var awaitEffect = (BoundSpillSequence)value;
                spillBuilder.AddSpill(awaitEffect);
                newValue = awaitEffect.Value;
            }
            else
            {
                newValue = value;
            }

            return spillBuilder.BuildSequenceAndFree(F, newValue);
        }
        public override BoundNode VisitConditionalOperator(BoundConditionalOperator node)
        {
            BoundExpression condition = (BoundExpression)this.Visit(node.Condition);
            BoundExpression consequence = (BoundExpression)this.Visit(node.Consequence);
            BoundExpression alternative = (BoundExpression)this.Visit(node.Alternative);
            TypeSymbol type = this.VisitType(node.Type);

            if (!RequiresSpill(condition, consequence, alternative))
            {
                return node.Update(condition, consequence, alternative, node.ConstantValueOpt, type);
            }

            var spillBuilder = new SpillBuilder();

            LocalSymbol resultLocal = F.SynthesizedLocal(type, null);
            spillBuilder.Locals.Add(resultLocal);

            BoundExpression newCondition;
            if (condition.Kind == BoundKind.SpillSequence)
            {
                var spill = (BoundSpillSequence)condition;
                spillBuilder.AddSpill(spill);
                newCondition = spill.Value;
            }
            else
            {
                newCondition = condition;
            }

            spillBuilder.Statements.Add(
                F.If(
                    condition: newCondition,
                    thenClause: CrushExpression(consequence, resultLocal),
                    elseClause: CrushExpression(alternative, resultLocal)));

            return spillBuilder.BuildSequenceAndFree(F, F.Local(resultLocal));

        }
        public override BoundNode VisitBinaryOperator(BoundBinaryOperator node)
        {
            BoundExpression left = (BoundExpression)this.Visit(node.Left);
            BoundExpression right = (BoundExpression)this.Visit(node.Right);
            TypeSymbol type = this.VisitType(node.Type);
            
            if (!RequiresSpill(left, right))
            {
                return node.Update(node.OperatorKind, left, right, node.ConstantValueOpt, node.MethodOpt, node.ResultKind, type);
            }

            var subExprs = ReadOnlyArray<BoundExpression>.CreateFrom(left, right);
            var spillBuilder = new SpillBuilder();
            var newArgs = SpillExpressionList(spillBuilder, subExprs);
            Debug.Assert(newArgs.Count == 2);

            var newBinaryOperator = node.Update(
                node.OperatorKind,
                newArgs[0],
                newArgs[1],
                node.ConstantValueOpt,
                node.MethodOpt,
                node.ResultKind,
                type);

            return spillBuilder.BuildSequenceAndFree(F, newBinaryOperator);
        }
        public override BoundNode VisitArrayAccess(BoundArrayAccess node)
        {
            BoundExpression expression = (BoundExpression)this.Visit(node.Expression);
            ReadOnlyArray<BoundExpression> indices = (ReadOnlyArray<BoundExpression>)this.VisitList(node.Indices);
            TypeSymbol type = this.VisitType(node.Type);

            if (!RequiresSpill(indices) && expression.Kind != BoundKind.SpillSequence)
            {
                return node.Update(expression, indices, type);
            }

            var spillBuilder = new SpillBuilder();
            var spillResult = SpillExpressionsWithReceiver(expression, indices, spillBuilder, refKindsOpt: ReadOnlyArray<RefKind>.Empty);
            BoundExpression newBoundArrayAccess = node.Update(spillResult.Item1, spillResult.Item2, type);
            return spillBuilder.BuildSequenceAndFree(F, newBoundArrayAccess);
        }
        public override BoundNode VisitCall(BoundCall node)
        {
            BoundExpression receiverOpt = (BoundExpression)this.Visit(node.ReceiverOpt);
            ReadOnlyArray<BoundExpression> arguments = this.VisitList(node.Arguments);
            TypeSymbol type = this.VisitType(node.Type);

            if (!RequiresSpill(arguments) && !RequiresSpill(receiverOpt))
            {
                return node.Update(
                    receiverOpt, 
                    node.Method, 
                    arguments, 
                    node.ArgumentNamesOpt, 
                    node.ArgumentRefKindsOpt, 
                    node.IsDelegateCall,
                    node.Expanded, 
                    node.InvokedAsExtensionMethod, 
                    node.ArgsToParamsOpt, 
                    node.ResultKind, type);
            }

            var spillBuilder = new SpillBuilder();
            var spillResult = SpillExpressionsWithReceiver(receiverOpt, arguments, spillBuilder, node.Method.ParameterRefKinds);

            var newCall = node.Update(
                spillResult.Item1,
                node.Method,
                spillResult.Item2,
                node.ArgumentNamesOpt,
                node.ArgumentRefKindsOpt,
                node.IsDelegateCall,
                node.Expanded,
                node.InvokedAsExtensionMethod,
                node.ArgsToParamsOpt,
                node.ResultKind,
                type);

            return spillBuilder.BuildSequenceAndFree(F, newCall);
        }
        public override BoundNode VisitObjectCreationExpression(BoundObjectCreationExpression node)
        {
            ReadOnlyArray<BoundExpression> arguments = (ReadOnlyArray<BoundExpression>)this.VisitList(node.Arguments);
            BoundExpression initializerExpressionOpt = (BoundExpression)this.Visit(node.InitializerExpressionOpt);
            TypeSymbol type = this.VisitType(node.Type);

            if (!RequiresSpill(arguments) && (initializerExpressionOpt == null || initializerExpressionOpt.Kind != BoundKind.SpillSequence))
            {
                return node.Update(node.Constructor, arguments, node.ArgumentNamesOpt, node.ArgumentRefKindsOpt, node.Expanded, node.ArgsToParamsOpt, node.ConstantValueOpt, initializerExpressionOpt, type);
            }

            var spillBuilder = new SpillBuilder();
            ReadOnlyArray<BoundExpression> newArguments = SpillExpressionList(spillBuilder, arguments);

            BoundExpression newInitializerExpressionOpt;
            if (initializerExpressionOpt != null && initializerExpressionOpt.Kind == BoundKind.SpillSequence)
            {
                var spill = (BoundSpillSequence)initializerExpressionOpt;
                spillBuilder.AddSpill(spill);
                newInitializerExpressionOpt = spill.Value;
            }
            else
            {
                newInitializerExpressionOpt = initializerExpressionOpt;
            }

            BoundObjectCreationExpression newObjectCreation = node.Update(
                node.Constructor,
                newArguments,
                node.ArgumentNamesOpt,
                node.ArgumentRefKindsOpt,
                node.Expanded,
                node.ArgsToParamsOpt,
                node.ConstantValueOpt,
                newInitializerExpressionOpt,
                type);

            return spillBuilder.BuildSequenceAndFree(F, newObjectCreation);
        }
        public override BoundNode VisitArrayCreation(BoundArrayCreation node)
        {
            ReadOnlyArray<BoundExpression> bounds = this.VisitList(node.Bounds);
            BoundArrayInitialization visitedInitializer = (BoundArrayInitialization)this.Visit(node.InitializerOpt);
            TypeSymbol type = this.VisitType(node.Type);

            if (!RequiresSpill(bounds) && (visitedInitializer == null || !RequiresSpill(visitedInitializer.Initializers)))
            {
                return node.Update(bounds, visitedInitializer, type);
            }

            var spillBuilder = new SpillBuilder();
            ReadOnlyArray<BoundExpression> newBounds = SpillExpressionList(spillBuilder, bounds);
            BoundArrayInitialization newInitializerOpt = (visitedInitializer == null) ? visitedInitializer :
                visitedInitializer.Update(SpillExpressionList(spillBuilder, visitedInitializer.Initializers));
            BoundArrayCreation newArrayCreation = node.Update(newBounds, newInitializerOpt, type);
            return spillBuilder.BuildSequenceAndFree(F, newArrayCreation);
        }