File: CodeGen\MethodBody.cs
Web Access
Project: src\src\Compilers\Core\Portable\Microsoft.CodeAnalysis.csproj (Microsoft.CodeAnalysis)
// 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.
 
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.Debugging;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.PooledObjects;
 
namespace Microsoft.CodeAnalysis.CodeGen
{
    /// <summary>
    /// Holds on to the method body data.
    /// </summary>
    internal sealed class MethodBody : Cci.IMethodBody
    {
        private readonly Cci.IMethodDefinition _parent;
 
        private readonly ImmutableArray<byte> _ilBits;
        private readonly ushort _maxStack;
        private readonly ImmutableArray<Cci.ILocalDefinition> _locals;
        private readonly ImmutableArray<Cci.ExceptionHandlerRegion> _exceptionHandlers;
        private readonly bool _areLocalsZeroed;
 
        // Debug information emitted to Release & Debug PDBs supporting the debugger, EEs and other tools:
        private readonly ImmutableArray<Cci.SequencePoint> _sequencePoints;
        private readonly ImmutableArray<Cci.LocalScope> _localScopes;
        private readonly Cci.IImportScope _importScopeOpt;
        private readonly string _stateMachineTypeNameOpt;
        private readonly ImmutableArray<StateMachineHoistedLocalScope> _stateMachineHoistedLocalScopes;
        private readonly bool _hasDynamicLocalVariables;
        private readonly StateMachineMoveNextBodyDebugInfo _stateMachineMoveNextDebugInfoOpt;
 
        // Debug information emitted to Debug PDBs supporting EnC:
        private readonly DebugId _methodId;
        private readonly ImmutableArray<EncHoistedLocalInfo> _stateMachineHoistedLocalSlots;
        private readonly ImmutableArray<EncLambdaInfo> _lambdaDebugInfo;
        private readonly ImmutableArray<LambdaRuntimeRudeEditInfo> _orderedLambdaRuntimeRudeEdits;
        private readonly ImmutableArray<EncClosureInfo> _closureDebugInfo;
        private readonly StateMachineStatesDebugInfo _stateMachineStatesDebugInfo;
 
        // Data used when emitting EnC delta:
        private readonly ImmutableArray<Cci.ITypeReference?> _stateMachineAwaiterSlots;
 
        // Data used when emitting Dynamic Analysis resource generated by code coverage instrumentation. Empty if not applicable.
        private readonly ImmutableArray<SourceSpan> _codeCoverageSpans;
 
        private readonly bool _isPrimaryConstructor;
 
        public MethodBody(
            ImmutableArray<byte> ilBits,
            ushort maxStack,
            Cci.IMethodDefinition parent,
            DebugId methodId,
            ImmutableArray<Cci.ILocalDefinition> locals,
            SequencePointList sequencePoints,
            DebugDocumentProvider debugDocumentProvider,
            ImmutableArray<Cci.ExceptionHandlerRegion> exceptionHandlers,
            bool areLocalsZeroed,
            bool hasStackalloc,
            ImmutableArray<Cci.LocalScope> localScopes,
            bool hasDynamicLocalVariables,
            Cci.IImportScope importScopeOpt,
            ImmutableArray<EncLambdaInfo> lambdaDebugInfo,
            ImmutableArray<LambdaRuntimeRudeEditInfo> orderedLambdaRuntimeRudeEdits,
            ImmutableArray<EncClosureInfo> closureDebugInfo,
            string stateMachineTypeNameOpt,
            ImmutableArray<StateMachineHoistedLocalScope> stateMachineHoistedLocalScopes,
            ImmutableArray<EncHoistedLocalInfo> stateMachineHoistedLocalSlots,
            ImmutableArray<Cci.ITypeReference?> stateMachineAwaiterSlots,
            StateMachineStatesDebugInfo stateMachineStatesDebugInfo,
            StateMachineMoveNextBodyDebugInfo stateMachineMoveNextDebugInfoOpt,
            ImmutableArray<SourceSpan> codeCoverageSpans,
            bool isPrimaryConstructor)
        {
            Debug.Assert(!locals.IsDefault);
            Debug.Assert(!exceptionHandlers.IsDefault);
            Debug.Assert(!localScopes.IsDefault);
 
            _ilBits = ilBits;
            _maxStack = maxStack;
            _parent = parent;
            _methodId = methodId;
            _locals = locals;
            _exceptionHandlers = exceptionHandlers;
            _areLocalsZeroed = areLocalsZeroed;
            HasStackalloc = hasStackalloc;
            _localScopes = localScopes;
            _hasDynamicLocalVariables = hasDynamicLocalVariables;
            _importScopeOpt = importScopeOpt;
            _lambdaDebugInfo = lambdaDebugInfo;
            _orderedLambdaRuntimeRudeEdits = orderedLambdaRuntimeRudeEdits;
            _closureDebugInfo = closureDebugInfo;
            _stateMachineTypeNameOpt = stateMachineTypeNameOpt;
            _stateMachineHoistedLocalScopes = stateMachineHoistedLocalScopes;
            _stateMachineHoistedLocalSlots = stateMachineHoistedLocalSlots;
            _stateMachineAwaiterSlots = stateMachineAwaiterSlots;
            _stateMachineStatesDebugInfo = stateMachineStatesDebugInfo;
            _stateMachineMoveNextDebugInfoOpt = stateMachineMoveNextDebugInfoOpt;
            _codeCoverageSpans = codeCoverageSpans;
            _sequencePoints = GetSequencePoints(sequencePoints, debugDocumentProvider);
            _isPrimaryConstructor = isPrimaryConstructor;
        }
 
