Exemplo n.º 1
0
        internal override ImmutableArray <Microsoft.CodeAnalysis.Emit.EncLocalInfo> GetLocalInfo(
            Cci.IMethodDefinition methodDef,
            ImmutableArray <LocalDefinition> localDefs)
        {
            if (localDefs.IsEmpty)
            {
                return(ImmutableArray <Microsoft.CodeAnalysis.Emit.EncLocalInfo> .Empty);
            }

            // Find declarators in current method syntax.
            var declarators = GetLocalVariableDeclaratorsVisitor.GetDeclarators((MethodSymbol)methodDef);

            // Create a map from declarator to declarator index.
            var declaratorToIndex = CreateDeclaratorToIndexMap(declarators);

            return(localDefs.SelectAsArray(localDef => GetLocalInfo(declaratorToIndex, localDef)));
        }
Exemplo n.º 2
0
        internal static ImmutableArray <SyntaxNode> GetDeclarators(MethodSymbol method)
        {
            var syntaxRefs = method.DeclaringSyntaxReferences;

            // No syntax refs for synthesized methods.
            if (syntaxRefs.Length == 0)
            {
                return(ImmutableArray <SyntaxNode> .Empty);
            }

            var syntax  = syntaxRefs[0].GetSyntax();
            var builder = ArrayBuilder <SyntaxNode> .GetInstance();

            var visitor = new GetLocalVariableDeclaratorsVisitor(builder);

            visitor.Visit(syntax);
            return(builder.ToImmutableAndFree());
        }
