/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/VisualBasic/Portable/Lowering/LocalRewriter/LocalRewriter_If.vb
213 строк
11 KB
Jonathon Marolf
update headers
23 янв 2020, 04:01
Не верифицирован
23 янв 2020, 04:01
91571a3
Код
Авторство
О чём код?
' Licensed to the .NET Foundation under one or more agreements. ' The .NET Foundation licenses this file to you under the MIT license. ' See the LICENSE file in the project root for more information. Imports System.Collections.Immutable Imports Microsoft.CodeAnalysis.Text Imports Microsoft.CodeAnalysis.VisualBasic.Syntax Namespace Microsoft.CodeAnalysis.VisualBasic Partial Friend NotInheritable Class LocalRewriter Public Overrides Function VisitIfStatement(node As BoundIfStatement) As BoundNode Dim syntax = node.Syntax Dim generateUnstructuredExceptionHandlingResumeCode As Boolean = ShouldGenerateUnstructuredExceptionHandlingResumeCode(node) Dim unstructuredExceptionHandlingResumeTarget As ImmutableArray(Of BoundStatement) = Nothing If generateUnstructuredExceptionHandlingResumeCode Then unstructuredExceptionHandlingResumeTarget = RegisterUnstructuredExceptionHandlingResumeTarget(syntax, canThrow:=True) End If ' == Rewrite Condition Dim newCondition = VisitExpressionNode(node.Condition) ' == Rewrite Consequence Dim newConsequence As BoundStatement = DirectCast(Visit(node.Consequence), BoundStatement) ' Update the resume table so exceptions that occur in the [Consequence] don't fall through to ' [AlternativeOpt] upon Resume Next and to make sure that we are in the right scope when we ' Resume Next on [End If]. Dim finishConsequenceWithResumeTarget As Boolean = (node.AlternativeOpt IsNot Nothing) ' need to add a sequence point before the body ' make sure SP is outside of the block if consequence is a block ' also add SP for End If after the consequence ' make sure SP is inside the block if the consequence is a block ' we must still have the block in scope when stopped on End If Dim instrument As Boolean = Me.Instrument(node) If instrument Then Dim resumeTarget As BoundStatement = Nothing Select Case syntax.Kind Case SyntaxKind.MultiLineIfBlock, SyntaxKind.ElseIfBlock If generateUnstructuredExceptionHandlingResumeCode AndAlso (OptimizationLevelIsDebug OrElse finishConsequenceWithResumeTarget) Then resumeTarget = RegisterUnstructuredExceptionHandlingNonThrowingResumeTarget(newConsequence.Syntax) End If finishConsequenceWithResumeTarget = False Case SyntaxKind.SingleLineIfStatement ' single line if has no EndIf Case Else Throw ExceptionUtilities.UnexpectedValue(syntax.Kind) End Select newConsequence = Concat(newConsequence, _instrumenterOpt.InstrumentIfStatementConsequenceEpilogue(node, resumeTarget)) End If If generateUnstructuredExceptionHandlingResumeCode AndAlso finishConsequenceWithResumeTarget Then newConsequence = Concat(newConsequence, RegisterUnstructuredExceptionHandlingNonThrowingResumeTarget(newConsequence.Syntax)) End If ' == Rewrite Else Dim newAlternative As BoundStatement = DirectCast(Visit(node.AlternativeOpt), BoundStatement) If instrument AndAlso newAlternative IsNot Nothing Then If syntax.Kind <> SyntaxKind.SingleLineIfStatement Then Dim asElse = TryCast(node.AlternativeOpt.Syntax, ElseBlockSyntax) If asElse IsNot Nothing Then ' Update the resume table to make sure that we are in the right scope when we Resume Next on [End If]. Dim resumeTarget As BoundStatement = Nothing If generateUnstructuredExceptionHandlingResumeCode AndAlso OptimizationLevelIsDebug Then resumeTarget = RegisterUnstructuredExceptionHandlingNonThrowingResumeTarget(newAlternative.Syntax) End If newAlternative = Concat(newAlternative, _instrumenterOpt.InstrumentIfStatementAlternativeEpilogue(node, resumeTarget)) newAlternative = PrependWithPrologue(newAlternative, _instrumenterOpt.CreateIfStatementAlternativePrologue(node)) End If Else Dim asElse = TryCast(node.AlternativeOpt.Syntax, SingleLineElseClauseSyntax) If asElse IsNot Nothing Then newAlternative = PrependWithPrologue(newAlternative, _instrumenterOpt.CreateIfStatementAlternativePrologue(node)) ' single line if has no EndIf End If End If End If ' == Rewrite the whole node ' 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. Debug.Assert(newCondition IsNot Nothing) If instrument Then newCondition = _instrumenterOpt.InstrumentIfStatementCondition(node, newCondition, _currentMethodOrLambda) End If Dim result As BoundStatement = RewriteIfStatement( node.Syntax, newCondition, newConsequence, newAlternative, instrumentationTargetOpt:=If(instrument, node, Nothing), unstructuredExceptionHandlingResumeTarget:=unstructuredExceptionHandlingResumeTarget) Return result End Function Private Function RewriteIfStatement( syntaxNode As SyntaxNode, rewrittenCondition As BoundExpression, rewrittenConsequence As BoundStatement, rewrittenAlternative As BoundStatement, instrumentationTargetOpt As BoundStatement, Optional unstructuredExceptionHandlingResumeTarget As ImmutableArray(Of BoundStatement) = Nothing ) As BoundStatement Debug.Assert(unstructuredExceptionHandlingResumeTarget.IsDefaultOrEmpty OrElse instrumentationTargetOpt IsNot Nothing) ' Note that ElseIf clauses are transformed into a nested if inside an else at the bound tree generation, so ' a BoundIfStatement does not contain ElseIf clauses. Dim afterif = GenerateLabel("afterif") Dim afterIfStatement As BoundStatement = New BoundLabelStatement(syntaxNode, afterif) If rewrittenAlternative Is Nothing Then ' if (condition) ' consequence; ' ' becomes ' ' GotoIfFalse condition afterif; ' consequence; ' afterif: Dim condGoto As BoundStatement = New BoundConditionalGoto(syntaxNode, rewrittenCondition, False, afterif) If Not unstructuredExceptionHandlingResumeTarget.IsDefaultOrEmpty Then condGoto = New BoundStatementList(condGoto.Syntax, unstructuredExceptionHandlingResumeTarget.Add(condGoto)) End If If instrumentationTargetOpt IsNot Nothing Then Select Case instrumentationTargetOpt.Syntax.Kind Case SyntaxKind.MultiLineIfBlock, SyntaxKind.ElseIfBlock, SyntaxKind.SingleLineIfStatement condGoto = _instrumenterOpt.InstrumentIfStatementConditionalGoto(DirectCast(instrumentationTargetOpt, BoundIfStatement), condGoto) Case SyntaxKind.CaseBlock condGoto = _instrumenterOpt.InstrumentCaseBlockConditionalGoto(DirectCast(instrumentationTargetOpt, BoundCaseBlock), condGoto) Case Else Throw ExceptionUtilities.UnexpectedValue(instrumentationTargetOpt.Syntax.Kind) End Select If instrumentationTargetOpt.Syntax.Kind = SyntaxKind.MultiLineIfBlock Then ' If it is a multiline If and there is no else, associate afterIf with EndIf afterIfStatement = _instrumenterOpt.InstrumentIfStatementAfterIfStatement(DirectCast(instrumentationTargetOpt, BoundIfStatement), afterIfStatement) Else ' otherwise hide afterif (so that it does not associate with if body). afterIfStatement = SyntheticBoundNodeFactory.HiddenSequencePoint(afterIfStatement) End If End If Return New BoundStatementList(syntaxNode, ImmutableArray.Create(condGoto, rewrittenConsequence, afterIfStatement)) Else ' if (condition) ' consequence; ' else ' alternative ' ' becomes ' ' GotoIfFalse condition alt; ' consequence ' goto afterif; ' alt: ' alternative; ' afterif: Dim alt = GenerateLabel("alternative") Dim condGoto As BoundStatement = New BoundConditionalGoto(syntaxNode, rewrittenCondition, False, alt) If Not unstructuredExceptionHandlingResumeTarget.IsDefaultOrEmpty Then condGoto = New BoundStatementList(condGoto.Syntax, unstructuredExceptionHandlingResumeTarget.Add(condGoto)) End If If instrumentationTargetOpt IsNot Nothing Then Select Case instrumentationTargetOpt.Syntax.Kind Case SyntaxKind.MultiLineIfBlock, SyntaxKind.ElseIfBlock, SyntaxKind.SingleLineIfStatement condGoto = _instrumenterOpt.InstrumentIfStatementConditionalGoto(DirectCast(instrumentationTargetOpt, BoundIfStatement), condGoto) Case SyntaxKind.CaseBlock condGoto = _instrumenterOpt.InstrumentCaseBlockConditionalGoto(DirectCast(instrumentationTargetOpt, BoundCaseBlock), condGoto) Case Else Throw ExceptionUtilities.UnexpectedValue(instrumentationTargetOpt.Syntax.Kind) End Select End If Return New BoundStatementList(syntaxNode, ImmutableArray.Create(Of BoundStatement)( condGoto, rewrittenConsequence, New BoundGotoStatement(syntaxNode, afterif, Nothing), New BoundLabelStatement(syntaxNode, alt), rewrittenAlternative, afterIfStatement)) End If End Function End Class End Namespace