Beispiel #1
0
        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);
        }
Beispiel #2
0
        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();
        }