示例#1
0
        internal void SetPEEntryPoint(IMethodSymbolInternal method, DiagnosticBag diagnostics)
        {
            Debug.Assert(method == null || IsSourceDefinition(method));
            Debug.Assert(OutputKind.IsApplication());

            PEEntryPoint = Translate(method, diagnostics, needDeclaration: true);
        }
示例#2
0
 internal sealed override Cci.IMethodReference Translate(
     IMethodSymbolInternal symbol,
     DiagnosticBag diagnostics,
     bool needDeclaration
     )
 {
     return(Translate((TMethodSymbol)symbol, diagnostics, needDeclaration));
 }
示例#3
0
 private void ReportMissingStateMachineAttribute(DiagnosticBag diagnostics, IMethodSymbolInternal method, string stateMachineAttributeFullName)
 {
     diagnostics.Add(MessageProvider.CreateDiagnostic(
                         MessageProvider.ERR_EncUpdateFailedMissingAttribute,
                         method.Locations.First(),
                         MessageProvider.GetErrorDisplayString(method.GetISymbol()),
                         stateMachineAttributeFullName));
 }
示例#4
0
 public MappedMethod(
     IMethodSymbolInternal previousMethod,
     Func <SyntaxNode, SyntaxNode?>?syntaxMap
     )
 {
     PreviousMethod = previousMethod;
     SyntaxMap      = syntaxMap;
 }
示例#5
0
        private static string GetMethodName(IMethodSymbolInternal methodSymbol)
        {
            IMethodSymbol iMethod = (IMethodSymbol)methodSymbol.GetISymbol();
            var           format  = (iMethod.MethodKind == MethodKind.UserDefinedOperator) ?
                                    _testDataOperatorKeyFormat :
                                    _testDataKeyFormat;

            return(iMethod.ToDisplayString(format));
        }
