Esempio n. 1
0
        private static EncHoistedLocalInfo MapHoistedLocalSlot(EncHoistedLocalInfo info, SymbolMatcher map)
        {
            if (info.IsUnused)
            {
                return info;
            }

            return new EncHoistedLocalInfo(info.SlotInfo, map.MapReference(info.Type));
        }
Esempio n. 2
0
        protected override void GetStateMachineFieldMapFromMetadata(
            ITypeSymbol stateMachineType,
            ImmutableArray <LocalSlotDebugInfo> localSlotDebugInfo,
            out IReadOnlyDictionary <EncHoistedLocalInfo, int> hoistedLocalMap,
            out IReadOnlyDictionary <Cci.ITypeReference, int> awaiterMap,
            out int awaiterSlotCount)
        {
            // we are working with PE symbols
            Debug.Assert(stateMachineType.ContainingAssembly is PEAssemblySymbol);

            var hoistedLocals       = new Dictionary <EncHoistedLocalInfo, int>();
            var awaiters            = new Dictionary <Cci.ITypeReference, int>();
            int maxAwaiterSlotIndex = -1;

            foreach (var member in stateMachineType.GetMembers())
            {
                if (member.Kind == SymbolKind.Field)
                {
                    string name = member.Name;
                    int    slotIndex;

                    switch (GeneratedNames.GetKind(name))
                    {
                    case GeneratedNameKind.AwaiterField:
                        if (GeneratedNames.TryParseSlotIndex(name, out slotIndex))
                        {
                            var field = (IFieldSymbol)member;

                            // correct metadata won't contain duplicates, but malformed might, ignore the duplicate:
                            awaiters[(Cci.ITypeReference)field.Type] = slotIndex;

                            if (slotIndex > maxAwaiterSlotIndex)
                            {
                                maxAwaiterSlotIndex = slotIndex;
                            }
                        }

                        break;

                    case GeneratedNameKind.HoistedLocalField:
                    case GeneratedNameKind.HoistedSynthesizedLocalField:
                        if (GeneratedNames.TryParseSlotIndex(name, out slotIndex))
                        {
                            var field = (IFieldSymbol)member;
                            if (slotIndex >= localSlotDebugInfo.Length)
                            {
                                // invalid or missing metadata
                                continue;
                            }

                            var key = new EncHoistedLocalInfo(localSlotDebugInfo[slotIndex], (Cci.ITypeReference)field.Type);

                            // correct metadata won't contain duplicate ids, but malformed might, ignore the duplicate:
                            hoistedLocals[key] = slotIndex;
                        }

                        break;
                    }
                }
            }

            hoistedLocalMap  = hoistedLocals;
            awaiterMap       = awaiters;
            awaiterSlotCount = maxAwaiterSlotIndex + 1;
        }
        public override bool TryGetPreviousHoistedLocalSlotIndex(SyntaxNode currentDeclarator, Cci.ITypeReference currentType, SynthesizedLocalKind synthesizedKind, LocalDebugId currentId, out int slotIndex)
        {
            Debug.Assert(_hoistedLocalSlotsOpt != null);

            LocalDebugId previousId;
            if (!TryGetPreviousLocalId(currentDeclarator, currentId, out previousId))
            {
                slotIndex = -1;
                return false;
            }

            var previousType = _symbolMap.MapReference(currentType);
            if (previousType == null)
            {
                slotIndex = -1;
                return false;
            }

            // TODO (bug #781309): Should report a warning if the type of the local has changed
            // and the previous value will be dropped.
            var localKey = new EncHoistedLocalInfo(new LocalSlotDebugInfo(synthesizedKind, previousId), previousType);

            return _hoistedLocalSlotsOpt.TryGetValue(localKey, out slotIndex);
        }
