Пример #1
0
        /// <summary>
        /// Entrypoint for the <see cref="T:Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator.CSharpExpressionCompiler"/>.
        /// </summary>
        internal static EmitBaseline CreateInitialBaselineWithoutChecks(ModuleMetadata module, LocalVariableNameProvider localNames)
        {
            var reader = module.MetadataReader;
            var moduleVersionId = module.GetModuleVersionId();

            return new EmitBaseline(
                module,
                compilation: null,
                moduleBuilder: null,
                moduleVersionId: moduleVersionId,
                ordinal: 0,
                encId: default(Guid),
                typesAdded: new Dictionary<ITypeDefinition, uint>(),
                eventsAdded: new Dictionary<IEventDefinition, uint>(),
                fieldsAdded: new Dictionary<IFieldDefinition, uint>(),
                methodsAdded: new Dictionary<IMethodDefinition, uint>(),
                propertiesAdded: new Dictionary<IPropertyDefinition, uint>(),
                eventMapAdded: new Dictionary<uint, uint>(),
                propertyMapAdded: new Dictionary<uint, uint>(),
                tableEntriesAdded: EmptyTableSizes,
                blobStreamLengthAdded: 0,
                stringStreamLengthAdded: 0,
                userStringStreamLengthAdded: 0,
                guidStreamLengthAdded: 0,
                anonymousTypeMap: null, // Unset for initial metadata
                localsForMethodsAddedOrChanged: new Dictionary<uint, ImmutableArray<EncLocalInfo>>(),
                localNames: localNames,
                typeToEventMap: reader.CalculateTypeEventMap(),
                typeToPropertyMap: reader.CalculateTypePropertyMap());
        }
Пример #2
0
        internal EmitBaseline With(
            Compilation compilation,
            CommonPEModuleBuilder moduleBuilder,
            int ordinal,
            Guid encId,
            IReadOnlyDictionary <ITypeDefinition, uint> typesAdded,
            IReadOnlyDictionary <IEventDefinition, uint> eventsAdded,
            IReadOnlyDictionary <IFieldDefinition, uint> fieldsAdded,
            IReadOnlyDictionary <IMethodDefinition, uint> methodsAdded,
            IReadOnlyDictionary <IPropertyDefinition, uint> propertiesAdded,
            IReadOnlyDictionary <uint, uint> eventMapAdded,
            IReadOnlyDictionary <uint, uint> propertyMapAdded,
            IReadOnlyDictionary <MethodImplKey, uint> methodImplsAdded,
            ImmutableArray <int> tableEntriesAdded,
            int blobStreamLengthAdded,
            int stringStreamLengthAdded,
            int userStringStreamLengthAdded,
            int guidStreamLengthAdded,
            IReadOnlyDictionary <AnonymousTypeKey, AnonymousTypeValue> anonymousTypeMap,
            IReadOnlyDictionary <uint, ImmutableArray <EncLocalInfo> > localsForMethodsAddedOrChanged,
            LocalVariableNameProvider localNames)
        {
            Debug.Assert((this.AnonymousTypeMap == null) || (anonymousTypeMap != null));
            Debug.Assert((this.AnonymousTypeMap == null) || (anonymousTypeMap.Count >= this.AnonymousTypeMap.Count));

            return(new EmitBaseline(
                       this.OriginalMetadata,
                       compilation,
                       moduleBuilder,
                       this.ModuleVersionId,
                       ordinal,
                       encId,
                       typesAdded,
                       eventsAdded,
                       fieldsAdded,
                       methodsAdded,
                       propertiesAdded,
                       eventMapAdded,
                       propertyMapAdded,
                       methodImplsAdded,
                       tableEntriesAdded,
                       blobStreamLengthAdded: blobStreamLengthAdded,
                       stringStreamLengthAdded: stringStreamLengthAdded,
                       userStringStreamLengthAdded: userStringStreamLengthAdded,
                       guidStreamLengthAdded: guidStreamLengthAdded,
                       anonymousTypeMap: anonymousTypeMap,
                       localsForMethodsAddedOrChanged: localsForMethodsAddedOrChanged,
                       localNames: localNames,
                       typeToEventMap: this.TypeToEventMap,
                       typeToPropertyMap: this.TypeToPropertyMap,
                       methodImpls: this.MethodImpls));
        }
