private void EmitSequencePointStatement(BoundSequencePointWithSpan node) { TextSpan span = node.Span; if (span != default(TextSpan) && _emitPdbSequencePoints) { this.EmitSequencePoint(node.SyntaxTree, span); } BoundStatement statement = node.StatementOpt; int instructionsEmitted = 0; if (statement != null) { instructionsEmitted = this.EmitStatementAndCountInstructions(statement); } if ( instructionsEmitted == 0 && span != default(TextSpan) && _ilEmitStyle == ILEmitStyle.Debug ) { // if there was no code emitted, then emit nop // otherwise this point could get associated with some random statement, possibly in a wrong scope _builder.EmitOpCode(ILOpCode.Nop); } }
private void EmitSequencePointStatement(BoundSequencePointWithSpan node) { AssertExplicitSequencePointAllowed(); TextSpan span = node.Span; if (span != default(TextSpan) && this.emitSequencePoints) { this.EmitSequencePoint(node.SyntaxTree, span); } BoundStatement statement = node.StatementOpt; int instructionsEmitted = 0; if (statement != null) { instructionsEmitted = -builder.InstructionsEmitted; this.EmitStatement(statement); instructionsEmitted += builder.InstructionsEmitted; } if (instructionsEmitted == 0 && span != default(TextSpan) && noOptimizations) { // if there was no code emitted, then emit nop // otherwise this point could get associated with some random statement, possibly in a wrong scope builder.EmitOpCode(ILOpCode.Nop); } }
/// <summary> /// Add sequence point |here|: /// /// |foreach| (Type var in expr) { } /// </summary> /// <remarks> /// Hit once, before looping begins. /// </remarks> private void AddForEachKeywordSequencePoint(ForEachStatementSyntax forEachSyntax, ref BoundStatement result) { if (this.generateDebugInfo) { BoundSequencePointWithSpan foreachKeywordSequencePoint = new BoundSequencePointWithSpan(forEachSyntax, null, forEachSyntax.ForEachKeyword.Span); result = new BoundStatementList(forEachSyntax, ReadOnlyArray <BoundStatement> .CreateFrom(foreachKeywordSequencePoint, result)); } }
/// <summary> /// Add sequence point |here|: /// /// foreach (|Type var| in expr) { } /// </summary> /// <remarks> /// Hit every iteration. /// </remarks> private void AddForEachIterationVariableSequencePoint(ForEachStatementSyntax forEachSyntax, ref BoundStatement iterationVarDecl) { if (this.generateDebugInfo) { TextSpan iterationVarDeclSpan = TextSpan.FromBounds(forEachSyntax.Type.Span.Start, forEachSyntax.Identifier.Span.End); iterationVarDecl = new BoundSequencePointWithSpan(forEachSyntax, iterationVarDecl, iterationVarDeclSpan); } }
/// <summary> /// Add sequence point |here|: /// /// |foreach| (Type var in expr) { } /// </summary> /// <remarks> /// Hit once, before looping begins. /// </remarks> public override BoundStatement InstrumentForEachStatement(BoundForEachStatement original, BoundStatement rewritten) { var forEachSyntax = (ForStatementSyntax)original.Syntax; BoundSequencePointWithSpan foreachKeywordSequencePoint = new BoundSequencePointWithSpan(forEachSyntax, null, forEachSyntax.ForEachKeyword.Span); return(new BoundStatementList(forEachSyntax, ImmutableArray.Create <BoundStatement>(foreachKeywordSequencePoint, base.InstrumentForEachStatement(original, rewritten)))); }
private BoundStatement RewriteWhileStatement( SyntaxNode syntax, BoundExpression rewrittenCondition, TextSpan conditionSequencePointSpan, BoundStatement rewrittenBody, GeneratedLabelSymbol breakLabel, GeneratedLabelSymbol continueLabel, bool hasErrors) { var startLabel = new GeneratedLabelSymbol("start"); BoundStatement ifConditionGotoStart = new BoundConditionalGoto(rewrittenCondition.Syntax, rewrittenCondition, true, startLabel); if (this.generateDebugInfo) { ifConditionGotoStart = new BoundSequencePointWithSpan(syntax, ifConditionGotoStart, conditionSequencePointSpan); } // while (condition) // body; // // becomes // // goto continue; // start: // body // continue: // GotoIfTrue condition start; // break: BoundStatement gotoContinue = new BoundGotoStatement(syntax, continueLabel); if (this.generateDebugInfo) { //mark the initial jump as hidden. //We do it to tell that this is not a part of previou 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 gotoContinue = new BoundSequencePoint(null, gotoContinue); } return(BoundStatementList.Synthesized(syntax, hasErrors, gotoContinue, new BoundLabelStatement(syntax, startLabel), rewrittenBody, new BoundLabelStatement(syntax, continueLabel), ifConditionGotoStart, new BoundLabelStatement(syntax, breakLabel))); }
public override BoundNode VisitDoStatement(BoundDoStatement node) { Debug.Assert(node != null); var rewrittenCondition = (BoundExpression)Visit(node.Condition); var rewrittenBody = (BoundStatement)Visit(node.Body); var startLabel = new GeneratedLabelSymbol("start"); var syntax = node.Syntax; BoundStatement ifConditionGotoStart = new BoundConditionalGoto(syntax, rewrittenCondition, true, startLabel); if (this.generateDebugInfo) { var doSyntax = (DoStatementSyntax)syntax; var span = TextSpan.FromBounds( doSyntax.WhileKeyword.Span.Start, doSyntax.SemicolonToken.Span.End); ifConditionGotoStart = new BoundSequencePointWithSpan(doSyntax, ifConditionGotoStart, span); } // do // body // while (condition); // // becomes // // start: // body // continue: // sequence point // GotoIfTrue condition start; // break: return(BoundStatementList.Synthesized(syntax, node.HasErrors, new BoundLabelStatement(syntax, startLabel), rewrittenBody, new BoundLabelStatement(syntax, node.ContinueLabel), ifConditionGotoStart, new BoundLabelStatement(syntax, node.BreakLabel))); }
internal static BoundBlock ConstructDestructorBody(MethodSymbol method, BoundBlock block) { var syntax = block.Syntax; Debug.Assert(method.MethodKind == MethodKind.Destructor); Debug.Assert(syntax.Kind() == SyntaxKind.Block || syntax.Kind() == SyntaxKind.ArrowExpressionClause); // If this is a destructor and a base type has a Finalize method (see GetBaseTypeFinalizeMethod for exact // requirements), then we need to call that method in a finally block. Otherwise, just return block as-is. // NOTE: the Finalize method need not be a destructor or be overridden by the current method. MethodSymbol baseTypeFinalize = GetBaseTypeFinalizeMethod(method); if ((object)baseTypeFinalize != null) { BoundStatement baseFinalizeCall = new BoundExpressionStatement( syntax, BoundCall.Synthesized( syntax, new BoundBaseReference( syntax, method.ContainingType) { WasCompilerGenerated = true }, baseTypeFinalize)) { WasCompilerGenerated = true }; if (syntax.Kind() == SyntaxKind.Block) { //sequence point to mimic Dev10 baseFinalizeCall = new BoundSequencePointWithSpan( syntax, baseFinalizeCall, ((BlockSyntax)syntax).CloseBraceToken.Span); } return(new BoundBlock( syntax, ImmutableArray <LocalSymbol> .Empty, ImmutableArray.Create <BoundStatement>( new BoundTryStatement( syntax, block, ImmutableArray <BoundCatchBlock> .Empty, new BoundBlock( syntax, ImmutableArray <LocalSymbol> .Empty, ImmutableArray.Create <BoundStatement>( baseFinalizeCall) ) { WasCompilerGenerated = true } ) { WasCompilerGenerated = true }))); } return(block); }
/// <summary> /// Add sequence point |here|: /// /// |foreach| (Type var in expr) { } /// </summary> /// <remarks> /// Hit once, before looping begins. /// </remarks> private void AddForEachKeywordSequencePoint(ForEachStatementSyntax forEachSyntax, ref BoundStatement result) { if (this.generateDebugInfo) { BoundSequencePointWithSpan foreachKeywordSequencePoint = new BoundSequencePointWithSpan(forEachSyntax, null, forEachSyntax.ForEachKeyword.Span); result = new BoundStatementList(forEachSyntax, ReadOnlyArray<BoundStatement>.CreateFrom(foreachKeywordSequencePoint, result)); } }
private BoundStatement RewriteWhileStatement( SyntaxNode syntax, BoundExpression rewrittenCondition, TextSpan conditionSequencePointSpan, BoundStatement rewrittenBody, GeneratedLabelSymbol breakLabel, GeneratedLabelSymbol continueLabel, bool hasErrors) { var startLabel = new GeneratedLabelSymbol("start"); BoundStatement ifConditionGotoStart = new BoundConditionalGoto(rewrittenCondition.Syntax, rewrittenCondition, true, startLabel); if (this.generateDebugInfo) { ifConditionGotoStart = new BoundSequencePointWithSpan(syntax, ifConditionGotoStart, conditionSequencePointSpan); } // while (condition) // body; // // becomes // // goto continue; // start: // body // continue: // GotoIfTrue condition start; // break: BoundStatement gotoContinue = new BoundGotoStatement(syntax, continueLabel); if (this.generateDebugInfo) { //mark the initial jump as hidden. //We do it to tell that this is not a part of previou 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 gotoContinue = new BoundSequencePoint(null, gotoContinue); } return BoundStatementList.Synthesized(syntax, hasErrors, gotoContinue, new BoundLabelStatement(syntax, startLabel), rewrittenBody, new BoundLabelStatement(syntax, continueLabel), ifConditionGotoStart, new BoundLabelStatement(syntax, breakLabel)); }
private BoundStatement RewriteForStatement( SyntaxNode syntax, ReadOnlyArray <LocalSymbol> locals, BoundStatement rewrittenInitializer, BoundExpression rewrittenCondition, SyntaxNodeOrToken conditionSyntax, BoundStatement rewrittenIncrement, BoundStatement rewrittenBody, GeneratedLabelSymbol breakLabel, GeneratedLabelSymbol continueLabel, bool hasErrors) { var startLabel = new GeneratedLabelSymbol("start"); var endLabel = new GeneratedLabelSymbol("end"); // 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: // } // initializer; // goto end; var statementBuilder = ArrayBuilder <BoundStatement> .GetInstance(); if (rewrittenInitializer != null) { statementBuilder.Add(rewrittenInitializer); } //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 var gotoEnd = new BoundSequencePoint(null, new BoundGotoStatement(syntax, endLabel)); statementBuilder.Add(gotoEnd); // start: // body; statementBuilder.Add(new BoundLabelStatement(syntax, startLabel)); Debug.Assert(rewrittenBody != null); 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.generateDebugInfo) { if (conditionSyntax.IsToken) { branchBack = new BoundSequencePointWithSpan(syntax, branchBack, conditionSyntax.Span); } else { //if there is no condition, make this a hidden point so that //it does not count as a part of previous statement branchBack = new BoundSequencePoint(conditionSyntax.AsNode(), branchBack); } } statementBuilder.Add(branchBack); // break: statementBuilder.Add(new BoundLabelStatement(syntax, breakLabel)); var statements = statementBuilder.ToReadOnlyAndFree(); return(new BoundBlock(syntax, locals, statements, hasErrors)); }
private BoundStatement RewriteForStatement( SyntaxNode syntax, ReadOnlyArray<LocalSymbol> locals, BoundStatement rewrittenInitializer, BoundExpression rewrittenCondition, SyntaxNodeOrToken conditionSyntax, BoundStatement rewrittenIncrement, BoundStatement rewrittenBody, GeneratedLabelSymbol breakLabel, GeneratedLabelSymbol continueLabel, bool hasErrors) { var startLabel = new GeneratedLabelSymbol("start"); var endLabel = new GeneratedLabelSymbol("end"); // 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: // } // initializer; // goto end; var statementBuilder = ArrayBuilder<BoundStatement>.GetInstance(); if (rewrittenInitializer != null) { statementBuilder.Add(rewrittenInitializer); } //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 var gotoEnd = new BoundSequencePoint(null, new BoundGotoStatement(syntax, endLabel)); statementBuilder.Add(gotoEnd); // start: // body; statementBuilder.Add(new BoundLabelStatement(syntax, startLabel)); Debug.Assert(rewrittenBody != null); 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.generateDebugInfo) { if (conditionSyntax.IsToken) { branchBack = new BoundSequencePointWithSpan(syntax, branchBack, conditionSyntax.Span); } else { //if there is no condition, make this a hidden point so that //it does not count as a part of previous statement branchBack = new BoundSequencePoint(conditionSyntax.AsNode(), branchBack); } } statementBuilder.Add(branchBack); // break: statementBuilder.Add(new BoundLabelStatement(syntax, breakLabel)); var statements = statementBuilder.ToReadOnlyAndFree(); return new BoundBlock(syntax, locals, statements, hasErrors); }
public override BoundNode VisitDoStatement(BoundDoStatement node) { Debug.Assert(node != null); var rewrittenCondition = (BoundExpression)Visit(node.Condition); var rewrittenBody = (BoundStatement)Visit(node.Body); var startLabel = new GeneratedLabelSymbol("start"); var syntax = node.Syntax; BoundStatement ifConditionGotoStart = new BoundConditionalGoto(syntax, rewrittenCondition, true, startLabel); if (this.generateDebugInfo) { var doSyntax = (DoStatementSyntax)syntax; var span = TextSpan.FromBounds( doSyntax.WhileKeyword.Span.Start, doSyntax.SemicolonToken.Span.End); ifConditionGotoStart = new BoundSequencePointWithSpan(doSyntax, ifConditionGotoStart, span); } // do // body // while (condition); // // becomes // // start: // body // continue: // sequence point // GotoIfTrue condition start; // break: return BoundStatementList.Synthesized(syntax, node.HasErrors, new BoundLabelStatement(syntax, startLabel), rewrittenBody, new BoundLabelStatement(syntax, node.ContinueLabel), ifConditionGotoStart, new BoundLabelStatement(syntax, node.BreakLabel)); }
private void EmitSequencePointStatement(BoundSequencePointWithSpan node) { TextSpan span = node.Span; if (span != default(TextSpan) && _emitPdbSequencePoints) { this.EmitSequencePoint(node.SyntaxTree, span); } BoundStatement statement = node.StatementOpt; int instructionsEmitted = 0; if (statement != null) { instructionsEmitted = this.EmitStatementAndCountInstructions(statement); } if (instructionsEmitted == 0 && span != default(TextSpan) && _ilEmitStyle == ILEmitStyle.Debug) { // if there was no code emitted, then emit nop // otherwise this point could get associated with some random statement, possibly in a wrong scope _builder.EmitOpCode(ILOpCode.Nop); } }
public override object VisitSequencePointWithSpan(BoundSequencePointWithSpan node, object arg) { return(null); }