public ImmutableSortedSet <int> GetInScopeHoistedLocalIndices(int ilOffset, ref ILSpan methodContextReuseSpan) { if (HoistedLocalScopeRecords.IsDefaultOrEmpty) { return(ImmutableSortedSet <int> .Empty); } methodContextReuseSpan = MethodContextReuseConstraints.CalculateReuseSpan( ilOffset, methodContextReuseSpan, HoistedLocalScopeRecords.Select(record => new ILSpan((uint)record.StartOffset, (uint)(record.StartOffset + record.Length)))); var scopesBuilder = ArrayBuilder <int> .GetInstance(); int i = 0; foreach (var record in HoistedLocalScopeRecords) { var delta = ilOffset - record.StartOffset; if (0 <= delta && delta < record.Length) { scopesBuilder.Add(i); } i++; } var result = scopesBuilder.ToImmutableSortedSet(); scopesBuilder.Free(); return(result); }
public MethodDebugInfo( ImmutableArray <HoistedLocalScopeRecord> hoistedLocalScopeRecords, ImmutableArray <ImmutableArray <ImportRecord> > importRecordGroups, ImmutableArray <ExternAliasRecord> externAliasRecords, ImmutableDictionary <int, ImmutableArray <bool> >?dynamicLocalMap, ImmutableDictionary <int, ImmutableArray <string?> >?tupleLocalMap, string defaultNamespaceName, ImmutableArray <string> localVariableNames, ImmutableArray <TLocalSymbol> localConstants, ILSpan reuseSpan) { RoslynDebug.Assert(!importRecordGroups.IsDefault); RoslynDebug.Assert(!externAliasRecords.IsDefault); RoslynDebug.AssertNotNull(defaultNamespaceName); HoistedLocalScopeRecords = hoistedLocalScopeRecords; ImportRecordGroups = importRecordGroups; ExternAliasRecords = externAliasRecords; DynamicLocalMap = dynamicLocalMap; TupleLocalMap = tupleLocalMap; DefaultNamespaceName = defaultNamespaceName; LocalVariableNames = localVariableNames; LocalConstants = localConstants; ReuseSpan = reuseSpan; }
/// <summary> /// Finds a span of IL containing the specified offset where local variables and imports are guaranteed to be the same. /// Examples: /// scopes: [ [ ) x [ ) ) /// result: [ ) /// /// scopes: [ x [ ) [ ) ) /// result: [ ) /// /// scopes: [ [ x ) [ ) ) /// result: [ ) /// </summary> public static ILSpan CalculateReuseSpan(int ilOffset, ILSpan initialSpan, IEnumerable <ILSpan> scopes) { Debug.Assert(ilOffset >= 0); uint _startOffset = initialSpan.StartOffset; uint _endOffsetExclusive = initialSpan.EndOffsetExclusive; foreach (ILSpan scope in scopes) { if (ilOffset < scope.StartOffset) { _endOffsetExclusive = Math.Min(_endOffsetExclusive, scope.StartOffset); } else if (ilOffset >= scope.EndOffsetExclusive) { _startOffset = Math.Max(_startOffset, scope.EndOffsetExclusive); } else { _startOffset = Math.Max(_startOffset, scope.StartOffset); _endOffsetExclusive = Math.Min(_endOffsetExclusive, scope.EndOffsetExclusive); } } return(new ILSpan(_startOffset, _endOffsetExclusive)); }
internal MethodContextReuseConstraints(Guid moduleVersionId, int methodToken, int methodVersion, ILSpan span) { Debug.Assert(moduleVersionId != default(Guid)); Debug.Assert(MetadataTokens.Handle(methodToken).Kind == HandleKind.MethodDefinition); Debug.Assert(methodVersion >= 1); _moduleVersionId = moduleVersionId; _methodToken = methodToken; _methodVersion = methodVersion; _span = span; }
private static void ReadLocalScopeInformation( MetadataReader reader, MethodDefinitionHandle methodHandle, int ilOffset, EESymbolProvider <TTypeSymbol, TLocalSymbol> symbolProvider, bool isVisualBasicMethod, out ImmutableArray <ImmutableArray <ImportRecord> > importGroups, out ImmutableArray <ExternAliasRecord> externAliases, out ImmutableArray <string> localVariableNames, out ImmutableDictionary <int, ImmutableArray <bool> >?dynamicLocalMap, out ImmutableDictionary <int, ImmutableArray <string?> >?tupleLocalMap, out ImmutableArray <TLocalSymbol> localConstants, out ILSpan reuseSpan ) { var localVariableNamesBuilder = ArrayBuilder <string> .GetInstance(); var localConstantsBuilder = ArrayBuilder <TLocalSymbol> .GetInstance(); ImmutableDictionary <int, ImmutableArray <bool> > .Builder? lazyDynamicLocalsBuilder = null; ImmutableDictionary <int, ImmutableArray <string?> > .Builder?lazyTupleLocalsBuilder = null; var innerMostImportScope = default(ImportScopeHandle); uint reuseSpanStart = 0; uint reuseSpanEnd = uint.MaxValue; try { foreach (var scopeHandle in reader.GetLocalScopes(methodHandle)) { try { var scope = reader.GetLocalScope(scopeHandle); if (ilOffset < scope.StartOffset) { // scopes are sorted by StartOffset, hence all scopes that follow can't contain ilOffset reuseSpanEnd = Math.Min(reuseSpanEnd, (uint)scope.StartOffset); break; } if (ilOffset >= scope.EndOffset) { // ilOffset is not in this scope, go to next one reuseSpanStart = Math.Max(reuseSpanStart, (uint)scope.EndOffset); continue; } // reuse span is a subspan of the inner-most scope containing the IL offset: reuseSpanStart = Math.Max(reuseSpanStart, (uint)scope.StartOffset); reuseSpanEnd = Math.Min(reuseSpanEnd, (uint)scope.EndOffset); // imports (use the inner-most): innerMostImportScope = scope.ImportScope; // locals (from all contained scopes): foreach (var variableHandle in scope.GetLocalVariables()) { var variable = reader.GetLocalVariable(variableHandle); if ((variable.Attributes & LocalVariableAttributes.DebuggerHidden) != 0) { continue; } localVariableNamesBuilder.SetItem( variable.Index, reader.GetString(variable.Name) ); var dynamicFlags = ReadDynamicCustomDebugInformation( reader, variableHandle ); if (!dynamicFlags.IsDefault) { lazyDynamicLocalsBuilder ??= ImmutableDictionary.CreateBuilder < int, ImmutableArray <bool> >(); lazyDynamicLocalsBuilder[variable.Index] = dynamicFlags; } var tupleElementNames = ReadTupleCustomDebugInformation( reader, variableHandle ); if (!tupleElementNames.IsDefault) { lazyTupleLocalsBuilder ??= ImmutableDictionary.CreateBuilder < int, ImmutableArray <string?> >(); lazyTupleLocalsBuilder[variable.Index] = tupleElementNames; } } // constants (from all contained scopes): foreach (var constantHandle in scope.GetLocalConstants()) { var constant = reader.GetLocalConstant(constantHandle); var sigReader = reader.GetBlobReader(constant.Signature); symbolProvider.DecodeLocalConstant( ref sigReader, out var typeSymbol, out var value ); var name = reader.GetString(constant.Name); var dynamicFlags = ReadDynamicCustomDebugInformation( reader, constantHandle ); var tupleElementNames = ReadTupleCustomDebugInformation( reader, constantHandle ); localConstantsBuilder.Add( symbolProvider.GetLocalConstant( name, typeSymbol, value, dynamicFlags, tupleElementNames ) ); } } catch (Exception e) when(e is UnsupportedSignatureContent || e is BadImageFormatException) { // ignore scopes with invalid data } } } finally { localVariableNames = localVariableNamesBuilder.ToImmutableAndFree(); localConstants = localConstantsBuilder.ToImmutableAndFree(); dynamicLocalMap = lazyDynamicLocalsBuilder?.ToImmutable(); tupleLocalMap = lazyTupleLocalsBuilder?.ToImmutable(); reuseSpan = new ILSpan(reuseSpanStart, reuseSpanEnd); } var importGroupsBuilder = ArrayBuilder <ImmutableArray <ImportRecord> > .GetInstance(); var externAliasesBuilder = ArrayBuilder <ExternAliasRecord> .GetInstance(); if (!innerMostImportScope.IsNil) { PopulateImports( reader, innerMostImportScope, symbolProvider, isVisualBasicMethod, importGroupsBuilder, externAliasesBuilder ); } importGroups = importGroupsBuilder.ToImmutableAndFree(); externAliases = externAliasesBuilder.ToImmutableAndFree(); }