|
// 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;
}
}
|