Esempio n. 1
0
        public EncLocalSlotManager(ImmutableArray <EncLocalInfo> previousLocals, GetPreviousLocalSlot getPreviousLocalSlot)
        {
            this.allLocals            = new List <LocalDefinition>();
            this.getPreviousLocalSlot = getPreviousLocalSlot;

            // Add placeholders for previous locals. The actual
            // identities are populated if/when the locals are reused.
            for (int i = 0; i < previousLocals.Length; i++)
            {
                var localInfo = previousLocals[i];
                Debug.Assert(localInfo.Type != null);
                var local = new LocalDefinition(
                    identity: null,
                    name: null,
                    type: localInfo.Type,
                    slot: i,
                    isCompilerGenerated: true,
                    // The placeholder local is marked as compiler-generated
                    // so it will be excluded from the PDB and debugger if not
                    // replaced by a valid local in DeclareLocalInternal.
                    constraints: localInfo.Constraints,
                    isDynamic: false,
                    dynamicTransformFlags: default(ImmutableArray <TypedConstant>));
                this.allLocals.Add(local);
            }
        }
Esempio n. 2
0
        public EncLocalSlotManager(ImmutableArray<EncLocalInfo> previousLocals, GetPreviousLocalSlot getPreviousLocalSlot)
        {
            this.allLocals = new List<LocalDefinition>();
            this.getPreviousLocalSlot = getPreviousLocalSlot;

            // Add placeholders for previous locals. The actual
            // identities are populated if/when the locals are reused.
            for (int i = 0; i < previousLocals.Length; i++)
            {
                var localInfo = previousLocals[i];
                Debug.Assert(localInfo.Type != null);
                var local = new LocalDefinition(
                    identity: null,
                    name: null,
                    type: localInfo.Type,
                    slot: i,
                    isCompilerGenerated: true,
                    // The placeholder local is marked as compiler-generated
                    // so it will be excluded from the PDB and debugger if not
                    // replaced by a valid local in DeclareLocalInternal.
                    constraints: localInfo.Constraints,
                    isDynamic: false,
                    dynamicTransformFlags: default(ImmutableArray<TypedConstant>));
                this.allLocals.Add(local);
            }
        }
 public EncLocalSlotManager(ImmutableArray<EncLocalInfo> previousLocals, GetPreviousLocalSlot getPreviousLocalSlot)
 {
     // Add placeholders for previous locals. The actual
     // identities are populated if/when the locals are reused.
     this.allLocals = new List<ILocalDefinition>(previousLocals.Select((info, index) => new SignatureOnlyLocalDefinition(info.Signature, index)));
     this.getPreviousLocalSlot = getPreviousLocalSlot;
 }
 public EncLocalSlotManager(ImmutableArray <EncLocalInfo> previousLocals, GetPreviousLocalSlot getPreviousLocalSlot)
 {
     // Add placeholders for previous locals. The actual
     // identities are populated if/when the locals are reused.
     this.allLocals            = new List <ILocalDefinition>(previousLocals.Select((info, index) => new SignatureOnlyLocalDefinition(info.Signature, index)));
     this.getPreviousLocalSlot = getPreviousLocalSlot;
 }
Esempio n. 5
0
        internal override bool TryGetPreviousLocals(
            EmitBaseline baseline,
            IMethodSymbol method,
            out ImmutableArray<EncLocalInfo> previousLocals,
            out GetPreviousLocalSlot getPreviousLocalSlot)
        {
            previousLocals = default(ImmutableArray<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(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 = 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 methodBody = this.module.GetMethodBodyOrThrow(handle);

                    if (!methodBody.LocalSignature.IsNil)
                    {
                        var signature = this.module.MetadataReader.GetLocalSignature(methodBody.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 = LocalVariableDeclaratorsCollector.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<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 = LocalVariableDeclaratorsCollector.GetDeclarators(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 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;
        }
Esempio n. 6
0
 internal abstract bool TryGetPreviousLocals(
     EmitBaseline baseline,
     IMethodSymbol method,
     out ImmutableArray <EncLocalInfo> previousLocals,
     out GetPreviousLocalSlot getPreviousLocalSlot);
        internal override bool TryGetPreviousLocals(
            EmitBaseline baseline,
            IMethodSymbol method,
            out ImmutableArray <EncLocalInfo> previousLocals,
            out GetPreviousLocalSlot getPreviousLocalSlot)
        {
            previousLocals       = default(ImmutableArray <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(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 = 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 methodBody = this.module.GetMethodBodyOrThrow(handle);

                    if (!methodBody.LocalSignature.IsNil)
                    {
                        var signatureHandle = this.module.MetadataReader.GetLocalSignature(methodBody.LocalSignature);
                        var signatureReader = this.module.GetMemoryReaderOrThrow(signatureHandle);
                        localInfo = this.metadataDecoder.DecodeLocalSignatureOrThrow(ref signatureReader);
                    }
                    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 = LocalVariableDeclaratorsCollector.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 <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       = LocalVariableDeclaratorsCollector.GetDeclarators(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 EncLocalInfo(offset, previousType, constraints, (int)local.SynthesizedLocalKind, signature: null);
                                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);
        }
Esempio n. 8
0
 internal abstract bool TryGetPreviousLocals(
     EmitBaseline baseline,
     IMethodSymbol method,
     out ImmutableArray<EncLocalInfo> previousLocals,
     out GetPreviousLocalSlot getPreviousLocalSlot);