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); }
public override BoundNode VisitGotoStatement(BoundGotoStatement node) { AddGoto(node.Label); return(base.VisitGotoStatement(node)); }
public virtual BoundStatement InstrumentGotoStatement(BoundGotoStatement original, BoundStatement rewritten) { return(InstrumentStatement(original, rewritten)); }
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)); }
public override BoundStatement InstrumentGotoStatement(BoundGotoStatement original, BoundStatement rewritten) { return(Previous.InstrumentGotoStatement(original, rewritten)); }