Пример #3
0
        public void CreateInitialBaseline()
        {
            var provider = new LocalVariableNameProvider(_ => ImmutableArray.Create<string>());
            var peModule = ModuleMetadata.CreateFromImage(TestResources.MetadataTests.Basic.Members);
            var peReader = peModule.Module.PEReaderOpt;

            var mdBytes = peReader.ReadAllMetadataBytes();
            var mdBytesHandle = PinnedImmutableArray.Create(mdBytes);
            var mdModule = ModuleMetadata.CreateFromMetadata(mdBytesHandle.Pointer, mdBytes.Length);

            Assert.Throws<ArgumentNullException>(() => EmitBaseline.CreateInitialBaseline(null, provider));
            Assert.Throws<ArgumentNullException>(() => EmitBaseline.CreateInitialBaseline(peModule, null));
            Assert.Throws<ArgumentException>(() => EmitBaseline.CreateInitialBaseline(mdModule, provider));
        }
Пример #4
0
        public void CreateInitialBaseline()
        {
            var provider = new LocalVariableNameProvider(_ => ImmutableArray.Create <string>());
            var peModule = ModuleMetadata.CreateFromImage(TestResources.MetadataTests.Basic.Members);
            var peReader = peModule.Module.PEReaderOpt;

            var mdBytes       = peReader.GetMetadata().GetContent();
            var mdBytesHandle = PinnedImmutableArray.Create(mdBytes);
            var mdModule      = ModuleMetadata.CreateFromMetadata(mdBytesHandle.Pointer, mdBytes.Length);

            Assert.Throws <ArgumentNullException>(() => EmitBaseline.CreateInitialBaseline(null, provider));
            Assert.Throws <ArgumentNullException>(() => EmitBaseline.CreateInitialBaseline(peModule, null));
            Assert.Throws <ArgumentException>(() => EmitBaseline.CreateInitialBaseline(mdModule, provider));
        }
Пример #5
0
        /// <summary>
        /// Creates an <see cref="EmitBaseline"/> from the metadata of the module before editing
        /// and from a function that maps from a method to an array of local names.
        /// </summary>
        /// <param name="module">The metadata of the module before editing.</param>
        /// <param name="localNames">
        /// A function that returns the array of local names given a method index from the module metadata.
        /// </param>
        /// <returns>An <see cref="EmitBaseline"/> for the module.</returns>
        /// <remarks>
        /// Only the initial baseline is created using this method; subsequent baselines are created
        /// automatically when emitting the differences in subsequent compilations.
        ///
        /// When an active method (one for which a frame is allocated on a stack) is updated the values of its local variables need to be preserved.
        /// The mapping of local variable names to their slots in the frame is not included in the metadata and thus needs to be provided by
        /// <paramref name="localNames"/>.
        ///
        /// The <see cref="LocalVariableNameProvider"/> is only needed for the initial generation. The mapping for the subsequent generations
        /// is carried over through <see cref="EmitBaseline"/>. The compiler assigns slots to named local variables (including named temporary variables)
        /// it the order in which they appear in the source code. This property allows the compiler to reconstruct the local variable mapping
        /// for the initial generation. A subsequent generation may add a new variable in between two variables of the previous generation.
        /// Since the slots of the previous generation variables need to be preserved the only option is to add these new variables to the end.
        /// The slot ordering thus no longer matches the syntax ordering. It is therefore necessary to pass <see cref="EmitDifferenceResult.Baseline"/>
        /// to the next generation (rather than e.g. create new <see cref="EmitBaseline"/>s from scratch based on metadata produced by subsequent compilations).
        /// </remarks>
        public static EmitBaseline CreateInitialBaseline(ModuleMetadata module, LocalVariableNameProvider localNames)
        {
            if (module == null)
            {
                throw new ArgumentNullException("module");
            }

            if (!module.Module.HasIL)
            {
                throw new ArgumentException(CodeAnalysisResources.PEImageNotAvailable, "module");
            }

            if (localNames == null)
            {
                throw new ArgumentNullException("localNames");
            }

            var reader          = module.MetadataReader;
            var moduleVersionId = module.GetModuleVersionId();

            return(new EmitBaseline(
                       module,
                       compilation: null,
                       moduleBuilder: null,
                       moduleVersionId: moduleVersionId,
                       ordinal: 0,
                       encId: default(Guid),
                       typesAdded: new Dictionary <ITypeDefinition, uint>(),
                       eventsAdded: new Dictionary <IEventDefinition, uint>(),
                       fieldsAdded: new Dictionary <IFieldDefinition, uint>(),
                       methodsAdded: new Dictionary <IMethodDefinition, uint>(),
                       propertiesAdded: new Dictionary <IPropertyDefinition, uint>(),
                       eventMapAdded: new Dictionary <uint, uint>(),
                       propertyMapAdded: new Dictionary <uint, uint>(),
                       methodImplsAdded: new Dictionary <MethodImplKey, uint>(),
                       tableEntriesAdded: EmptyTableSizes,
                       blobStreamLengthAdded: 0,
                       stringStreamLengthAdded: 0,
                       userStringStreamLengthAdded: 0,
                       guidStreamLengthAdded: 0,
                       anonymousTypeMap: null, // Unset for initial metadata
                       localsForMethodsAddedOrChanged: new Dictionary <uint, ImmutableArray <EncLocalInfo> >(),
                       localNames: localNames,
                       typeToEventMap: reader.CalculateTypeEventMap(),
                       typeToPropertyMap: reader.CalculateTypePropertyMap(),
                       methodImpls: CalculateMethodImpls(reader)));
        }