Exemplo n.º 3
0
        internal override bool TryGetPreviousLocals(
            Microsoft.CodeAnalysis.Emit.EmitBaseline baseline,
            IMethodSymbol method,
            out ImmutableArray <Microsoft.CodeAnalysis.Emit.EncLocalInfo> previousLocals,
            out GetPreviousLocalSlot getPreviousLocalSlot)
        {
            previousLocals       = default(ImmutableArray <Microsoft.CodeAnalysis.Emit.EncLocalInfo>);
            getPreviousLocalSlot = NoPreviousLocalSlot;

            MethodHandle handle;

            if (!this.TryGetMethodHandle(baseline, (Cci.IMethodDefinition)method, out handle))
            {
                // Unrecognized method. Must have been added in the current compilation.
                return(false);
            }

            MethodDefinitionEntry methodEntry;

            if (!this.methodMap.TryGetValue((MethodSymbol)method, out methodEntry))
            {
                // Not part of changeset. No need to preserve locals.
                return(false);
            }

            if (!methodEntry.PreserveLocalVariables)
            {
                // Not necessary to preserve locals.
                return(false);
            }

            var           previousMethod = (MethodSymbol)methodEntry.PreviousMethod;
            var           methodIndex    = (uint)MetadataTokens.GetRowNumber(handle);
            SymbolMatcher map;

            // Check if method has changed previously. If so, we already have a map.
            if (baseline.LocalsForMethodsAddedOrChanged.TryGetValue(methodIndex, out previousLocals))
            {
                map = this.mapToPrevious;
            }
            else
            {
                // Method has not changed since initial generation. Generate a map
                // using the local names provided with the initial metadata.
                var localNames = baseline.LocalNames(methodIndex);
                Debug.Assert(!localNames.IsDefault);

                var localInfo = default(ImmutableArray <MetadataDecoder.LocalInfo>);
                try
                {
                    Debug.Assert(this.module.HasIL);
                    var methodIL = this.module.GetMethodILOrThrow(handle);

                    if (!methodIL.LocalSignature.IsNil)
                    {
                        var signature = this.module.MetadataReader.GetLocalSignature(methodIL.LocalSignature);
                        localInfo = this.metadataDecoder.DecodeLocalSignatureOrThrow(signature);
                    }
                    else
                    {
                        localInfo = ImmutableArray <MetadataDecoder.LocalInfo> .Empty;
                    }
                }
                catch (UnsupportedSignatureContent)
                {
                }
                catch (BadImageFormatException)
                {
                }

                if (localInfo.IsDefault)
                {
                    // TODO: Report error that metadata is not supported.
                    return(false);
                }
                else
                {
                    // The signature may have more locals than names if trailing locals are unnamed.
                    // (Locals in the middle of the signature may be unnamed too but since localNames
                    // is indexed by slot, unnamed locals before the last named local will be represented
                    // as null values in the array.)
                    Debug.Assert(localInfo.Length >= localNames.Length);
                    previousLocals = GetLocalSlots(previousMethod, localNames, localInfo);
                    Debug.Assert(previousLocals.Length == localInfo.Length);
                }

                map = this.mapToMetadata;
            }

            // Find declarators in previous method syntax.
            // The locals are indices into this list.
            var previousDeclarators = GetLocalVariableDeclaratorsVisitor.GetDeclarators(previousMethod);

            // Create a map from declarator to declarator offset.
            var previousDeclaratorToOffset = new Dictionary <SyntaxNode, int>();

            for (int offset = 0; offset < previousDeclarators.Length; offset++)
            {
                previousDeclaratorToOffset.Add(previousDeclarators[offset], offset);
            }

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

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

            var syntaxMap = methodEntry.SyntaxMap;

            if (syntaxMap == null)
            {
                // If there was no syntax map, the syntax structure has not changed,
                // so we can map from current to previous syntax by declarator index.
                Debug.Assert(methodEntry.PreserveLocalVariables);
                // Create a map from declarator to declarator index.
                var currentDeclarators       = GetLocalVariableDeclaratorsVisitor.GetDeclarators((MethodSymbol)method);
                var currentDeclaratorToIndex = CreateDeclaratorToIndexMap(currentDeclarators);
                syntaxMap = currentSyntax =>
                {
                    var currentIndex = currentDeclaratorToIndex[(CSharpSyntaxNode)currentSyntax];
                    return(previousDeclarators[currentIndex]);
                };
            }

            getPreviousLocalSlot = (object identity, Cci.ITypeReference typeRef, LocalSlotConstraints constraints) =>
            {
                var local      = (LocalSymbol)identity;
                var syntaxRefs = local.DeclaringSyntaxReferences;
                Debug.Assert(!syntaxRefs.IsDefault);

                if (!syntaxRefs.IsDefaultOrEmpty)
                {
                    var currentSyntax  = syntaxRefs[0].GetSyntax();
                    var previousSyntax = (CSharpSyntaxNode)syntaxMap(currentSyntax);
                    if (previousSyntax != null)
                    {
                        int offset;
                        if (previousDeclaratorToOffset.TryGetValue(previousSyntax, out offset))
                        {
                            var previousType = map.MapReference(typeRef);
                            if (previousType != null)
                            {
                                var localKey = new Microsoft.CodeAnalysis.Emit.EncLocalInfo(offset, previousType, constraints, (int)local.TempKind);
                                int slot;
                                // Should report a warning if the type of the local has changed
                                // and the previous value will be dropped. (Bug #781309.)
                                if (previousLocalInfoToSlot.TryGetValue(localKey, out slot))
                                {
                                    return(slot);
                                }
                            }
                        }
                    }
                }

                return(-1);
            };
            return(true);
        }
Exemplo n.º 4
0
        internal static ImmutableArray<SyntaxNode> GetDeclarators(MethodSymbol method)
        {
            var syntaxRefs = method.DeclaringSyntaxReferences;
            // No syntax refs for synthesized methods.
            if (syntaxRefs.Length == 0)
            {
                return ImmutableArray<SyntaxNode>.Empty;
            }

            var syntax = syntaxRefs[0].GetSyntax();
            var builder = ArrayBuilder<SyntaxNode>.GetInstance();
            var visitor = new GetLocalVariableDeclaratorsVisitor(builder);
            visitor.Visit(syntax);
            return builder.ToImmutableAndFree();
        }