Esempio n. 1
0
        // internal for testing
        internal static IReadOnlyDictionary <SynthesizedDelegateKey, SynthesizedDelegateValue> GetAnonymousDelegateMapFromMetadata(MetadataReader reader, MetadataDecoder metadataDecoder)
        {
            var result = new Dictionary <SynthesizedDelegateKey, SynthesizedDelegateValue>();

            foreach (var handle in reader.TypeDefinitions)
            {
                var def = reader.GetTypeDefinition(handle);
                if (!def.Namespace.IsNil)
                {
                    continue;
                }

                if (!reader.StringComparer.StartsWith(def.Name, GeneratedNames.ActionDelegateNamePrefix) &&
                    !reader.StringComparer.StartsWith(def.Name, GeneratedNames.FuncDelegateNamePrefix))
                {
                    continue;
                }

                // The name of a synthesized delegate neatly encodes everything we need to identify it, either
                // in the prefix (return void or not) or the name (ref kinds and arity) so we don't need anything
                // fancy for a key.
                var metadataName = reader.GetString(def.Name);
                var key          = new SynthesizedDelegateKey(metadataName);

                var type  = (NamedTypeSymbol)metadataDecoder.GetTypeOfToken(handle);
                var value = new SynthesizedDelegateValue(type.GetCciAdapter());
                result.Add(key, value);
            }
            return(result);
        }
Esempio n. 2
0
        internal SynthesizedDelegateSymbol SynthesizeDelegate(int parameterCount, BitVector byRefParameters, bool returnsVoid)
        {
            // parameterCount doesn't include return type
            Debug.Assert(byRefParameters.IsNull || parameterCount == byRefParameters.Capacity);

            var key = new SynthesizedDelegateKey(parameterCount, byRefParameters, returnsVoid);

            SynthesizedDelegateValue result;

            if (this.SynthesizedDelegates.TryGetValue(key, out result))
            {
                return(result.Delegate);
            }

            // NOTE: the newly created template may be thrown away if another thread wins
            return(this.SynthesizedDelegates.GetOrAdd(key,
                                                      new SynthesizedDelegateValue(
                                                          this,
                                                          new SynthesizedDelegateSymbol(
                                                              this.Compilation.Assembly.GlobalNamespace,
                                                              key.MakeTypeName(),
                                                              this.System_Object,
                                                              Compilation.GetSpecialType(SpecialType.System_IntPtr),
                                                              returnsVoid ? Compilation.GetSpecialType(SpecialType.System_Void) : null,
                                                              parameterCount,
                                                              byRefParameters))).Delegate);
        }
Esempio n. 3
0
        public void AssignTemplatesNamesAndCompile(MethodCompiler compiler, PEModuleBuilder moduleBeingBuilt, BindingDiagnosticBag diagnostics)
        {
            // Ensure all previous anonymous type templates are included so the
            // types are available for subsequent edit and continue generations.
            foreach (var key in moduleBeingBuilt.GetPreviousAnonymousTypes())
            {
                var templateKey = AnonymousTypeDescriptor.ComputeKey(key.Fields, f => f.Name);
                this.AnonymousTypeTemplates.GetOrAdd(templateKey, k => this.CreatePlaceholderTemplate(key));
            }

            // Get all anonymous types owned by this manager
            var builder = ArrayBuilder <AnonymousTypeTemplateSymbol> .GetInstance();

            GetCreatedAnonymousTypeTemplates(builder);

            // If the collection is not sealed yet we should assign
            // new indexes to the created anonymous type templates
            if (!this.AreTemplatesSealed)
            {
                // If we are emitting .NET module, include module's name into type's name to ensure
                // uniqueness across added modules.
                string moduleId;

                if (moduleBeingBuilt.OutputKind == OutputKind.NetModule)
                {
                    moduleId = moduleBeingBuilt.Name;

                    string extension = OutputKind.NetModule.GetDefaultExtension();

                    if (moduleId.EndsWith(extension, StringComparison.OrdinalIgnoreCase))
                    {
                        moduleId = moduleId.Substring(0, moduleId.Length - extension.Length);
                    }

                    moduleId = MetadataHelpers.MangleForTypeNameIfNeeded(moduleId);
                }
                else
                {
                    moduleId = string.Empty;
                }

                int nextIndex = moduleBeingBuilt.GetNextAnonymousTypeIndex();
                foreach (var template in builder)
                {
                    string name;
                    int    index;
                    if (!moduleBeingBuilt.TryGetAnonymousTypeName(template, out name, out index))
                    {
                        index = nextIndex++;
                        name  = GeneratedNames.MakeAnonymousTypeTemplateName(index, this.Compilation.GetSubmissionSlotIndex(), moduleId);
                    }
                    // normally it should only happen once, but in case there is a race
                    // NameAndIndex.set has an assert which guarantees that the
                    // template name provided is the same as the one already assigned
                    template.NameAndIndex = new NameAndIndex(name, index);
                }

                this.SealTemplates();
            }

            if (builder.Count > 0 && !ReportMissingOrErroneousSymbols(diagnostics))
            {
                // Process all the templates
                foreach (var template in builder)
                {
                    foreach (var method in template.SpecialMembers)
                    {
                        moduleBeingBuilt.AddSynthesizedDefinition(template, method.GetCciAdapter());
                    }

                    compiler.Visit(template, null);
                }
            }

            builder.Free();

            // Ensure all previous synthesized delegates are included so the
            // types are available for subsequent edit and continue generations.
            foreach (var key in moduleBeingBuilt.GetPreviousSynthesizedDelegates())
            {
                if (GeneratedNames.TryParseSynthesizedDelegateName(key.Name, out var refKinds, out var returnsVoid, out var generation, out var parameterCount))
                {
                    var delegateKey = new SynthesizedDelegateKey(parameterCount, refKinds, returnsVoid, generation);
                    this.SynthesizedDelegates.GetOrAdd(delegateKey, (k, args) => CreatePlaceholderSynthesizedDelegateValue(key.Name, args.refKinds, args.returnsVoid, args.parameterCount), (refKinds, returnsVoid, parameterCount));
                }
            }

            var synthesizedDelegates = ArrayBuilder <SynthesizedDelegateSymbol> .GetInstance();

            GetCreatedSynthesizedDelegates(synthesizedDelegates);
            foreach (var synthesizedDelegate in synthesizedDelegates)
            {
                compiler.Visit(synthesizedDelegate, null);
            }
            synthesizedDelegates.Free();
        }