public override BoundNode VisitGotoStatement(BoundGotoStatement node)
        {
            BoundExpression caseExpressionOpt  = (BoundExpression)this.Visit(node.CaseExpressionOpt);
            BoundLabel      labelExpressionOpt = (BoundLabel)this.Visit(node.LabelExpressionOpt);
            var             proxyLabel         = _currentFinallyFrame.ProxyLabelIfNeeded(node.Label);

            Debug.Assert(node.Label == proxyLabel || !(F.CurrentFunction is IteratorFinallyMethodSymbol), "should not be proxying branches in finally");
            return(node.Update(proxyLabel, caseExpressionOpt, labelExpressionOpt));
        }
        public override BoundNode VisitContinueStatement(BoundContinueStatement node)
        {
            BoundStatement result = new BoundGotoStatement(node.Syntax, node.Label, node.HasErrors);

            if (this.Instrument && !node.WasCompilerGenerated)
            {
                result = _instrumenter.InstrumentContinueStatement(node, result);
            }

            return(result);
        }
        public override BoundNode VisitGotoStatement(BoundGotoStatement node)
        {
            // we are removing the label expressions from the bound tree because this expression is no longer needed
            // for the emit phase. It is even doing harm to e.g. the stack depth calculation because this expression
            // would not need to be pushed to the stack.
            BoundExpression caseExpressionOpt = null;

            // we are removing the label expressions from the bound tree because this expression is no longer needed
            // for the emit phase. It is even doing harm to e.g. the stack depth calculation because this expression
            // would not need to be pushed to the stack.
            BoundLabel     labelExpressionOpt = null;
            BoundStatement result             = node.Update(node.Label, caseExpressionOpt, labelExpressionOpt);

            if (this.Instrument && !node.WasCompilerGenerated)
            {
                result = _instrumenter.InstrumentGotoStatement(node, result);
            }

            return(result);
        }
Пример #4
0
 public override BoundNode VisitGotoStatement(BoundGotoStatement node)
 {
     AddGoto(node.Label);
     return(base.VisitGotoStatement(node));
 }
Пример #5
0
 public virtual BoundStatement InstrumentGotoStatement(BoundGotoStatement original, BoundStatement rewritten)
 {
     return(InstrumentStatement(original, rewritten));
 }
Пример #6
0
 public override BoundStatement InstrumentGotoStatement(BoundGotoStatement original, BoundStatement rewritten)
 {
     return(AddSequencePoint(base.InstrumentGotoStatement(original, rewritten)));
 }
 public override BoundStatement InstrumentGotoStatement(BoundGotoStatement original, BoundStatement rewritten)
 {
     return(AddDynamicAnalysis(original, base.InstrumentGotoStatement(original, rewritten)));
 }
        private BoundStatement RewriteForStatementWithoutInnerLocals(
            BoundLoopStatement original,
            ImmutableArray <LocalSymbol> outerLocals,
            BoundStatement rewrittenInitializer,
            BoundExpression rewrittenCondition,
            BoundStatement rewrittenIncrement,
            BoundStatement rewrittenBody,
            GeneratedLabelSymbol breakLabel,
            GeneratedLabelSymbol continueLabel,
            bool hasErrors)
        {
            Debug.Assert(original.Kind == BoundKind.ForStatement || original.Kind == BoundKind.ForEachStatement);
            Debug.Assert(rewrittenBody != null);

            // The sequence point behavior exhibited here is different from that of the native compiler.  In the native
            // compiler, if you have something like
            //
            // for([|int i = 0, j = 0|]; ; [|i++, j++|])
            //
            // then all the initializers are treated as a single sequence point, as are
            // all the loop incrementors.
            //
            // We now make each one individually a sequence point:
            //
            // for([|int i = 0|], [|j = 0|]; ; [|i++|], [|j++|])
            //
            // If we decide that we want to preserve the native compiler stepping behavior
            // then we'll need to be a bit fancy here. The initializer and increment statements
            // can contain lambdas whose bodies need to have sequence points inserted, so we
            // need to make sure we visit the children. But we'll also need to make sure that
            // we do not generate one sequence point for each statement in the initializers
            // and the incrementors.

            SyntaxNode syntax           = original.Syntax;
            var        statementBuilder = ArrayBuilder <BoundStatement> .GetInstance();

            if (rewrittenInitializer != null)
            {
                statementBuilder.Add(rewrittenInitializer);
            }

            var startLabel = new GeneratedLabelSymbol("start");

            // for (initializer; condition; increment)
            //   body;
            //
            // becomes the following (with block added for locals)
            //
            // {
            //   initializer;
            //   goto end;
            // start:
            //   body;
            // continue:
            //   increment;
            // end:
            //   GotoIfTrue condition start;
            // break:
            // }

            var endLabel = new GeneratedLabelSymbol("end");

            //  initializer;
            //  goto end;

            BoundStatement gotoEnd = new BoundGotoStatement(syntax, endLabel);

            if (this.Instrument)
            {
                // Mark the initial jump as hidden.
                // We do it to tell that this is not a part of previous statement.
                // This jump may be a target of another jump (for example if loops are nested) and that will make
                // impression of the previous statement being re-executed
                gotoEnd = new BoundSequencePoint(null, gotoEnd);
            }

            statementBuilder.Add(gotoEnd);

            // start:
            //   body;
            statementBuilder.Add(new BoundLabelStatement(syntax, startLabel));

            statementBuilder.Add(rewrittenBody);

            // continue:
            //   increment;
            statementBuilder.Add(new BoundLabelStatement(syntax, continueLabel));
            if (rewrittenIncrement != null)
            {
                statementBuilder.Add(rewrittenIncrement);
            }

            // end:
            //   GotoIfTrue condition start;
            statementBuilder.Add(new BoundLabelStatement(syntax, endLabel));
            BoundStatement branchBack = null;

            if (rewrittenCondition != null)
            {
                branchBack = new BoundConditionalGoto(rewrittenCondition.Syntax, rewrittenCondition, true, startLabel);
            }
            else
            {
                branchBack = new BoundGotoStatement(syntax, startLabel);
            }

            if (this.Instrument)
            {
                switch (original.Kind)
                {
                case BoundKind.ForEachStatement:
                    branchBack = _instrumenter.InstrumentForEachStatementConditionalGotoStart((BoundForEachStatement)original, branchBack);
                    break;

                default:
                    throw ExceptionUtilities.UnexpectedValue(original.Kind);
                }
            }

            statementBuilder.Add(branchBack);

            // break:
            statementBuilder.Add(new BoundLabelStatement(syntax, breakLabel));

            var statements = statementBuilder.ToImmutableAndFree();

            return(new BoundBlock(syntax, outerLocals, statements, hasErrors));
        }
Пример #9
0
 public override BoundStatement InstrumentGotoStatement(BoundGotoStatement original, BoundStatement rewritten)
 {
     return(Previous.InstrumentGotoStatement(original, rewritten));
 }