        private static ImmutableArray<Cci.SequencePoint> GetSequencePoints(SequencePointList? sequencePoints, DebugDocumentProvider debugDocumentProvider)
        {
            if (sequencePoints == null || sequencePoints.IsEmpty)
            {
                return ImmutableArray<Cci.SequencePoint>.Empty;
            }
 
            var sequencePointsBuilder = ArrayBuilder<Cci.SequencePoint>.GetInstance();
            sequencePoints.GetSequencePoints(debugDocumentProvider, sequencePointsBuilder);
            return sequencePointsBuilder.ToImmutableAndFree();
        }
 
        ImmutableArray<SourceSpan> Cci.IMethodBody.CodeCoverageSpans => _codeCoverageSpans;
 
        ImmutableArray<Cci.ExceptionHandlerRegion> Cci.IMethodBody.ExceptionRegions => _exceptionHandlers;
 
        bool Cci.IMethodBody.AreLocalsZeroed => _areLocalsZeroed;
 
        ImmutableArray<Cci.ILocalDefinition> Cci.IMethodBody.LocalVariables => _locals;
 
        Cci.IMethodDefinition Cci.IMethodBody.MethodDefinition => _parent;
 
        StateMachineMoveNextBodyDebugInfo Cci.IMethodBody.MoveNextBodyInfo => _stateMachineMoveNextDebugInfoOpt;
 
        ushort Cci.IMethodBody.MaxStack => _maxStack;
 
        public ImmutableArray<byte> IL => _ilBits;
 
        public ImmutableArray<Cci.SequencePoint> SequencePoints => _sequencePoints;
 
        ImmutableArray<Cci.LocalScope> Cci.IMethodBody.LocalScopes => _localScopes;
 
        /// <summary>
        /// This is a list of the using directives that were in scope for this method body.
        /// </summary>
        Cci.IImportScope Cci.IMethodBody.ImportScope => _importScopeOpt;
 
        string Cci.IMethodBody.StateMachineTypeName => _stateMachineTypeNameOpt;
 
        ImmutableArray<StateMachineHoistedLocalScope> Cci.IMethodBody.StateMachineHoistedLocalScopes
            => _stateMachineHoistedLocalScopes;
 
        ImmutableArray<EncHoistedLocalInfo> Cci.IMethodBody.StateMachineHoistedLocalSlots
            => _stateMachineHoistedLocalSlots;
 
        ImmutableArray<Cci.ITypeReference?> Cci.IMethodBody.StateMachineAwaiterSlots
            => _stateMachineAwaiterSlots;
 
        bool Cci.IMethodBody.HasDynamicLocalVariables => _hasDynamicLocalVariables;
 
        public DebugId MethodId => _methodId;
 
        public ImmutableArray<EncLambdaInfo> LambdaDebugInfo => _lambdaDebugInfo;
 
        /// <summary>
        /// Ordered by <see cref="LambdaRuntimeRudeEditInfo.LambdaId"/>.
        /// </summary>
        public ImmutableArray<LambdaRuntimeRudeEditInfo> OrderedLambdaRuntimeRudeEdits => _orderedLambdaRuntimeRudeEdits;
 
        public ImmutableArray<EncClosureInfo> ClosureDebugInfo => _closureDebugInfo;
 
        public StateMachineStatesDebugInfo StateMachineStatesDebugInfo => _stateMachineStatesDebugInfo;
 
        /// <summary>
        /// True if there's a stackalloc somewhere in the method.
        /// </summary>
        public bool HasStackalloc { get; }
 
        public bool IsPrimaryConstructor => _isPrimaryConstructor;
    }
}