Permalink
Switch branches/tags
version-2.9.0 version-2.8.2 version-2.8.0 version-2.7.0-beta3 version-2.6.0-beta3 version-2.4.0 version-2.3.5 version-2.3.4 version-2.3.2 version-2.3.2-beta1 version-2.3.0-beta3 version-2.3.0-beta2 version-2.3.0-beta1 version-2.2.0 version-2.1.0 version-2.0.0 version-2.0.0-rc4 version-2.0.0-rc3 version-2.0.0-rc2 version-2.0.0-rc version-2.0.0-beta5 version-2.0.0-beta4 version-2.0.0-beta3 version-2.0.0-beta1 version-1.3.2 version-1.3.1 version-1.3.0 version-1.3.0-beta1-20160429-01 version-1.2.2 version-1.2.1 version-1.2.0 version-1.2.0-beta1-20160108-01 version-1.2.0-beta version-1.2.0-beta-20151211-01 version-1.1.1 version-1.1.0 version-1.1.0-rc1-20151109-01 version-1.0.0 version-1.0.0-beta1-20141031-01 toolset_5 toolset_3 toolset_2 toolset_1_1 toolset_1 Visual.Studio.2015.Update.1.RC Visual.Studio.2015.Update.1.CTP Visual-Studio-2017 Visual-Studio-2017-Version-15.8 Visual-Studio-2017-Version-15.7.2 Visual-Studio-2017-Version-15.7 Visual-Studio-2017-Version-15.6 Visual-Studio-2017-Version-15.5 Visual-Studio-2017-Version-15.4 Visual-Studio-2017-Version-15.3.5 Visual-Studio-2017-Version-15.3.4 Visual-Studio-2017-Version-15.3.2 Visual-Studio-2017-Version-15.3 Visual-Studio-2017-Version-15.2 Visual-Studio-2017-Version-15.1 Visual-Studio-2017-RC4 Visual-Studio-2017-RC3 Visual-Studio-2017-RC2 Visual-Studio-2017-RC Visual-Studio-2017-Preview-Version-15.3 Visual-Studio-2017-Preview-6-Version-15.7 Visual-Studio-2017-Preview-3-Version-15.4 Visual-Studio-2017-Preview-3-Version-15.3 Visual-Studio-2017-Preview-2-Version-15.4 Visual-Studio-2017-Preview-2-Version-15.3 Visual-Studio-2017-Preview-1-Version-15.4 Visual-Studio-2015 Visual-Studio-2015-Update-3 Visual-Studio-2015-Update-3-Micro-Update-1 Visual-Studio-2015-Update-2 Visual-Studio-2015-Update-2-RC Visual-Studio-2015-Update-2-Micro-Update-3 Visual-Studio-2015-Update-2-Micro-Update-1 Visual-Studio-2015-Update-1 Visual-Studio-2015-Update-1-RC Visual-Studio-2015-Update-1-CTP Visual-Studio-2015-RC Visual-Studio-2015-Preview Visual-Studio-2015-CTP-6 Visual-Studio-2015-CTP-5 Visual-Studio-15-Preview Visual-Studio-15-Preview-5 Visual-Studio-15-Preview-4 Visual-Studio-15-Preview-3 VS.Toolset.Roslyn.1.1.0-beta1-20150727-01 VS.Tools.X86.Managed.V45.1.0.150513.2 Oss.Scan.2015.03.13 Oss.Scan.2013.03.13 NetFx.Toolset.150729
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
150 lines (130 sloc) 6.05 KB
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using System.Collections.Immutable;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp
{
internal sealed partial class LocalRewriter
{
public override BoundNode VisitWhileStatement(BoundWhileStatement node)
{
Debug.Assert(node != null);
var rewrittenCondition = (BoundExpression)Visit(node.Condition);
var rewrittenBody = (BoundStatement)Visit(node.Body);
// EnC: We need to insert a hidden sequence point to handle function remapping in case
// the containing method is edited while methods invoked in the condition are being executed.
if (!node.WasCompilerGenerated && this.Instrument)
{
rewrittenCondition = _instrumenter.InstrumentWhileStatementCondition(node, rewrittenCondition, _factory);
}
return RewriteWhileStatement(
node,
node.Locals,
rewrittenCondition,
rewrittenBody,
node.BreakLabel,
node.ContinueLabel,
node.HasErrors);
}
private BoundStatement RewriteWhileStatement(
BoundLoopStatement loop,
BoundExpression rewrittenCondition,
BoundStatement rewrittenBody,
GeneratedLabelSymbol breakLabel,
GeneratedLabelSymbol continueLabel,
bool hasErrors)
{
Debug.Assert(loop.Kind == BoundKind.WhileStatement || loop.Kind == BoundKind.ForEachStatement);
// while (condition)
// body;
//
// becomes
//
// goto continue;
// start:
// {
// body
// continue:
// GotoIfTrue condition start;
// }
// break:
SyntaxNode syntax = loop.Syntax;
var startLabel = new GeneratedLabelSymbol("start");
BoundStatement ifConditionGotoStart = new BoundConditionalGoto(rewrittenCondition.Syntax, rewrittenCondition, true, startLabel);
BoundStatement gotoContinue = new BoundGotoStatement(syntax, continueLabel);
if (this.Instrument && !loop.WasCompilerGenerated)
{
switch (loop.Kind)
{
case BoundKind.WhileStatement:
ifConditionGotoStart = _instrumenter.InstrumentWhileStatementConditionalGotoStartOrBreak((BoundWhileStatement)loop, ifConditionGotoStart);
break;
case BoundKind.ForEachStatement:
ifConditionGotoStart = _instrumenter.InstrumentForEachStatementConditionalGotoStart((BoundForEachStatement)loop, ifConditionGotoStart);
break;
default:
throw ExceptionUtilities.UnexpectedValue(loop.Kind);
}
// 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 would give the
// impression that the previous statement is 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 RewriteWhileStatement(
BoundWhileStatement loop,
ImmutableArray<LocalSymbol> locals,
BoundExpression rewrittenCondition,
BoundStatement rewrittenBody,
GeneratedLabelSymbol breakLabel,
GeneratedLabelSymbol continueLabel,
bool hasErrors)
{
if (locals.IsEmpty)
{
return RewriteWhileStatement(loop, rewrittenCondition, rewrittenBody, breakLabel, continueLabel, hasErrors);
}
// We need to enter scope-block from the top, that is where an instance of a display class will be created
// if any local is captured within a lambda.
// while (condition)
// body;
//
// becomes
//
// continue:
// {
// GotoIfFalse condition break;
// body
// goto continue;
// }
// break:
SyntaxNode syntax = loop.Syntax;
BoundStatement continueLabelStatement = new BoundLabelStatement(syntax, continueLabel);
BoundStatement ifNotConditionGotoBreak = new BoundConditionalGoto(rewrittenCondition.Syntax, rewrittenCondition, false, breakLabel);
if (this.Instrument && !loop.WasCompilerGenerated)
{
ifNotConditionGotoBreak = _instrumenter.InstrumentWhileStatementConditionalGotoStartOrBreak(loop, ifNotConditionGotoBreak);
continueLabelStatement = new BoundSequencePoint(null, continueLabelStatement);
}
return BoundStatementList.Synthesized(syntax, hasErrors,
continueLabelStatement,
new BoundBlock(syntax,
locals,
ImmutableArray.Create(
ifNotConditionGotoBreak,
rewrittenBody,
new BoundGotoStatement(syntax, continueLabel))),
new BoundLabelStatement(syntax, breakLabel));
}
}
}