Пример #6
0
        /// <summary>
        /// Creates an <see cref="EmitBaseline"/> from the metadata of the module before editing
        /// and from a function that maps from a method to an array of local names. Only the
        /// initial baseline is created using this method; subsequent baselines are created
        /// automatically when emitting the differences in subsequent compilations.
        /// </summary>
        /// <param name="module">The metadata of the module before editing.</param>
        /// <param name="localNames">A function that returns the array of local names given a method index from the module metadata.</param>
        /// <returns>An EmitBaseline for the module.</returns>
        public static EmitBaseline CreateInitialBaseline(ModuleMetadata module, LocalVariableNameProvider localNames)
        {
            if (module == null)
            {
                throw new ArgumentNullException("module");
            }

            if (!module.Module.HasIL)
            {
                throw new ArgumentException(CodeAnalysisResources.PEImageNotAvailable, "module");
            }

            if (localNames == null)
            {
                throw new ArgumentNullException("localNames");
            }

            return CreateInitialBaselineWithoutChecks(module, localNames);
        }
Пример #7
0
        /// <summary>
        /// Creates an <see cref="EmitBaseline"/> from the metadata of the module before editing
        /// and from a function that maps from a method to an array of local names. Only the
        /// initial baseline is created using this method; subsequent baselines are created
        /// automatically when emitting the differences in subsequent compilations.
        /// </summary>
        /// <param name="module">The metadata of the module before editing.</param>
        /// <param name="localNames">A function that returns the array of local names given a method index from the module metadata.</param>
        /// <returns>An EmitBaseline for the module.</returns>
        public static EmitBaseline CreateInitialBaseline(ModuleMetadata module, LocalVariableNameProvider localNames)
        {
            if (module == null)
            {
                throw new ArgumentNullException("module");
            }

            if (!module.Module.HasIL)
            {
                throw new ArgumentException(CodeAnalysisResources.PEImageNotAvailable, "module");
            }

            if (localNames == null)
            {
                throw new ArgumentNullException("localNames");
            }

            return(CreateInitialBaselineWithoutChecks(module, localNames));
        }
