public PEDeltaAssemblyBuilder( SourceAssemblySymbol sourceAssembly, string outputName, OutputKind outputKind, ModulePropertiesForSerialization serializationProperties, IEnumerable <ResourceDescription> manifestResources, Func <AssemblySymbol, AssemblyIdentity> assemblySymbolMapper, EmitBaseline previousGeneration, IEnumerable <SemanticEdit> edits) : base(sourceAssembly, outputName, outputKind, serializationProperties, manifestResources, assemblySymbolMapper, additionalTypes: ImmutableArray <NamedTypeSymbol> .Empty, metadataOnly: false) { var context = new EmitContext(this, null, new DiagnosticBag()); var module = previousGeneration.OriginalMetadata; var compilation = sourceAssembly.DeclaringCompilation; var metadataAssembly = compilation.GetBoundReferenceManager().CreatePEAssemblyForAssemblyMetadata(AssemblyMetadata.Create(module), MetadataImportOptions.All); var metadataDecoder = new Microsoft.CodeAnalysis.CSharp.Symbols.Metadata.PE.MetadataDecoder(metadataAssembly.PrimaryModule); previousGeneration = EnsureInitialized(previousGeneration, metadataDecoder); var matchToMetadata = new CSharpSymbolMatcher(previousGeneration.AnonymousTypeMap, sourceAssembly, context, metadataAssembly); CSharpSymbolMatcher matchToPrevious = null; if (previousGeneration.Ordinal > 0) { var previousAssembly = ((CSharpCompilation)previousGeneration.Compilation).SourceAssembly; var previousContext = new EmitContext((PEModuleBuilder)previousGeneration.PEModuleBuilder, null, new DiagnosticBag()); matchToPrevious = new CSharpSymbolMatcher(previousGeneration.AnonymousTypeMap, sourceAssembly, context, previousAssembly, previousContext); } this.previousDefinitions = new CSharpDefinitionMap(previousGeneration.OriginalMetadata.Module, edits, metadataDecoder, matchToMetadata, matchToPrevious); this.previousGeneration = previousGeneration; this.changes = new SymbolChanges(this.previousDefinitions, edits); }
public PEDeltaAssemblyBuilder( SourceAssemblySymbol sourceAssembly, EmitOptions emitOptions, OutputKind outputKind, Cci.ModulePropertiesForSerialization serializationProperties, IEnumerable <ResourceDescription> manifestResources, EmitBaseline previousGeneration, IEnumerable <SemanticEdit> edits, Func <ISymbol, bool> isAddedSymbol) : base(sourceAssembly, emitOptions, outputKind, serializationProperties, manifestResources, additionalTypes: ImmutableArray <NamedTypeSymbol> .Empty) { var initialBaseline = previousGeneration.InitialBaseline; var context = new EmitContext(this, null, new DiagnosticBag(), metadataOnly: false, includePrivateMembers: true); // Hydrate symbols from initial metadata. Once we do so it is important to reuse these symbols across all generations, // in order for the symbol matcher to be able to use reference equality once it maps symbols to initial metadata. var metadataSymbols = GetOrCreateMetadataSymbols(initialBaseline, sourceAssembly.DeclaringCompilation); var metadataDecoder = (MetadataDecoder)metadataSymbols.MetadataDecoder; var metadataAssembly = (PEAssemblySymbol)metadataDecoder.ModuleSymbol.ContainingAssembly; var matchToMetadata = new CSharpSymbolMatcher(metadataSymbols.AnonymousTypes, metadataSymbols.SynthesizedDelegates, sourceAssembly, context, metadataAssembly); CSharpSymbolMatcher?matchToPrevious = null; if (previousGeneration.Ordinal > 0) { RoslynDebug.AssertNotNull(previousGeneration.Compilation); RoslynDebug.AssertNotNull(previousGeneration.PEModuleBuilder); var previousAssembly = ((CSharpCompilation)previousGeneration.Compilation).SourceAssembly; var previousContext = new EmitContext((PEModuleBuilder)previousGeneration.PEModuleBuilder, null, new DiagnosticBag(), metadataOnly: false, includePrivateMembers: true); matchToPrevious = new CSharpSymbolMatcher( previousGeneration.AnonymousTypeMap, previousGeneration.SynthesizedDelegates, sourceAssembly: sourceAssembly, sourceContext: context, otherAssembly: previousAssembly, otherContext: previousContext, otherSynthesizedMembersOpt: previousGeneration.SynthesizedMembers); } _previousDefinitions = new CSharpDefinitionMap(edits, metadataDecoder, matchToMetadata, matchToPrevious); _previousGeneration = previousGeneration; _changes = new CSharpSymbolChanges(_previousDefinitions, edits, isAddedSymbol); // Workaround for https://github.com/dotnet/roslyn/issues/3192. // When compiling state machine we stash types of awaiters and state-machine hoisted variables, // so that next generation can look variables up and reuse their slots if possible. // // When we are about to allocate a slot for a lifted variable while compiling the next generation // we map its type to the previous generation and then check the slot types that we stashed earlier. // If the variable type matches we reuse it. In order to compare the previous variable type with the current one // both need to be completely lowered (translated). Standard translation only goes one level deep. // Generic arguments are not translated until they are needed by metadata writer. // // In order to get the fully lowered form we run the type symbols of stashed variables through a deep translator // that translates the symbol recursively. _deepTranslator = new CSharpSymbolMatcher.DeepTranslator(sourceAssembly.GetSpecialType(SpecialType.System_Object)); }
public CSharpDefinitionMap( IEnumerable <SemanticEdit> edits, MetadataDecoder metadataDecoder, CSharpSymbolMatcher mapToMetadata, CSharpSymbolMatcher mapToPrevious) : base(edits, mapToMetadata, mapToPrevious) { Debug.Assert(metadataDecoder != null); _metadataDecoder = metadataDecoder; }
/// <summary> /// Return a version of the baseline with all definitions mapped to this compilation. /// Definitions from the initial generation, from metadata, are not mapped since /// the initial generation is always included as metadata. That is, the symbols from /// types, methods, ... in the TypesAdded, MethodsAdded, ... collections are replaced /// by the corresponding symbols from the current compilation. /// </summary> private static EmitBaseline MapToCompilation( CSharpCompilation compilation, PEDeltaAssemblyBuilder moduleBeingBuilt) { var previousGeneration = moduleBeingBuilt.PreviousGeneration; RoslynDebug.Assert(previousGeneration.Compilation != compilation); if (previousGeneration.Ordinal == 0) { // Initial generation, nothing to map. (Since the initial generation // is always loaded from metadata in the context of the current // compilation, there's no separate mapping step.) return(previousGeneration); } RoslynDebug.AssertNotNull(previousGeneration.Compilation); RoslynDebug.AssertNotNull(previousGeneration.PEModuleBuilder); var currentSynthesizedMembers = moduleBeingBuilt.GetAllSynthesizedMembers(); // Mapping from previous compilation to the current. var anonymousTypeMap = moduleBeingBuilt.GetAnonymousTypeMap(); var synthesizedDelegates = moduleBeingBuilt.GetSynthesizedDelegates(); var sourceAssembly = ((CSharpCompilation)previousGeneration.Compilation).SourceAssembly; var sourceContext = new EmitContext((PEModuleBuilder)previousGeneration.PEModuleBuilder, null, new DiagnosticBag(), metadataOnly: false, includePrivateMembers: true); var otherContext = new EmitContext(moduleBeingBuilt, null, new DiagnosticBag(), metadataOnly: false, includePrivateMembers: true); var matcher = new CSharpSymbolMatcher( anonymousTypeMap, synthesizedDelegates, sourceAssembly, sourceContext, compilation.SourceAssembly, otherContext, currentSynthesizedMembers); var mappedSynthesizedMembers = matcher.MapSynthesizedMembers(previousGeneration.SynthesizedMembers, currentSynthesizedMembers); // TODO: can we reuse some data from the previous matcher? var matcherWithAllSynthesizedMembers = new CSharpSymbolMatcher( anonymousTypeMap, synthesizedDelegates, sourceAssembly, sourceContext, compilation.SourceAssembly, otherContext, mappedSynthesizedMembers); return(matcherWithAllSynthesizedMembers.MapBaselineToCompilation( previousGeneration, compilation, moduleBeingBuilt, mappedSynthesizedMembers)); }
public CSharpDefinitionMap( IEnumerable <SemanticEdit> edits, MetadataDecoder metadataDecoder, CSharpSymbolMatcher mapToMetadata, CSharpSymbolMatcher?mapToPrevious) : base(edits) { _metadataDecoder = metadataDecoder; _mapToMetadata = mapToMetadata; _mapToPrevious = mapToPrevious ?? mapToMetadata; }
public CSharpDefinitionMap( PEModule module, IEnumerable <SemanticEdit> edits, MetadataDecoder metadataDecoder, CSharpSymbolMatcher mapToMetadata, CSharpSymbolMatcher mapToPrevious) : base(module, edits) { Debug.Assert(mapToMetadata != null); Debug.Assert(metadataDecoder != null); this.mapToMetadata = mapToMetadata; this.mapToPrevious = mapToPrevious ?? mapToMetadata; this.metadataDecoder = metadataDecoder; }
private static EncLocalInfo MapLocalInfo( CSharpSymbolMatcher map, EncLocalInfo localInfo) { Debug.Assert(!localInfo.IsDefault); if (localInfo.Type == null) { Debug.Assert(localInfo.Signature != null); return(localInfo); } else { var type = map.MapReference(localInfo.Type); Debug.Assert(type != null); return(new EncLocalInfo(localInfo.Offset, type, localInfo.Constraints, localInfo.SynthesizedKind, localInfo.Signature)); } }
public PEDeltaAssemblyBuilder( SourceAssemblySymbol sourceAssembly, EmitOptions emitOptions, OutputKind outputKind, ModulePropertiesForSerialization serializationProperties, IEnumerable <ResourceDescription> manifestResources, EmitBaseline previousGeneration, IEnumerable <SemanticEdit> edits, Func <ISymbol, bool> isAddedSymbol) : base(sourceAssembly, emitOptions, outputKind, serializationProperties, manifestResources, assemblySymbolMapper: null, additionalTypes: ImmutableArray <NamedTypeSymbol> .Empty) { var initialBaseline = previousGeneration.InitialBaseline; var context = new EmitContext(this, null, new DiagnosticBag()); var module = previousGeneration.OriginalMetadata; var compilation = sourceAssembly.DeclaringCompilation; var metadataAssembly = compilation.GetBoundReferenceManager().CreatePEAssemblyForAssemblyMetadata(AssemblyMetadata.Create(module), MetadataImportOptions.All); var metadataDecoder = new Symbols.Metadata.PE.MetadataDecoder(metadataAssembly.PrimaryModule); if (initialBaseline.LazyOriginalMetadataAnonymousTypeMap == null) { initialBaseline.LazyOriginalMetadataAnonymousTypeMap = GetAnonymousTypeMapFromMetadata(module.MetadataReader, metadataDecoder); } var matchToMetadata = new CSharpSymbolMatcher(initialBaseline.LazyOriginalMetadataAnonymousTypeMap, sourceAssembly, context, metadataAssembly); CSharpSymbolMatcher matchToPrevious = null; if (previousGeneration.Ordinal > 0) { var previousAssembly = ((CSharpCompilation)previousGeneration.Compilation).SourceAssembly; var previousContext = new EmitContext((PEModuleBuilder)previousGeneration.PEModuleBuilder, null, new DiagnosticBag()); matchToPrevious = new CSharpSymbolMatcher( previousGeneration.AnonymousTypeMap, sourceAssembly: sourceAssembly, sourceContext: context, otherAssembly: previousAssembly, otherContext: previousContext, otherSynthesizedMembersOpt: previousGeneration.SynthesizedMembers); } _previousDefinitions = new CSharpDefinitionMap(previousGeneration.OriginalMetadata.Module, edits, metadataDecoder, matchToMetadata, matchToPrevious); _previousGeneration = previousGeneration; _changes = new SymbolChanges(_previousDefinitions, edits, isAddedSymbol); }
private static IReadOnlyDictionary <K, V> MapDefinitions <K, V>( CSharpSymbolMatcher map, IReadOnlyDictionary <K, V> items) where K : Cci.IDefinition { var result = new Dictionary <K, V>(); foreach (var pair in items) { var key = (K)map.MapDefinition(pair.Key); // Result may be null if the definition was deleted, or if the definition // was synthesized (e.g.: an iterator type) and the method that generated // the synthesized definition was unchanged and not recompiled. if (key != null) { result.Add(key, pair.Value); } } return(result); }
/// <summary> /// Return a version of the baseline with all definitions mapped to this compilation. /// Definitions from the initial generation, from metadata, are not mapped since /// the initial generation is always included as metadata. That is, the symbols from /// types, methods, ... in the TypesAdded, MethodsAdded, ... collections are replaced /// by the corresponding symbols from the current compilation. /// </summary> private static EmitBaseline MapToCompilation( CSharpCompilation compilation, PEDeltaAssemblyBuilder moduleBeingBuilt) { var previousGeneration = moduleBeingBuilt.PreviousGeneration; Debug.Assert(previousGeneration.Compilation != compilation); if (previousGeneration.Ordinal == 0) { // Initial generation, nothing to map. (Since the initial generation // is always loaded from metadata in the context of the current // compilation, there's no separate mapping step.) return(previousGeneration); } var map = new CSharpSymbolMatcher( moduleBeingBuilt.GetAnonymousTypeMap(), ((CSharpCompilation)previousGeneration.Compilation).SourceAssembly, new EmitContext((PEModuleBuilder)previousGeneration.PEModuleBuilder, null, new DiagnosticBag()), compilation.SourceAssembly, new EmitContext((Cci.IModule)moduleBeingBuilt, null, new DiagnosticBag())); // Map all definitions to this compilation. var typesAdded = MapDefinitions(map, previousGeneration.TypesAdded); var eventsAdded = MapDefinitions(map, previousGeneration.EventsAdded); var fieldsAdded = MapDefinitions(map, previousGeneration.FieldsAdded); var methodsAdded = MapDefinitions(map, previousGeneration.MethodsAdded); var propertiesAdded = MapDefinitions(map, previousGeneration.PropertiesAdded); // Map anonymous types to this compilation. var anonymousTypeMap = new Dictionary <AnonymousTypeKey, AnonymousTypeValue>(); foreach (var pair in previousGeneration.AnonymousTypeMap) { var key = pair.Key; var value = pair.Value; var type = (Cci.ITypeDefinition)map.MapDefinition(value.Type); Debug.Assert(type != null); anonymousTypeMap.Add(key, new AnonymousTypeValue(value.Name, value.UniqueIndex, type)); } // Map locals (specifically, local types) to this compilation. var locals = new Dictionary <uint, ImmutableArray <EncLocalInfo> >(); foreach (var pair in previousGeneration.LocalsForMethodsAddedOrChanged) { locals.Add(pair.Key, pair.Value.SelectAsArray((l, m) => MapLocalInfo(m, l), map)); } return(previousGeneration.With( compilation, moduleBeingBuilt, previousGeneration.Ordinal, previousGeneration.EncId, typesAdded, eventsAdded, fieldsAdded, methodsAdded, propertiesAdded, eventMapAdded: previousGeneration.EventMapAdded, propertyMapAdded: previousGeneration.PropertyMapAdded, methodImplsAdded: previousGeneration.MethodImplsAdded, tableEntriesAdded: previousGeneration.TableEntriesAdded, blobStreamLengthAdded: previousGeneration.BlobStreamLengthAdded, stringStreamLengthAdded: previousGeneration.StringStreamLengthAdded, userStringStreamLengthAdded: previousGeneration.UserStringStreamLengthAdded, guidStreamLengthAdded: previousGeneration.GuidStreamLengthAdded, anonymousTypeMap: anonymousTypeMap, localsForMethodsAddedOrChanged: locals, localNames: previousGeneration.LocalNames)); }