示例#6
0
        public void SetMethodBody(IMethodSymbolInternal methodSymbol, Cci.IMethodBody body)
        {
            Debug.Assert(methodSymbol.ContainingModule == CommonSourceModule);
            Debug.Assert(methodSymbol.IsDefinition);
            Debug.Assert(((IMethodSymbol)methodSymbol.GetISymbol()).PartialDefinitionPart == null); // Must be definition.
            Debug.Assert(body == null || (object)methodSymbol == body.MethodDefinition);

            _methodBodyMap.Add(methodSymbol, body);
        }
        public EncVariableSlotAllocator(
            SymbolMatcher symbolMap,
            Func <SyntaxNode, SyntaxNode?>?syntaxMap,
            IMethodSymbolInternal previousTopLevelMethod,
            DebugId methodId,
            ImmutableArray <EncLocalInfo> previousLocals,
            IReadOnlyDictionary <int, KeyValuePair <DebugId, int> >?lambdaMap,
            IReadOnlyDictionary <int, DebugId>?closureMap,
            string?stateMachineTypeName,
            int hoistedLocalSlotCount,
            IReadOnlyDictionary <EncHoistedLocalInfo, int>?hoistedLocalSlots,
            int awaiterCount,
            IReadOnlyDictionary <Cci.ITypeReference, int>?awaiterMap,
            IReadOnlyDictionary <int, int>?stateMachineStateMap,
            int?firstUnusedIncreasingStateMachineState,
            int?firstUnusedDecreasingStateMachineState,
            LambdaSyntaxFacts lambdaSyntaxFacts)
        {
            Debug.Assert(!previousLocals.IsDefault);

            _symbolMap              = symbolMap;
            _syntaxMap              = syntaxMap;
            _previousLocals         = previousLocals;
            _previousTopLevelMethod = previousTopLevelMethod;
            _methodId              = methodId;
            _hoistedLocalSlots     = hoistedLocalSlots;
            _hoistedLocalSlotCount = hoistedLocalSlotCount;
            _stateMachineTypeName  = stateMachineTypeName;
            _awaiterCount          = awaiterCount;
            _awaiterMap            = awaiterMap;
            _stateMachineStateMap  = stateMachineStateMap;
            _lambdaMap             = lambdaMap;
            _closureMap            = closureMap;
            _lambdaSyntaxFacts     = lambdaSyntaxFacts;
            _firstUnusedIncreasingStateMachineState = firstUnusedIncreasingStateMachineState;
            _firstUnusedDecreasingStateMachineState = firstUnusedDecreasingStateMachineState;

            // Create a map from local info to slot.
            var previousLocalInfoToSlot = new Dictionary <EncLocalInfo, int>();

            for (int slot = 0; slot < previousLocals.Length; slot++)
            {
                var localInfo = previousLocals[slot];
                Debug.Assert(!localInfo.IsDefault);
                if (localInfo.IsUnused)
                {
                    // Unrecognized or deleted local.
                    continue;
                }

                previousLocalInfoToSlot.Add(localInfo, slot);
            }

            _previousLocalSlots = previousLocalInfoToSlot;
        }
        private readonly IReadOnlyDictionary <int, DebugId> _closureMapOpt;                     // SyntaxOffset -> Id

        public EncVariableSlotAllocator(
            CommonMessageProvider messageProvider,
            SymbolMatcher symbolMap,
            Func <SyntaxNode, SyntaxNode> syntaxMapOpt,
            IMethodSymbolInternal previousTopLevelMethod,
            DebugId methodId,
            ImmutableArray <EncLocalInfo> previousLocals,
            IReadOnlyDictionary <int, KeyValuePair <DebugId, int> > lambdaMapOpt,
            IReadOnlyDictionary <int, DebugId> closureMapOpt,
            string stateMachineTypeNameOpt,
            int hoistedLocalSlotCount,
            IReadOnlyDictionary <EncHoistedLocalInfo, int> hoistedLocalSlotsOpt,
            int awaiterCount,
            IReadOnlyDictionary <Cci.ITypeReference, int> awaiterMapOpt)
        {
            Debug.Assert(messageProvider != null);
            Debug.Assert(symbolMap != null);
            Debug.Assert(previousTopLevelMethod != null);
            Debug.Assert(!previousLocals.IsDefault);

            _messageProvider        = messageProvider;
            _symbolMap              = symbolMap;
            _syntaxMapOpt           = syntaxMapOpt;
            _previousLocals         = previousLocals;
            _previousTopLevelMethod = previousTopLevelMethod;
            _methodId                = methodId;
            _hoistedLocalSlotsOpt    = hoistedLocalSlotsOpt;
            _hoistedLocalSlotCount   = hoistedLocalSlotCount;
            _stateMachineTypeNameOpt = stateMachineTypeNameOpt;
            _awaiterCount            = awaiterCount;
            _awaiterMapOpt           = awaiterMapOpt;
            _lambdaMapOpt            = lambdaMapOpt;
            _closureMapOpt           = closureMapOpt;

            // Create a map from local info to slot.
            var previousLocalInfoToSlot = new Dictionary <EncLocalInfo, int>();

            for (int slot = 0; slot < previousLocals.Length; slot++)
            {
                var localInfo = previousLocals[slot];
                Debug.Assert(!localInfo.IsDefault);
                if (localInfo.IsUnused)
                {
                    // Unrecognized or deleted local.
                    continue;
                }

                previousLocalInfoToSlot.Add(localInfo, slot);
            }

            _previousLocalSlots = previousLocalInfoToSlot;
        }
