File: Compilation\TypeCompilationState.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.Collections.Immutable
Imports Microsoft.CodeAnalysis.Emit
Imports Microsoft.CodeAnalysis.CodeGen
Imports Microsoft.CodeAnalysis.PooledObjects
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Emit
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Imports ReferenceEqualityComparer = Roslyn.Utilities.ReferenceEqualityComparer
 
Namespace Microsoft.CodeAnalysis.VisualBasic
 
    ''' <summary>
    ''' Represents the state of compilation of one particular type.
    ''' This includes, for example, a collection of synthesized methods created during lowering.
    ''' WARNING: Note that the underlying collection classes are not thread-safe and this will
    ''' need to be revised if emit phase is changed to support multithreading when
    ''' translating a particular type.
    ''' </summary>
    Friend Class TypeCompilationState
 
        ''' <summary> Method's information </summary>
        Public Structure MethodWithBody
            Public ReadOnly Method As MethodSymbol
            Public ReadOnly Body As BoundStatement
            Public ReadOnly StateMachineType As StateMachineTypeSymbol
            Public ReadOnly StateMachineStatesDebugInfo As ImmutableArray(Of StateMachineStateDebugInfo)
 
            Friend Sub New(method As MethodSymbol,
                           body As BoundStatement,
                           stateMachineType As StateMachineTypeSymbol,
                           stateMachineStatesDebugInfo As ImmutableArray(Of StateMachineStateDebugInfo))
 
                Debug.Assert(Not stateMachineStatesDebugInfo.IsDefault)
 
                Me.Method = method
                Me.Body = body
                Me.StateMachineType = stateMachineType
                Me.StateMachineStatesDebugInfo = stateMachineStatesDebugInfo
            End Sub
        End Structure
 
        Public ReadOnly Compilation As VisualBasicCompilation
 
        Public staticLambdaFrame As LambdaFrame
 
        ' Can be Nothing if we're not emitting.
        ' During the lowering phase, however, it cannot be Nothing.
        Public ReadOnly ModuleBuilderOpt As PEModuleBuilder
 
        ''' <summary> Flat array of created methods, non-empty if not-nothing </summary>
        Private _synthesizedMethods As ArrayBuilder(Of MethodWithBody) = Nothing
 
        Public ReadOnly InitializeComponentOpt As MethodSymbol
 
        ''' <summary>
        ''' A mapping from (source) iterator or async methods to the compiler-generated classes that implement them.
        ''' </summary>
        Public ReadOnly StateMachineImplementationClass As New Dictionary(Of MethodSymbol, NamedTypeSymbol)(ReferenceEqualityComparer.Instance)
 
        ''' <summary>
        ''' Map of 'MyBase' or 'MyClass' call wrappers; actually each method symbol will
        ''' only need one wrapper to call it non-virtually;
        '''
        ''' Indeed, if the type have a virtual method M1 overridden, MyBase.M1 will use
        ''' a wrapper for base type's method and MyClass.M1 a wrapper for this type's method.
        '''
        ''' And if the type does not override a virtual method M1, both MyBase.M1
        ''' and MyClass.M1 will use a wrapper for base type's method.
        ''' </summary>
        Private _methodWrappers As Dictionary(Of MethodSymbol, MethodSymbol) = Nothing
 
        Private _initializeComponentCallTree As Dictionary(Of MethodSymbol, ImmutableArray(Of MethodSymbol)) = Nothing
 
        Public Sub New(compilation As VisualBasicCompilation, moduleBuilderOpt As PEModuleBuilder, initializeComponentOpt As MethodSymbol)
            Me.Compilation = compilation
            Me.ModuleBuilderOpt = moduleBuilderOpt
            Me.InitializeComponentOpt = initializeComponentOpt
        End Sub
 
        ''' <summary>
        ''' Is there any content in the methods collection.
        ''' </summary>
        Public ReadOnly Property HasSynthesizedMethods As Boolean
            Get
                Return _synthesizedMethods IsNot Nothing
            End Get
        End Property
 
        ''' <summary> Method created with their bodies </summary>
        Public ReadOnly Property SynthesizedMethods As ArrayBuilder(Of MethodWithBody)
            Get
                Return _synthesizedMethods
            End Get
        End Property
 
        Public Sub AddSynthesizedMethod(method As MethodSymbol,
                                        body As BoundStatement,
                                        stateMachineType As StateMachineTypeSymbol,
                                        stateMachineStatesDebugInfo As ImmutableArray(Of StateMachineStateDebugInfo))
            If _synthesizedMethods Is Nothing Then
                _synthesizedMethods = ArrayBuilder(Of MethodWithBody).GetInstance()
            End If
 
            _synthesizedMethods.Add(New MethodWithBody(method, body, stateMachineType, stateMachineStatesDebugInfo))
        End Sub
 
        Public Function HasMethodWrapper(method As MethodSymbol) As Boolean
            Return _methodWrappers IsNot Nothing AndAlso _methodWrappers.ContainsKey(method)
        End Function
 
        Public Sub AddMethodWrapper(method As MethodSymbol, wrapper As MethodSymbol, body As BoundStatement)
            If _methodWrappers Is Nothing Then
                _methodWrappers = New Dictionary(Of MethodSymbol, MethodSymbol)()
            End If
 
            _methodWrappers(method) = wrapper
            AddSynthesizedMethod(wrapper, body, stateMachineType:=Nothing, ImmutableArray(Of StateMachineStateDebugInfo).Empty)
        End Sub
 
        Public Function GetMethodWrapper(method As MethodSymbol) As MethodSymbol
            Dim wrapper As MethodSymbol = Nothing
            Return If(_methodWrappers IsNot Nothing AndAlso _methodWrappers.TryGetValue(method, wrapper), wrapper, Nothing)
        End Function
 
        ''' <summary> Free resources </summary>
        Public Sub Free()
            If Me._synthesizedMethods IsNot Nothing Then
                Me._synthesizedMethods.Free()
                Me._synthesizedMethods = Nothing
            End If
 
            If _methodWrappers IsNot Nothing Then
                _methodWrappers = Nothing
            End If
 
        End Sub
 
        Public Sub AddToInitializeComponentCallTree(method As MethodSymbol, callees As ImmutableArray(Of MethodSymbol))
#If DEBUG Then
            Debug.Assert(method.IsDefinition)
            For Each m In callees
                Debug.Assert(m.IsDefinition)
            Next
#End If
 
            If _initializeComponentCallTree Is Nothing Then
                _initializeComponentCallTree = New Dictionary(Of MethodSymbol, ImmutableArray(Of MethodSymbol))(ReferenceEqualityComparer.Instance)
            End If
 
            _initializeComponentCallTree.Add(method, callees)
        End Sub
 
        Public Function CallsInitializeComponent(method As MethodSymbol) As Boolean
            Debug.Assert(method.IsDefinition)
 
            If _initializeComponentCallTree Is Nothing Then
                Return False
            End If
 
            Return CallsInitializeComponent(method, New HashSet(Of MethodSymbol)(ReferenceEqualityComparer.Instance))
        End Function
 
        Private Function CallsInitializeComponent(method As MethodSymbol, visited As HashSet(Of MethodSymbol)) As Boolean
            Dim added = visited.Add(method)
            Debug.Assert(added)
 
            Dim callees As ImmutableArray(Of MethodSymbol) = Nothing
 
            If _initializeComponentCallTree.TryGetValue(method, callees) Then
                For Each m In callees
                    If m Is InitializeComponentOpt Then
                        Return True
                    ElseIf Not visited.Contains(m) AndAlso CallsInitializeComponent(m, visited) Then
                        Return True
                    End If
                Next
            End If
 
            Return False
        End Function
 
    End Class
 
End Namespace