Esempio n. 4
0
        public override bool TryGetPreviousHoistedLocalSlotIndex(
            SyntaxNode currentDeclarator, 
            Cci.ITypeReference currentType,
            SynthesizedLocalKind synthesizedKind,
            LocalDebugId currentId,
            DiagnosticBag diagnostics, 
            out int slotIndex)
        {
            // The previous method was not a state machine (it is allowed to change non-state machine to a state machine):
            if (_hoistedLocalSlotsOpt == null)
            {
                slotIndex = -1;
                return false;
            }

            LocalDebugId previousId;
            if (!TryGetPreviousLocalId(currentDeclarator, currentId, out previousId))
            {
                slotIndex = -1;
                return false;
            }

            var previousType = _symbolMap.MapReference(currentType);
            if (previousType == null)
            {
                slotIndex = -1;
                return false;
            }

            // TODO (bug #781309): Should report a warning if the type of the local has changed
            // and the previous value will be dropped.
            var localKey = new EncHoistedLocalInfo(new LocalSlotDebugInfo(synthesizedKind, previousId), previousType);

            return _hoistedLocalSlotsOpt.TryGetValue(localKey, out slotIndex);
        }
Esempio n. 5
0
        public override bool TryGetPreviousHoistedLocalSlotIndex(
            SyntaxNode currentDeclarator, 
            Cci.ITypeReference currentType,
            SynthesizedLocalKind synthesizedKind,
            LocalDebugId currentId,
            DiagnosticBag diagnostics, 
            out int slotIndex)
        {
            // Well-formed state machine attribute wasn't found in the baseline (the type is missing or bad).
            // Should rarely happen since the IDE reports a rude edit if the attribute type doesn't exist.
            if (_hoistedLocalSlotsOpt == null)
            {
                // TODO: better error message https://github.com/dotnet/roslyn/issues/9196
                diagnostics.Add(_messageProvider.CreateDiagnostic(_messageProvider.ERR_ModuleEmitFailure, NoLocation.Singleton, _previousTopLevelMethod.ContainingModule.Name));
                slotIndex = -1;
                return false;
            }

            LocalDebugId previousId;
            if (!TryGetPreviousLocalId(currentDeclarator, currentId, out previousId))
            {
                slotIndex = -1;
                return false;
            }

            var previousType = _symbolMap.MapReference(currentType);
            if (previousType == null)
            {
                slotIndex = -1;
                return false;
            }

            // TODO (bug #781309): Should report a warning if the type of the local has changed
            // and the previous value will be dropped.
            var localKey = new EncHoistedLocalInfo(new LocalSlotDebugInfo(synthesizedKind, previousId), previousType);

            return _hoistedLocalSlotsOpt.TryGetValue(localKey, out slotIndex);
        }
Esempio n. 6
0
        public override bool TryGetPreviousHoistedLocalSlotIndex(
            SyntaxNode currentDeclarator, 
            Cci.ITypeReference currentType,
            SynthesizedLocalKind synthesizedKind,
            LocalDebugId currentId,
            DiagnosticBag diagnostics, 
            out int slotIndex)
        {
            // Well-formed state machine attribute wasn't found in the baseline (the type is missing or bad).
            // Should rarely happen since the IDE reports a rude edit if the attribute type doesn't exist.
            if (_hoistedLocalSlotsOpt == null)
            {
                ReportMissingStateMachineAttribute(diagnostics);
                slotIndex = -1;
                return false;
            }

            LocalDebugId previousId;
            if (!TryGetPreviousLocalId(currentDeclarator, currentId, out previousId))
            {
                slotIndex = -1;
                return false;
            }

            var previousType = _symbolMap.MapReference(currentType);
            if (previousType == null)
            {
                slotIndex = -1;
                return false;
            }

            // TODO (bug #781309): Should report a warning if the type of the local has changed
            // and the previous value will be dropped.
            var localKey = new EncHoistedLocalInfo(new LocalSlotDebugInfo(synthesizedKind, previousId), previousType);

            return _hoistedLocalSlotsOpt.TryGetValue(localKey, out slotIndex);
        }