示例#9
0
        public EncVariableSlotAllocator(
            CommonMessageProvider messageProvider,
            SymbolMatcher symbolMap,
            Func<SyntaxNode, SyntaxNode> syntaxMapOpt,
            IMethodSymbolInternal previousTopLevelMethod,
            DebugId methodId,
            ImmutableArray<EncLocalInfo> previousLocals,
            IReadOnlyDictionary<int, KeyValuePair<DebugId, int>> lambdaMapOpt,
            IReadOnlyDictionary<int, DebugId> closureMapOpt,
            string stateMachineTypeNameOpt,
            int hoistedLocalSlotCount,
            IReadOnlyDictionary<EncHoistedLocalInfo, int> hoistedLocalSlotsOpt,
            int awaiterCount,
            IReadOnlyDictionary<Cci.ITypeReference, int> awaiterMapOpt)
        {
            Debug.Assert(messageProvider != null);
            Debug.Assert(symbolMap != null);
            Debug.Assert(previousTopLevelMethod != null);
            Debug.Assert(!previousLocals.IsDefault);

            _messageProvider = messageProvider;
            _symbolMap = symbolMap;
            _syntaxMapOpt = syntaxMapOpt;
            _previousLocals = previousLocals;
            _previousTopLevelMethod = previousTopLevelMethod;
            _methodId = methodId;
            _hoistedLocalSlotsOpt = hoistedLocalSlotsOpt;
            _hoistedLocalSlotCount = hoistedLocalSlotCount;
            _stateMachineTypeNameOpt = stateMachineTypeNameOpt;
            _awaiterCount = awaiterCount;
            _awaiterMapOpt = awaiterMapOpt;
            _lambdaMapOpt = lambdaMapOpt;
            _closureMapOpt = closureMapOpt;

            // Create a map from local info to slot.
            var previousLocalInfoToSlot = new Dictionary<EncLocalInfo, int>();
            for (int slot = 0; slot < previousLocals.Length; slot++)
            {
                var localInfo = previousLocals[slot];
                Debug.Assert(!localInfo.IsDefault);
                if (localInfo.IsUnused)
                {
                    // Unrecognized or deleted local.
                    continue;
                }

                previousLocalInfoToSlot.Add(localInfo, slot);
            }

            _previousLocalSlots = previousLocalInfoToSlot;
        }
示例#10
0
        internal Cci.IMethodBody GetMethodBody(IMethodSymbolInternal methodSymbol)
        {
            Debug.Assert(methodSymbol.ContainingModule == CommonSourceModule);
            Debug.Assert(methodSymbol.IsDefinition);
            Debug.Assert(((IMethodSymbol)methodSymbol.GetISymbol()).PartialDefinitionPart == null); // Must be definition.

            Cci.IMethodBody body;

            if (_methodBodyMap.TryGetValue(methodSymbol, out body))
            {
                return(body);
            }

            return(null);
        }
示例#11
0
 public MappedMethod(IMethodSymbolInternal previousMethodOpt, Func<SyntaxNode, SyntaxNode> syntaxMap)
 {
     this.PreviousMethod = previousMethodOpt;
     this.SyntaxMap = syntaxMap;
 }
示例#12
0
 public MethodUpdate(IMethodSymbolInternal previousMethod, bool preserveLocalVariables, Func <SyntaxNode, SyntaxNode> syntaxMap)
 {
     this.PreviousMethod         = previousMethod;
     this.PreserveLocalVariables = preserveLocalVariables;
     this.SyntaxMap = syntaxMap;
 }
示例#13
0
 public MethodUpdate(IMethodSymbolInternal previousMethod, bool preserveLocalVariables, Func<SyntaxNode, SyntaxNode> syntaxMap)
 {
     this.PreviousMethod = previousMethod;
     this.PreserveLocalVariables = preserveLocalVariables;
     this.SyntaxMap = syntaxMap;
 }
示例#14
0
 public MappedMethod(IMethodSymbolInternal previousMethodOpt, Func <SyntaxNode, SyntaxNode> syntaxMap)
 {
     this.PreviousMethod = previousMethodOpt;
     this.SyntaxMap      = syntaxMap;
 }
示例#15
0
 public MethodData(ILBuilder ilBuilder, IMethodSymbolInternal method)
 {
     this.ILBuilder = ilBuilder;
     this.Method    = method;
 }
示例#16
0
 private bool IsSourceDefinition(IMethodSymbolInternal method)
 {
     return(method.ContainingModule == CommonSourceModule && method.IsDefinition);
 }
