private static EncHoistedLocalInfo MapHoistedLocalSlot(EncHoistedLocalInfo info, SymbolMatcher map) { if (info.IsUnused) { return info; } return new EncHoistedLocalInfo(info.SlotInfo, map.MapReference(info.Type)); }
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); }
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); }
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); }
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); }