Пример #8
0
        internal EmitBaseline With(
            Compilation compilation,
            CommonPEModuleBuilder moduleBuilder,
            int ordinal,
            Guid encId,
            IReadOnlyDictionary<ITypeDefinition, uint> typesAdded,
            IReadOnlyDictionary<IEventDefinition, uint> eventsAdded,
            IReadOnlyDictionary<IFieldDefinition, uint> fieldsAdded,
            IReadOnlyDictionary<IMethodDefinition, uint> methodsAdded,
            IReadOnlyDictionary<IPropertyDefinition, uint> propertiesAdded,
            IReadOnlyDictionary<uint, uint> eventMapAdded,
            IReadOnlyDictionary<uint, uint> propertyMapAdded,
            ImmutableArray<int> tableEntriesAdded,
            int blobStreamLengthAdded,
            int stringStreamLengthAdded,
            int userStringStreamLengthAdded,
            int guidStreamLengthAdded,
            IReadOnlyDictionary<AnonymousTypeKey, AnonymousTypeValue> anonymousTypeMap,
            IReadOnlyDictionary<uint, ImmutableArray<EncLocalInfo>> localsForMethodsAddedOrChanged,
            LocalVariableNameProvider localNames)
        {
            Debug.Assert((this.AnonymousTypeMap == null) || (anonymousTypeMap != null));
            Debug.Assert((this.AnonymousTypeMap == null) || (anonymousTypeMap.Count >= this.AnonymousTypeMap.Count));

            return new EmitBaseline(
                this.OriginalMetadata,
                compilation,
                moduleBuilder,
                this.ModuleVersionId,
                ordinal,
                encId,
                typesAdded,
                eventsAdded,
                fieldsAdded,
                methodsAdded,
                propertiesAdded,
                eventMapAdded,
                propertyMapAdded,
                tableEntriesAdded,
                blobStreamLengthAdded: blobStreamLengthAdded,
                stringStreamLengthAdded: stringStreamLengthAdded,
                userStringStreamLengthAdded: userStringStreamLengthAdded,
                guidStreamLengthAdded: guidStreamLengthAdded,
                anonymousTypeMap: anonymousTypeMap,
                localsForMethodsAddedOrChanged: localsForMethodsAddedOrChanged,
                localNames: localNames,
                typeToEventMap: this.TypeToEventMap,
                typeToPropertyMap: this.TypeToPropertyMap);
        }
Пример #9
0
        private EmitBaseline(
            ModuleMetadata module,
            Compilation compilation,
            CommonPEModuleBuilder moduleBuilder,
            Guid moduleVersionId,
            int ordinal,
            Guid encId,
            IReadOnlyDictionary<ITypeDefinition, uint> typesAdded,
            IReadOnlyDictionary<IEventDefinition, uint> eventsAdded,
            IReadOnlyDictionary<IFieldDefinition, uint> fieldsAdded,
            IReadOnlyDictionary<IMethodDefinition, uint> methodsAdded,
            IReadOnlyDictionary<IPropertyDefinition, uint> propertiesAdded,
            IReadOnlyDictionary<uint, uint> eventMapAdded,
            IReadOnlyDictionary<uint, uint> propertyMapAdded,
            ImmutableArray<int> tableEntriesAdded,
            int blobStreamLengthAdded,
            int stringStreamLengthAdded,
            int userStringStreamLengthAdded,
            int guidStreamLengthAdded,
            IReadOnlyDictionary<AnonymousTypeKey, AnonymousTypeValue> anonymousTypeMap,
            IReadOnlyDictionary<uint, ImmutableArray<EncLocalInfo>> localsForMethodsAddedOrChanged,
            LocalVariableNameProvider localNames,
            IReadOnlyDictionary<uint, uint> typeToEventMap,
            IReadOnlyDictionary<uint, uint> typeToPropertyMap)
        {
            Debug.Assert(module != null);
            Debug.Assert((ordinal == 0) == (encId == default(Guid)));
            Debug.Assert(encId != module.GetModuleVersionId());
            Debug.Assert(localNames != null);
            Debug.Assert(typeToEventMap != null);
            Debug.Assert(typeToPropertyMap != null);

            Debug.Assert(tableEntriesAdded.Length == MetadataTokens.TableCount);

            // The size of each table is the total number of entries added in all previous
            // generations after the initial generation. Depending on the table, some of the
            // entries may not be available in the current generation (say, a synthesized type
            // from a method that was not recompiled for instance)
            Debug.Assert(tableEntriesAdded[(int)TableIndex.TypeDef] >= typesAdded.Count);
            Debug.Assert(tableEntriesAdded[(int)TableIndex.Event] >= eventsAdded.Count);
            Debug.Assert(tableEntriesAdded[(int)TableIndex.Field] >= fieldsAdded.Count);
            Debug.Assert(tableEntriesAdded[(int)TableIndex.MethodDef] >= methodsAdded.Count);
            Debug.Assert(tableEntriesAdded[(int)TableIndex.Property] >= propertiesAdded.Count);
            Debug.Assert(tableEntriesAdded[(int)TableIndex.EventMap] >= eventMapAdded.Count);
            Debug.Assert(tableEntriesAdded[(int)TableIndex.PropertyMap] >= propertyMapAdded.Count);

            var reader = module.Module.MetadataReader;

            this.OriginalMetadata = module;
            this.Compilation = compilation;
            this.PEModuleBuilder = moduleBuilder;
            this.ModuleVersionId = moduleVersionId;
            this.Ordinal = ordinal;
            this.EncId = encId;

            this.TypesAdded = typesAdded;
            this.EventsAdded = eventsAdded;
            this.FieldsAdded = fieldsAdded;
            this.MethodsAdded = methodsAdded;
            this.PropertiesAdded = propertiesAdded;
            this.EventMapAdded = eventMapAdded;
            this.PropertyMapAdded = propertyMapAdded;
            this.TableEntriesAdded = tableEntriesAdded;
            this.BlobStreamLengthAdded = blobStreamLengthAdded;
            this.StringStreamLengthAdded = stringStreamLengthAdded;
            this.UserStringStreamLengthAdded = userStringStreamLengthAdded;
            this.GuidStreamLengthAdded = guidStreamLengthAdded;
            this.AnonymousTypeMap = anonymousTypeMap;
            this.LocalsForMethodsAddedOrChanged = localsForMethodsAddedOrChanged;

            this.LocalNames = localNames;
            this.TableSizes = CalculateTableSizes(reader, this.TableEntriesAdded);
            this.TypeToEventMap = typeToEventMap;
            this.TypeToPropertyMap = typeToPropertyMap;
        }