示例#17
0
        internal VariableSlotAllocator?TryCreateVariableSlotAllocator(EmitBaseline baseline, Compilation compilation, IMethodSymbolInternal method, IMethodSymbolInternal topLevelMethod, DiagnosticBag diagnostics)
        {
            // Top-level methods are always included in the semantic edit list. Lambda methods are not.
            if (!mappedMethods.TryGetValue(topLevelMethod, out var mappedMethod))
            {
                return(null);
            }

            // TODO (bug https://github.com/dotnet/roslyn/issues/2504):
            // Handle cases when the previous method doesn't exist.

            if (!TryGetMethodHandle(baseline, (Cci.IMethodDefinition)method.GetCciAdapter(), out var previousHandle))
            {
                // Unrecognized method. Must have been added in the current compilation.
                return(null);
            }

            ImmutableArray <EncLocalInfo> previousLocals;
            IReadOnlyDictionary <EncHoistedLocalInfo, int>?         hoistedLocalMap = null;
            IReadOnlyDictionary <Cci.ITypeReference, int>?          awaiterMap      = null;
            IReadOnlyDictionary <int, KeyValuePair <DebugId, int> >?lambdaMap       = null;
            IReadOnlyDictionary <int, DebugId>?closureMap           = null;
            IReadOnlyDictionary <int, int>?    stateMachineStateMap = null;
            int?firstUnusedIncreasingStateMachineState = null;
            int?firstUnusedDecreasingStateMachineState = null;

            int           hoistedLocalSlotCount = 0;
            int           awaiterSlotCount      = 0;
            string?       stateMachineTypeName  = null;
            SymbolMatcher symbolMap;

            int     methodIndex = MetadataTokens.GetRowNumber(previousHandle);
            DebugId methodId;

            // Check if method has changed previously. If so, we already have a map.
            if (baseline.AddedOrChangedMethods.TryGetValue(methodIndex, out var addedOrChangedMethod))
            {
                methodId = addedOrChangedMethod.MethodId;

                MakeLambdaAndClosureMaps(addedOrChangedMethod.LambdaDebugInfo, addedOrChangedMethod.ClosureDebugInfo, out lambdaMap, out closureMap);
                MakeStateMachineStateMap(addedOrChangedMethod.StateMachineStates.States, out stateMachineStateMap);

                firstUnusedIncreasingStateMachineState = addedOrChangedMethod.StateMachineStates.FirstUnusedIncreasingStateMachineState;
                firstUnusedDecreasingStateMachineState = addedOrChangedMethod.StateMachineStates.FirstUnusedDecreasingStateMachineState;

                if (addedOrChangedMethod.StateMachineTypeName != null)
                {
                    // method is async/iterator kickoff method
                    GetStateMachineFieldMapFromPreviousCompilation(
                        addedOrChangedMethod.StateMachineHoistedLocalSlotsOpt,
                        addedOrChangedMethod.StateMachineAwaiterSlotsOpt,
                        out hoistedLocalMap,
                        out awaiterMap);

                    hoistedLocalSlotCount = addedOrChangedMethod.StateMachineHoistedLocalSlotsOpt.Length;
                    awaiterSlotCount      = addedOrChangedMethod.StateMachineAwaiterSlotsOpt.Length;

                    // Kickoff method has no interesting locals on its own.
                    // We use the EnC method debug information for hoisted locals.
                    previousLocals = ImmutableArray <EncLocalInfo> .Empty;

                    stateMachineTypeName = addedOrChangedMethod.StateMachineTypeName;
                }
                else
                {
                    previousLocals = addedOrChangedMethod.Locals;
                }

                // All types that AddedOrChangedMethodInfo refers to have been mapped to the previous generation.
                // Therefore we don't need to fall back to metadata if we don't find the type reference, like we do in DefinitionMap.MapReference.
                symbolMap = MapToPreviousSymbolMatcher;
            }
            else
            {
                // Method has not changed since initial generation. Generate a map
                // using the local names provided with the initial metadata.
                EditAndContinueMethodDebugInformation debugInfo;
                StandaloneSignatureHandle             localSignature;
                try
                {
                    debugInfo      = baseline.DebugInformationProvider(previousHandle);
                    localSignature = baseline.LocalSignatureProvider(previousHandle);
                }
                catch (Exception e) when(e is InvalidDataException || e is IOException)
                {
                    diagnostics.Add(MessageProvider.CreateDiagnostic(
                                        MessageProvider.ERR_InvalidDebugInfo,
                                        method.Locations.First(),
                                        method,
                                        MetadataTokens.GetToken(previousHandle),
                                        method.ContainingAssembly
                                        ));

                    return(null);
                }

                methodId = new DebugId(debugInfo.MethodOrdinal, 0);

                if (!debugInfo.Lambdas.IsDefaultOrEmpty)
                {
                    MakeLambdaAndClosureMaps(debugInfo.Lambdas, debugInfo.Closures, out lambdaMap, out closureMap);
                }

                MakeStateMachineStateMap(debugInfo.StateMachineStates, out stateMachineStateMap);

                if (!debugInfo.StateMachineStates.IsDefaultOrEmpty)
                {
                    firstUnusedIncreasingStateMachineState = debugInfo.StateMachineStates.Max(s => s.StateNumber) + 1;
                    firstUnusedDecreasingStateMachineState = debugInfo.StateMachineStates.Min(s => s.StateNumber) - 1;
                }

                ITypeSymbolInternal?stateMachineType = TryGetStateMachineType(previousHandle);
                if (stateMachineType != null)
                {
                    // method is async/iterator kickoff method
                    var localSlotDebugInfo = debugInfo.LocalSlots.NullToEmpty();
                    GetStateMachineFieldMapFromMetadata(stateMachineType, localSlotDebugInfo, out hoistedLocalMap, out awaiterMap, out awaiterSlotCount);
                    hoistedLocalSlotCount = localSlotDebugInfo.Length;

                    // Kickoff method has no interesting locals on its own.
                    // We use the EnC method debug information for hoisted locals.
                    previousLocals = ImmutableArray <EncLocalInfo> .Empty;

                    stateMachineTypeName = stateMachineType.Name;
                }
                else
                {
                    // If the current method is async/iterator then either the previous method wasn't declared as async/iterator and it's updated to be one,
                    // or it was but is not marked by the corresponding state machine attribute because it was missing in the compilation.
                    // In the later case we need to report an error since we don't known how to map to the previous state machine.

                    // The IDE already checked that the attribute type is present in the base compilation, but didn't validate that it is well-formed.
                    // We don't have the base compilation to directly query for the attribute, only the source compilation.
                    // But since constructor signatures can't be updated during EnC we can just check the current compilation.

                    if (method.IsAsync)
                    {
                        if (compilation.CommonGetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_AsyncStateMachineAttribute__ctor) == null)
                        {
                            ReportMissingStateMachineAttribute(diagnostics, method, AttributeDescription.AsyncStateMachineAttribute.FullName);
                            return(null);
                        }
                    }
                    else if (method.IsIterator)
                    {
                        if (compilation.CommonGetWellKnownTypeMember(WellKnownMember.System_Runtime_CompilerServices_IteratorStateMachineAttribute__ctor) == null)
                        {
                            ReportMissingStateMachineAttribute(diagnostics, method, AttributeDescription.IteratorStateMachineAttribute.FullName);
                            return(null);
                        }
                    }

                    try
                    {
                        previousLocals = localSignature.IsNil ? ImmutableArray <EncLocalInfo> .Empty :
                                         GetLocalSlotMapFromMetadata(localSignature, debugInfo);
                    }
                    catch (Exception e) when(e is UnsupportedSignatureContent || e is BadImageFormatException || e is IOException)
                    {
                        diagnostics.Add(MessageProvider.CreateDiagnostic(
                                            MessageProvider.ERR_InvalidDebugInfo,
                                            method.Locations.First(),
                                            method,
                                            MetadataTokens.GetToken(localSignature),
                                            method.ContainingAssembly
                                            ));

                        return(null);
                    }
                }

                symbolMap = MapToMetadataSymbolMatcher;
            }

            return(new EncVariableSlotAllocator(
                       symbolMap,
                       mappedMethod.SyntaxMap,
                       mappedMethod.PreviousMethod,
                       methodId,
                       previousLocals,
                       lambdaMap,
                       closureMap,
                       stateMachineTypeName,
                       hoistedLocalSlotCount,
                       hoistedLocalMap,
                       awaiterSlotCount,
                       awaiterMap,
                       stateMachineStateMap,
                       firstUnusedIncreasingStateMachineState,
                       firstUnusedDecreasingStateMachineState,
                       GetLambdaSyntaxFacts()));
        }
示例#18
0
 internal void SetMethodTestData(IMethodSymbolInternal method, ILBuilder builder)
 {
     TestData.Add(method, new CompilationTestData.MethodData(builder, method));
 }
示例#19
0
 internal abstract Cci.IMethodReference Translate(IMethodSymbolInternal symbol, DiagnosticBag diagnostics, bool needDeclaration);