File: Analysis\FlowAnalysis\DataFlowPass.LocalState.vb
Web Access
Project: src\src\Compilers\VisualBasic\Portable\Microsoft.CodeAnalysis.VisualBasic.vbproj (Microsoft.CodeAnalysis.VisualBasic)
' 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
Imports System.Collections.Generic
Imports System.Diagnostics
Imports System.Threading
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
 
#If DEBUG Then
#Const REFERENCE_STATE = True
#End If
 
Namespace Microsoft.CodeAnalysis.VisualBasic
    Partial Friend Class DataFlowPass
        Inherits AbstractFlowPass(Of LocalState)
 
        Protected Overrides Function IntersectWith(ByRef self As LocalState, ByRef other As LocalState) As Boolean
            If self.Reachable = other.Reachable Then
                If self.Assigned.Capacity <> other.Assigned.Capacity Then
                    Me.Normalize(self)
                    Me.Normalize(other)
                End If
                Return IntersectBitArrays(self.Assigned, other.Assigned)
 
            ElseIf Not self.Reachable Then
                self = other.Clone()
                Return True
 
            Else
                Return False
            End If
        End Function
 
        Protected Overrides Sub UnionWith(ByRef self As LocalState, ByRef other As LocalState)
            If self.Assigned.Capacity <> other.Assigned.Capacity Then
                Normalize(self)
                Normalize(other)
            End If
 
            For slot = 0 To SlotKind.FirstAvailable - 1
                If other.Assigned(slot) Then self.Assigned(slot) = True
            Next
            For slot = SlotKind.FirstAvailable To self.Assigned.Capacity - 1
                If other.Assigned(slot) AndAlso Not self.Assigned(slot) Then
                    SetSlotAssigned(slot, self)
                End If
            Next
        End Sub
 
        Private Shared ReadOnly Property UnreachableBitsSet As BitVector
            Get
                Return BitVector.AllSet(1)
            End Get
        End Property
 
        ''' <summary>
        ''' Intersect bit arrays taking into account 'all bits set' flag
        ''' </summary>
        ''' <remarks>receiver will be changed as a result</remarks>
        Private Shared Function IntersectBitArrays(ByRef receiver As BitVector, other As BitVector) As Boolean
            ' NOTE: a state with 'unreachable' slot set to 'assigned' means 'all bits are set'
            If other(SlotKind.Unreachable) Then
                ' OTHER state has 'all bits set', thus, RECEIVER does not need to be changed
                Return False
            Else
                If receiver(SlotKind.Unreachable) Then
                    ' RECEIVER = OTHER
                    receiver = other.Clone()
                    Return True
                Else
                    ' both RECEIVER and OTHER have valid bitsets
                    Return receiver.IntersectWith(other)
                End If
            End If
        End Function
 
        Protected Sub Normalize(ByRef _state As LocalState)
            Dim oldNext As Integer = _state.Assigned.Capacity
            _state.Assigned.EnsureCapacity(nextVariableSlot)
            For i = oldNext To nextVariableSlot - 1
                Dim id As VariableIdentifier = Me.variableBySlot(i)
                If id.ContainingSlot >= SlotKind.FirstAvailable AndAlso _state.Assigned(id.ContainingSlot) Then
                    _state.Assign(i)
                End If
            Next
        End Sub
 
#If REFERENCE_STATE Then
        Friend Class LocalState
#Else
        Friend Structure LocalState
#End If
            Implements AbstractLocalState
 
            Friend Assigned As BitVector
 
            Friend Sub New(assigned As BitVector)
                Debug.Assert(Not assigned.IsNull)
                Me.Assigned = assigned
            End Sub
 
            ''' <summary>
            ''' Produce a duplicate of this flow analysis state.
            ''' </summary>
            ''' <returns></returns>
            Public Function Clone() As LocalState Implements AbstractFlowPass(Of LocalState).AbstractLocalState.Clone
                Return New LocalState(Me.Assigned.Clone())
            End Function
 
            Public Function IsAssigned(slot As Integer) As Boolean
                ' We use the first bit as an indication of the fact that state has 'all bits set'. 
                ' If the first bit is set, rest of the bits are just ignored and assumed to be set.
                Return (slot = SlotKind.NotTracked) OrElse Assigned(SlotKind.Unreachable) OrElse Assigned(slot)
            End Function
 
            Public Sub Assign(slot As Integer)
                If slot <> SlotKind.NotTracked Then
                    Me.Assigned(slot) = True
                End If
            End Sub
 
            Public Sub Unassign(slot As Integer)
                If slot <> SlotKind.NotTracked Then
                    Me.Assigned(slot) = False
                End If
            End Sub
 
            Public ReadOnly Property Reachable As Boolean
                Get
                    Return Me.Assigned.Capacity <= 0 OrElse Not Me.IsAssigned(SlotKind.Unreachable)
                End Get
            End Property
 
            Public ReadOnly Property FunctionAssignedValue As Boolean
                Get
                    Return IsAssigned(SlotKind.FunctionValue)
                End Get
            End Property
 
#If REFERENCE_STATE Then
        End Class
#Else
        End Structure
#End If
 
    End Class
 
End Namespace