Пример #10
0
        private EmitBaseline(
            ModuleMetadata module,
            Compilation compilation,
            CommonPEModuleBuilder moduleBuilder,
            Guid moduleVersionId,
            int ordinal,
            Guid encId,
            IReadOnlyDictionary <ITypeDefinition, uint> typesAdded,
            IReadOnlyDictionary <IEventDefinition, uint> eventsAdded,
            IReadOnlyDictionary <IFieldDefinition, uint> fieldsAdded,
            IReadOnlyDictionary <IMethodDefinition, uint> methodsAdded,
            IReadOnlyDictionary <IPropertyDefinition, uint> propertiesAdded,
            IReadOnlyDictionary <uint, uint> eventMapAdded,
            IReadOnlyDictionary <uint, uint> propertyMapAdded,
            IReadOnlyDictionary <MethodImplKey, uint> methodImplsAdded,
            ImmutableArray <int> tableEntriesAdded,
            int blobStreamLengthAdded,
            int stringStreamLengthAdded,
            int userStringStreamLengthAdded,
            int guidStreamLengthAdded,
            IReadOnlyDictionary <AnonymousTypeKey, AnonymousTypeValue> anonymousTypeMap,
            IReadOnlyDictionary <uint, ImmutableArray <EncLocalInfo> > localsForMethodsAddedOrChanged,
            LocalVariableNameProvider localNames,
            IReadOnlyDictionary <uint, uint> typeToEventMap,
            IReadOnlyDictionary <uint, uint> typeToPropertyMap,
            IReadOnlyDictionary <MethodImplKey, uint> methodImpls)
        {
            Debug.Assert(module != null);
            Debug.Assert((ordinal == 0) == (encId == default(Guid)));
            Debug.Assert(encId != module.GetModuleVersionId());
            Debug.Assert(localNames != null);
            Debug.Assert(typeToEventMap != null);
            Debug.Assert(typeToPropertyMap != null);
            Debug.Assert(moduleVersionId != default(Guid));
            Debug.Assert(moduleVersionId == module.GetModuleVersionId());

            Debug.Assert(tableEntriesAdded.Length == MetadataTokens.TableCount);

            // The size of each table is the total number of entries added in all previous
            // generations after the initial generation. Depending on the table, some of the
            // entries may not be available in the current generation (say, a synthesized type
            // from a method that was not recompiled for instance)
            Debug.Assert(tableEntriesAdded[(int)TableIndex.TypeDef] >= typesAdded.Count);
            Debug.Assert(tableEntriesAdded[(int)TableIndex.Event] >= eventsAdded.Count);
            Debug.Assert(tableEntriesAdded[(int)TableIndex.Field] >= fieldsAdded.Count);
            Debug.Assert(tableEntriesAdded[(int)TableIndex.MethodDef] >= methodsAdded.Count);
            Debug.Assert(tableEntriesAdded[(int)TableIndex.Property] >= propertiesAdded.Count);
            Debug.Assert(tableEntriesAdded[(int)TableIndex.EventMap] >= eventMapAdded.Count);
            Debug.Assert(tableEntriesAdded[(int)TableIndex.PropertyMap] >= propertyMapAdded.Count);

            var reader = module.Module.MetadataReader;

            this.OriginalMetadata = module;
            this.Compilation      = compilation;
            this.PEModuleBuilder  = moduleBuilder;
            this.ModuleVersionId  = moduleVersionId;
            this.Ordinal          = ordinal;
            this.EncId            = encId;

            this.TypesAdded                     = typesAdded;
            this.EventsAdded                    = eventsAdded;
            this.FieldsAdded                    = fieldsAdded;
            this.MethodsAdded                   = methodsAdded;
            this.PropertiesAdded                = propertiesAdded;
            this.EventMapAdded                  = eventMapAdded;
            this.PropertyMapAdded               = propertyMapAdded;
            this.MethodImplsAdded               = methodImplsAdded;
            this.TableEntriesAdded              = tableEntriesAdded;
            this.BlobStreamLengthAdded          = blobStreamLengthAdded;
            this.StringStreamLengthAdded        = stringStreamLengthAdded;
            this.UserStringStreamLengthAdded    = userStringStreamLengthAdded;
            this.GuidStreamLengthAdded          = guidStreamLengthAdded;
            this.AnonymousTypeMap               = anonymousTypeMap;
            this.LocalsForMethodsAddedOrChanged = localsForMethodsAddedOrChanged;

            this.LocalNames        = localNames;
            this.TableSizes        = CalculateTableSizes(reader, this.TableEntriesAdded);
            this.TypeToEventMap    = typeToEventMap;
            this.TypeToPropertyMap = typeToPropertyMap;
            this.MethodImpls       = methodImpls;
        }
Пример #11
0
        /// <summary>
        /// Entrypoint for the <see cref="T:Microsoft.CodeAnalysis.CSharp.ExpressionEvaluator.CSharpExpressionCompiler"/>.
        /// </summary>
        internal static EmitBaseline CreateInitialBaselineWithoutChecks(ModuleMetadata module, LocalVariableNameProvider localNames)
        {
            var reader          = module.MetadataReader;
            var moduleVersionId = module.GetModuleVersionId();

            return(new EmitBaseline(
                       module,
                       compilation: null,
                       moduleBuilder: null,
                       moduleVersionId: moduleVersionId,
                       ordinal: 0,
                       encId: default(Guid),
                       typesAdded: new Dictionary <ITypeDefinition, uint>(),
                       eventsAdded: new Dictionary <IEventDefinition, uint>(),
                       fieldsAdded: new Dictionary <IFieldDefinition, uint>(),
                       methodsAdded: new Dictionary <IMethodDefinition, uint>(),
                       propertiesAdded: new Dictionary <IPropertyDefinition, uint>(),
                       eventMapAdded: new Dictionary <uint, uint>(),
                       propertyMapAdded: new Dictionary <uint, uint>(),
                       tableEntriesAdded: EmptyTableSizes,
                       blobStreamLengthAdded: 0,
                       stringStreamLengthAdded: 0,
                       userStringStreamLengthAdded: 0,
                       guidStreamLengthAdded: 0,
                       anonymousTypeMap: null, // Unset for initial metadata
                       localsForMethodsAddedOrChanged: new Dictionary <uint, ImmutableArray <EncLocalInfo> >(),
                       localNames: localNames,
                       typeToEventMap: reader.CalculateTypeEventMap(),
                       typeToPropertyMap: reader.CalculateTypePropertyMap()));
        }