Exemplo n.º 1
0
 internal ILScannerBuilder(CompilerTypeSystemContext context, CompilationModuleGroup compilationGroup, NameMangler mangler, ILProvider ilProvider)
 {
     _context          = context;
     _compilationGroup = compilationGroup;
     _nameMangler      = mangler;
     _metadataManager  = new EmptyMetadataManager(context);
     _ilProvider       = ilProvider;
 }
Exemplo n.º 2
0
 public PreinitializationInfoHashtable(CompilationModuleGroup compilationGroup, ILProvider ilProvider)
 {
     _compilationGroup = compilationGroup;
     _ilProvider       = ilProvider;
 }
        public void AttachToDependencyGraph(DependencyAnalyzerBase <NodeFactory> graph, ILProvider ilProvider)
        {
            graph.ComputingDependencyPhaseChange += Graph_ComputingDependencyPhaseChange;

            var compilerIdentifierNode = new CompilerIdentifierNode(Target);

            Header.Add(Internal.Runtime.ReadyToRunSectionType.CompilerIdentifier, compilerIdentifierNode, compilerIdentifierNode);

            RuntimeFunctionsTable = new RuntimeFunctionsTableNode(this);
            Header.Add(Internal.Runtime.ReadyToRunSectionType.RuntimeFunctions, RuntimeFunctionsTable, RuntimeFunctionsTable);

            RuntimeFunctionsGCInfo = new RuntimeFunctionsGCInfoNode();
            graph.AddRoot(RuntimeFunctionsGCInfo, "GC info is always generated");

            DelayLoadMethodCallThunks = new DelayLoadMethodCallThunkNodeRange();
            Header.Add(Internal.Runtime.ReadyToRunSectionType.DelayLoadMethodCallThunks, DelayLoadMethodCallThunks, DelayLoadMethodCallThunks);

            ExceptionInfoLookupTableNode exceptionInfoLookupTableNode = new ExceptionInfoLookupTableNode(this);

            Header.Add(Internal.Runtime.ReadyToRunSectionType.ExceptionInfo, exceptionInfoLookupTableNode, exceptionInfoLookupTableNode);
            graph.AddRoot(exceptionInfoLookupTableNode, "ExceptionInfoLookupTable is always generated");

            ManifestMetadataTable = new ManifestMetadataTableNode(this);
            Header.Add(Internal.Runtime.ReadyToRunSectionType.ManifestMetadata, ManifestMetadataTable, ManifestMetadataTable);
            Resolver.SetModuleIndexLookup(ManifestMetadataTable.ModuleToIndex);
            ((ReadyToRunILProvider)ilProvider).InitManifestMutableModule(ManifestMetadataTable._mutableModule);
            Resolver.InitManifestMutableModule(ManifestMetadataTable._mutableModule);

            ManifestAssemblyMvidHeaderNode mvidTableNode = new ManifestAssemblyMvidHeaderNode(ManifestMetadataTable);

            Header.Add(Internal.Runtime.ReadyToRunSectionType.ManifestAssemblyMvids, mvidTableNode, mvidTableNode);

            AssemblyTableNode assemblyTable = null;

            if (CompilationModuleGroup.IsCompositeBuildMode)
            {
                assemblyTable = new AssemblyTableNode(Target);
                Header.Add(Internal.Runtime.ReadyToRunSectionType.ComponentAssemblies, assemblyTable, assemblyTable);
            }

            // Generate per assembly header tables
            int assemblyIndex = -1;

            foreach (EcmaModule inputModule in CompilationModuleGroup.CompilationModuleSet)
            {
                assemblyIndex++;
                HeaderNode tableHeader = Header;
                if (assemblyTable != null)
                {
                    AssemblyHeaderNode perAssemblyHeader = new AssemblyHeaderNode(Target, ReadyToRunFlags.READYTORUN_FLAG_Component, assemblyIndex);
                    assemblyTable.Add(perAssemblyHeader);
                    tableHeader = perAssemblyHeader;
                }

                MethodEntryPointTableNode methodEntryPointTable = new MethodEntryPointTableNode(inputModule, Target);
                tableHeader.Add(Internal.Runtime.ReadyToRunSectionType.MethodDefEntryPoints, methodEntryPointTable, methodEntryPointTable);

                TypesTableNode typesTable = new TypesTableNode(Target, inputModule);
                tableHeader.Add(Internal.Runtime.ReadyToRunSectionType.AvailableTypes, typesTable, typesTable);

                if (CompilationModuleGroup.IsCompositeBuildMode)
                {
                    InliningInfoNode inliningInfoTable = new InliningInfoNode(Target, inputModule, InliningInfoNode.InfoType.InliningInfo2);
                    tableHeader.Add(Internal.Runtime.ReadyToRunSectionType.InliningInfo2, inliningInfoTable, inliningInfoTable);
                }

                // Core library attributes are checked FAR more often than other dlls
                // attributes, so produce a highly efficient table for determining if they are
                // present. Other assemblies *MAY* benefit from this feature, but it doesn't show
                // as useful at this time.
                if (inputModule == TypeSystemContext.SystemModule)
                {
                    AttributePresenceFilterNode attributePresenceTable = new AttributePresenceFilterNode(inputModule);
                    tableHeader.Add(Internal.Runtime.ReadyToRunSectionType.AttributePresence, attributePresenceTable, attributePresenceTable);
                }
            }

            InliningInfoNode crossModuleInliningInfoTable = new InliningInfoNode(Target, null,
                                                                                 CompilationModuleGroup.IsCompositeBuildMode ? InliningInfoNode.InfoType.CrossModuleInliningForCrossModuleDataOnly : InliningInfoNode.InfoType.CrossModuleAllMethods);

            Header.Add(Internal.Runtime.ReadyToRunSectionType.CrossModuleInlineInfo, crossModuleInliningInfoTable, crossModuleInliningInfoTable);
            this.CrossModuleInlningInfo = crossModuleInliningInfoTable;

            InstanceEntryPointTable = new InstanceEntryPointTableNode(this);
            Header.Add(Internal.Runtime.ReadyToRunSectionType.InstanceMethodEntryPoints, InstanceEntryPointTable, InstanceEntryPointTable);

            ImportSectionsTable = new ImportSectionsTableNode(this);
            Header.Add(Internal.Runtime.ReadyToRunSectionType.ImportSections, ImportSectionsTable, ImportSectionsTable.StartSymbol);

            DebugInfoTable = new DebugInfoTableNode(Target);
            Header.Add(Internal.Runtime.ReadyToRunSectionType.DebugInfo, DebugInfoTable, DebugInfoTable);

            EagerImports = new ImportSectionNode(
                "EagerImports",
                ReadyToRunImportSectionType.Unknown,
                ReadyToRunImportSectionFlags.Eager,
                (byte)Target.PointerSize,
                emitPrecode: false,
                emitGCRefMap: false);
            ImportSectionsTable.AddEmbeddedObject(EagerImports);

            // All ready-to-run images have a module import helper which gets patched by the runtime on image load
            ModuleImport = new Import(EagerImports, new ReadyToRunHelperSignature(
                                          ReadyToRunHelper.Module));
            graph.AddRoot(ModuleImport, "Module import is required by the R2R format spec");

            if (Target.Architecture != TargetArchitecture.X86)
            {
                Import personalityRoutineImport = new Import(EagerImports, new ReadyToRunHelperSignature(
                                                                 ReadyToRunHelper.PersonalityRoutine));
                PersonalityRoutine = new ImportThunk(this,
                                                     ReadyToRunHelper.PersonalityRoutine, EagerImports, useVirtualCall: false, useJumpableStub: false);
                graph.AddRoot(PersonalityRoutine, "Personality routine is faster to root early rather than referencing it from each unwind info");

                Import filterFuncletPersonalityRoutineImport = new Import(EagerImports, new ReadyToRunHelperSignature(
                                                                              ReadyToRunHelper.PersonalityRoutineFilterFunclet));
                FilterFuncletPersonalityRoutine = new ImportThunk(this,
                                                                  ReadyToRunHelper.PersonalityRoutineFilterFunclet, EagerImports, useVirtualCall: false, useJumpableStub: false);
                graph.AddRoot(FilterFuncletPersonalityRoutine, "Filter funclet personality routine is faster to root early rather than referencing it from each unwind info");
            }

            if ((ProfileDataManager != null) && (ProfileDataManager.EmbedPgoDataInR2RImage))
            {
                // Profile instrumentation data attaches here
                HashSet <MethodDesc> methodsToInsertInstrumentationDataFor = new HashSet <MethodDesc>();
                foreach (EcmaModule inputModule in CompilationModuleGroup.CompilationModuleSet)
                {
                    foreach (MethodDesc method in ProfileDataManager.GetMethodsForModuleDesc(inputModule))
                    {
                        if (ProfileDataManager[method].SchemaData != null)
                        {
                            methodsToInsertInstrumentationDataFor.Add(method);
                        }
                    }
                }
                if (methodsToInsertInstrumentationDataFor.Count != 0)
                {
                    MethodDesc[] methodsToInsert = methodsToInsertInstrumentationDataFor.ToArray();
                    methodsToInsert.MergeSort(TypeSystemComparer.Instance.Compare);
                    InstrumentationDataTable = new InstrumentationDataTableNode(this, methodsToInsert, ProfileDataManager);
                    Header.Add(Internal.Runtime.ReadyToRunSectionType.PgoInstrumentationData, InstrumentationDataTable, InstrumentationDataTable);
                }
            }

            ILBodyPrecodeImports = new ImportSectionNode(
                "A_ILBodyPrecodeImports",
                ReadyToRunImportSectionType.Unknown,
                ReadyToRunImportSectionFlags.None,
                (byte)Target.PointerSize,
                emitPrecode: true,
                emitGCRefMap: false);
            ImportSectionsTable.AddEmbeddedObject(ILBodyPrecodeImports);

            MethodImports = new ImportSectionNode(
                "MethodImports",
                ReadyToRunImportSectionType.StubDispatch,
                ReadyToRunImportSectionFlags.PCode,
                (byte)Target.PointerSize,
                emitPrecode: false,
                emitGCRefMap: true);
            ImportSectionsTable.AddEmbeddedObject(MethodImports);

            DispatchImports = new ImportSectionNode(
                "DispatchImports",
                ReadyToRunImportSectionType.StubDispatch,
                ReadyToRunImportSectionFlags.PCode,
                (byte)Target.PointerSize,
                emitPrecode: false,
                emitGCRefMap: true);
            ImportSectionsTable.AddEmbeddedObject(DispatchImports);

            HelperImports = new ImportSectionNode(
                "HelperImports",
                ReadyToRunImportSectionType.Unknown,
                ReadyToRunImportSectionFlags.PCode,
                (byte)Target.PointerSize,
                emitPrecode: false,
                emitGCRefMap: false);
            ImportSectionsTable.AddEmbeddedObject(HelperImports);

            PrecodeImports = new ImportSectionNode(
                "PrecodeImports",
                ReadyToRunImportSectionType.Unknown,
                ReadyToRunImportSectionFlags.PCode,
                (byte)Target.PointerSize,
                emitPrecode: true,
                emitGCRefMap: false);
            ImportSectionsTable.AddEmbeddedObject(PrecodeImports);

            StringImports = new ImportSectionNode(
                "StringImports",
                ReadyToRunImportSectionType.StringHandle,
                ReadyToRunImportSectionFlags.None,
                (byte)Target.PointerSize,
                emitPrecode: true,
                emitGCRefMap: false);
            ImportSectionsTable.AddEmbeddedObject(StringImports);

            graph.AddRoot(ImportSectionsTable, "Import sections table is always generated");
            graph.AddRoot(ModuleImport, "Module import is always generated");
            graph.AddRoot(EagerImports, "Eager imports are always generated");
            graph.AddRoot(MethodImports, "Method imports are always generated");
            graph.AddRoot(DispatchImports, "Dispatch imports are always generated");
            graph.AddRoot(HelperImports, "Helper imports are always generated");
            graph.AddRoot(PrecodeImports, "Precode helper imports are always generated");
            graph.AddRoot(ILBodyPrecodeImports, "IL body precode imports are always generated");
            graph.AddRoot(StringImports, "String imports are always generated");
            graph.AddRoot(Header, "ReadyToRunHeader is always generated");
            graph.AddRoot(CopiedCorHeaderNode, "MSIL COR header is always generated for R2R files");
            graph.AddRoot(DebugDirectoryNode, "Debug Directory will always contain at least one entry");

            if (Win32ResourcesNode != null)
            {
                graph.AddRoot(Win32ResourcesNode, "Win32 Resources are placed if not empty");
            }

            MetadataManager.AttachToDependencyGraph(graph, this);
        }
Exemplo n.º 4
0
        internal ReadyToRunCodegenCompilation(
            DependencyAnalyzerBase <NodeFactory> dependencyGraph,
            NodeFactory nodeFactory,
            IEnumerable <ICompilationRootProvider> roots,
            ILProvider ilProvider,
            Logger logger,
            DevirtualizationManager devirtualizationManager,
            IEnumerable <string> inputFiles,
            string compositeRootPath,
            InstructionSetSupport instructionSetSupport,
            bool resilient,
            bool generateMapFile,
            bool generateMapCsvFile,
            bool generatePdbFile,
            Func <MethodDesc, string> printReproInstructions,
            string pdbPath,
            bool generatePerfMapFile,
            string perfMapPath,
            Guid?perfMapMvid,
            bool generateProfileFile,
            int parallelism,
            ProfileDataManager profileData,
            ReadyToRunMethodLayoutAlgorithm methodLayoutAlgorithm,
            ReadyToRunFileLayoutAlgorithm fileLayoutAlgorithm,
            int customPESectionAlignment,
            bool verifyTypeAndFieldLayout)
            : base(
                dependencyGraph,
                nodeFactory,
                roots,
                ilProvider,
                devirtualizationManager,
                modulesBeingInstrumented: nodeFactory.CompilationModuleGroup.CompilationModuleSet,
                logger,
                instructionSetSupport)
        {
            _resilient                = resilient;
            _parallelism              = parallelism;
            _generateMapFile          = generateMapFile;
            _generateMapCsvFile       = generateMapCsvFile;
            _generatePdbFile          = generatePdbFile;
            _pdbPath                  = pdbPath;
            _generatePerfMapFile      = generatePerfMapFile;
            _perfMapPath              = perfMapPath;
            _perfMapMvid              = perfMapMvid;
            _generateProfileFile      = generateProfileFile;
            _customPESectionAlignment = customPESectionAlignment;
            SymbolNodeFactory         = new ReadyToRunSymbolNodeFactory(nodeFactory, verifyTypeAndFieldLayout);
            if (nodeFactory.InstrumentationDataTable != null)
            {
                nodeFactory.InstrumentationDataTable.Initialize(SymbolNodeFactory);
            }
            _corInfoImpls           = new ConditionalWeakTable <Thread, CorInfoImpl>();
            _inputFiles             = inputFiles;
            _compositeRootPath      = compositeRootPath;
            _printReproInstructions = printReproInstructions;
            CompilationModuleGroup  = (ReadyToRunCompilationModuleGroupBase)nodeFactory.CompilationModuleGroup;

            // Generate baseline support specification for InstructionSetSupport. This will prevent usage of the generated
            // code if the runtime environment doesn't support the specified instruction set
            string instructionSetSupportString = ReadyToRunInstructionSetSupportSignature.ToInstructionSetSupportString(instructionSetSupport);
            ReadyToRunInstructionSetSupportSignature instructionSetSupportSig = new ReadyToRunInstructionSetSupportSignature(instructionSetSupportString);

            _dependencyGraph.AddRoot(new Import(NodeFactory.EagerImports, instructionSetSupportSig), "Baseline instruction set support");

            _profileData = profileData;

            _fileLayoutOptimizer = new ReadyToRunFileLayoutOptimizer(methodLayoutAlgorithm, fileLayoutAlgorithm, profileData, _nodeFactory);
        }
Exemplo n.º 5
0
 public override CompilationBuilder UseILProvider(ILProvider ilProvider)
 {
     _ilProvider = ilProvider;
     return(this);
 }
Exemplo n.º 6
0
        private int Run(string[] args)
        {
            InitializeDefaultOptions();

            ArgumentSyntax syntax = ParseCommandLine(args);

            if (_help)
            {
                Help(syntax.GetHelpText());
                return(1);
            }

            if (_outputFilePath == null)
            {
                throw new CommandLineException("Output filename must be specified (/out <file>)");
            }

            //
            // Set target Architecture and OS
            //
            if (_targetArchitectureStr != null)
            {
                if (_targetArchitectureStr.Equals("x86", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.X86;
                }
                else if (_targetArchitectureStr.Equals("x64", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.X64;
                }
                else if (_targetArchitectureStr.Equals("arm", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.ARM;
                }
                else if (_targetArchitectureStr.Equals("armel", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.ARM;
                }
                else if (_targetArchitectureStr.Equals("arm64", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.ARM64;
                }
                else if (_targetArchitectureStr.Equals("wasm", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.Wasm32;
                    _isWasmCodegen      = true;
                }
                else
                {
                    throw new CommandLineException("Target architecture is not supported");
                }
            }
            if (_targetOSStr != null)
            {
                if (_targetOSStr.Equals("windows", StringComparison.OrdinalIgnoreCase))
                {
                    _targetOS = TargetOS.Windows;
                }
                else if (_targetOSStr.Equals("linux", StringComparison.OrdinalIgnoreCase))
                {
                    _targetOS = TargetOS.Linux;
                }
                else if (_targetOSStr.Equals("osx", StringComparison.OrdinalIgnoreCase))
                {
                    _targetOS = TargetOS.OSX;
                }
                else
                {
                    throw new CommandLineException("Target OS is not supported");
                }
            }

            if (_isWasmCodegen)
            {
                _targetArchitecture = TargetArchitecture.Wasm32;
            }

            bool supportsReflection = !_disableReflection && !_isReadyToRunCodeGen && _systemModuleName == DefaultSystemModule;

            //
            // Initialize type system context
            //

            SharedGenericsMode genericsMode = _useSharedGenerics || !_isWasmCodegen ?
                                              SharedGenericsMode.CanonicalReferenceTypes : SharedGenericsMode.Disabled;

            // TODO: compiler switch for SIMD support?
            var simdVectorLength = (_isCppCodegen || _isWasmCodegen) ? SimdVectorLength.None : SimdVectorLength.Vector128Bit;
            var targetAbi        = _isCppCodegen ? TargetAbi.CppCodegen : TargetAbi.CoreRT;
            var targetDetails    = new TargetDetails(_targetArchitecture, _targetOS, targetAbi, simdVectorLength);
            CompilerTypeSystemContext typeSystemContext = (_isReadyToRunCodeGen
                ? new ReadyToRunCompilerContext(targetDetails, genericsMode)
                : new CompilerTypeSystemContext(targetDetails, genericsMode, supportsReflection ? DelegateFeature.All : 0));

            //
            // TODO: To support our pre-compiled test tree, allow input files that aren't managed assemblies since
            // some tests contain a mixture of both managed and native binaries.
            //
            // See: https://github.com/dotnet/corert/issues/2785
            //
            // When we undo this this hack, replace this foreach with
            //  typeSystemContext.InputFilePaths = _inputFilePaths;
            //
            Dictionary <string, string> inputFilePaths = new Dictionary <string, string>();

            foreach (var inputFile in _inputFilePaths)
            {
                try
                {
                    var module = typeSystemContext.GetModuleFromPath(inputFile.Value);
                    inputFilePaths.Add(inputFile.Key, inputFile.Value);
                }
                catch (TypeSystemException.BadImageFormatException)
                {
                    // Keep calm and carry on.
                }
            }

            typeSystemContext.InputFilePaths     = inputFilePaths;
            typeSystemContext.ReferenceFilePaths = _referenceFilePaths;

            typeSystemContext.SetSystemModule(typeSystemContext.GetModuleForSimpleName(_systemModuleName));

            if (typeSystemContext.InputFilePaths.Count == 0)
            {
                throw new CommandLineException("No input files specified");
            }

            //
            // Initialize compilation group and compilation roots
            //

            // Single method mode?
            MethodDesc singleMethod = CheckAndParseSingleMethodModeArguments(typeSystemContext);

            CompilationModuleGroup          compilationGroup;
            List <ICompilationRootProvider> compilationRoots = new List <ICompilationRootProvider>();

            if (singleMethod != null)
            {
                // Compiling just a single method
                compilationGroup = new SingleMethodCompilationModuleGroup(singleMethod);
                compilationRoots.Add(new SingleMethodRootProvider(singleMethod));
            }
            else
            {
                // Either single file, or multifile library, or multifile consumption.
                EcmaModule entrypointModule          = null;
                bool       systemModuleIsInputModule = false;
                foreach (var inputFile in typeSystemContext.InputFilePaths)
                {
                    EcmaModule module = typeSystemContext.GetModuleFromPath(inputFile.Value);

                    if (module.PEReader.PEHeaders.IsExe)
                    {
                        if (entrypointModule != null)
                        {
                            throw new Exception("Multiple EXE modules");
                        }
                        entrypointModule = module;
                    }

                    if (module == typeSystemContext.SystemModule)
                    {
                        systemModuleIsInputModule = true;
                    }

                    if (!_isReadyToRunCodeGen)
                    {
                        compilationRoots.Add(new ExportedMethodsRootProvider(module));
                    }
                }

                if (entrypointModule != null && !_isReadyToRunCodeGen)
                {
                    compilationRoots.Add(new MainMethodRootProvider(entrypointModule, CreateInitializerList(typeSystemContext)));
                    compilationRoots.Add(new RuntimeConfigurationRootProvider(_runtimeOptions));
                }

                if (_isReadyToRunCodeGen)
                {
                    List <EcmaModule> inputModules = new List <EcmaModule>();

                    foreach (var inputFile in typeSystemContext.InputFilePaths)
                    {
                        EcmaModule module = typeSystemContext.GetModuleFromPath(inputFile.Value);
                        compilationRoots.Add(new ReadyToRunRootProvider(module));
                        inputModules.Add(module);

                        if (!_isInputVersionBubble)
                        {
                            break;
                        }
                    }


                    List <ModuleDesc> versionBubbleModules = new List <ModuleDesc>();
                    if (_isInputVersionBubble)
                    {
                        // In large version bubble mode add reference paths to the compilation group
                        foreach (string referenceFile in _referenceFilePaths.Values)
                        {
                            try
                            {
                                // Currently SimpleTest.targets has no easy way to filter out non-managed assemblies
                                // from the reference list.
                                EcmaModule module = typeSystemContext.GetModuleFromPath(referenceFile);
                                versionBubbleModules.Add(module);
                            }
                            catch (TypeSystemException.BadImageFormatException ex)
                            {
                                Console.WriteLine("Warning: cannot open reference assembly '{0}': {1}", referenceFile, ex.Message);
                            }
                        }
                    }

                    compilationGroup = new ReadyToRunSingleAssemblyCompilationModuleGroup(
                        typeSystemContext, inputModules, versionBubbleModules);
                }
                else if (_multiFile)
                {
                    List <EcmaModule> inputModules = new List <EcmaModule>();

                    foreach (var inputFile in typeSystemContext.InputFilePaths)
                    {
                        EcmaModule module = typeSystemContext.GetModuleFromPath(inputFile.Value);

                        if (entrypointModule == null)
                        {
                            // This is a multifile production build - we need to root all methods
                            compilationRoots.Add(new LibraryRootProvider(module));
                        }
                        inputModules.Add(module);
                    }

                    compilationGroup = new MultiFileSharedCompilationModuleGroup(typeSystemContext, inputModules);
                }
                else
                {
                    if (entrypointModule == null && !_nativeLib)
                    {
                        throw new Exception("No entrypoint module");
                    }

                    if (!systemModuleIsInputModule)
                    {
                        compilationRoots.Add(new ExportedMethodsRootProvider((EcmaModule)typeSystemContext.SystemModule));
                    }
                    compilationGroup = new SingleFileCompilationModuleGroup();
                }

                if (_nativeLib)
                {
                    // Set owning module of generated native library startup method to compiler generated module,
                    // to ensure the startup method is included in the object file during multimodule mode build
                    compilationRoots.Add(new NativeLibraryInitializerRootProvider(typeSystemContext.GeneratedAssembly, CreateInitializerList(typeSystemContext)));
                    compilationRoots.Add(new RuntimeConfigurationRootProvider(_runtimeOptions));
                }

                if (_rdXmlFilePaths.Count > 0)
                {
                    Console.WriteLine("Warning: RD.XML processing will change before release (https://github.com/dotnet/corert/issues/5001)");
                }
                foreach (var rdXmlFilePath in _rdXmlFilePaths)
                {
                    compilationRoots.Add(new RdXmlRootProvider(typeSystemContext, rdXmlFilePath));
                }
            }

            //
            // Compile
            //

            CompilationBuilder builder;

            if (_isWasmCodegen)
            {
                builder = new WebAssemblyCodegenCompilationBuilder(typeSystemContext, compilationGroup);
            }
            else if (_isReadyToRunCodeGen)
            {
                string inputFilePath = "";
                foreach (var input in typeSystemContext.InputFilePaths)
                {
                    inputFilePath = input.Value;
                    break;
                }
                builder = new ReadyToRunCodegenCompilationBuilder(typeSystemContext, compilationGroup, inputFilePath);
            }
            else if (_isCppCodegen)
            {
                builder = new CppCodegenCompilationBuilder(typeSystemContext, compilationGroup);
            }
            else
            {
                builder = new RyuJitCompilationBuilder(typeSystemContext, compilationGroup);
            }

            string compilationUnitPrefix = _multiFile ? System.IO.Path.GetFileNameWithoutExtension(_outputFilePath) : "";

            builder.UseCompilationUnitPrefix(compilationUnitPrefix);

            if (!_isCppCodegen && !_isWasmCodegen)
            {
                builder.UsePInvokePolicy(new ConfigurablePInvokePolicy(typeSystemContext.Target));
            }

            RemovedFeature removedFeatures = 0;

            foreach (string feature in _removedFeatures)
            {
                if (feature == "EventSource")
                {
                    removedFeatures |= RemovedFeature.Etw;
                }
                else if (feature == "FrameworkStrings")
                {
                    removedFeatures |= RemovedFeature.FrameworkResources;
                }
                else if (feature == "Globalization")
                {
                    removedFeatures |= RemovedFeature.Globalization;
                }
                else if (feature == "Comparers")
                {
                    removedFeatures |= RemovedFeature.Comparers;
                }
                else if (feature == "CurlHandler")
                {
                    removedFeatures |= RemovedFeature.CurlHandler;
                }
            }

            ILProvider ilProvider = _isReadyToRunCodeGen ? (ILProvider) new ReadyToRunILProvider() : new CoreRTILProvider();

            if (removedFeatures != 0)
            {
                ilProvider = new RemovingILProvider(ilProvider, removedFeatures);
            }

            var stackTracePolicy = _emitStackTraceData ?
                                   (StackTraceEmissionPolicy) new EcmaMethodStackTraceEmissionPolicy() : new NoStackTraceEmissionPolicy();

            MetadataBlockingPolicy mdBlockingPolicy = _noMetadataBlocking
                    ? (MetadataBlockingPolicy) new NoMetadataBlockingPolicy()
                    : new BlockedInternalsBlockingPolicy(typeSystemContext);

            ManifestResourceBlockingPolicy resBlockingPolicy = (removedFeatures & RemovedFeature.FrameworkResources) != 0 ?
                                                               new FrameworkStringResourceBlockingPolicy() : (ManifestResourceBlockingPolicy) new NoManifestResourceBlockingPolicy();

            UsageBasedMetadataGenerationOptions metadataGenerationOptions = UsageBasedMetadataGenerationOptions.AnonymousTypeHeuristic;

            if (_completeTypesMetadata)
            {
                metadataGenerationOptions |= UsageBasedMetadataGenerationOptions.CompleteTypesOnly;
            }
            if (_scanReflection)
            {
                metadataGenerationOptions |= UsageBasedMetadataGenerationOptions.ILScanning;
            }
            if (_rootAllApplicationAssemblies)
            {
                metadataGenerationOptions |= UsageBasedMetadataGenerationOptions.FullUserAssemblyRooting;
            }

            DynamicInvokeThunkGenerationPolicy invokeThunkGenerationPolicy = new DefaultDynamicInvokeThunkGenerationPolicy();

            MetadataManager metadataManager;

            if (_isReadyToRunCodeGen)
            {
                metadataManager = new ReadyToRunTableManager(typeSystemContext);
            }
            else if (supportsReflection)
            {
                metadataManager = new UsageBasedMetadataManager(
                    compilationGroup,
                    typeSystemContext,
                    mdBlockingPolicy,
                    resBlockingPolicy,
                    _metadataLogFileName,
                    stackTracePolicy,
                    invokeThunkGenerationPolicy,
                    ilProvider,
                    metadataGenerationOptions);
            }
            else
            {
                metadataManager = new EmptyMetadataManager(typeSystemContext);
            }

            // Unless explicitly opted in at the command line, we enable scanner for retail builds by default.
            // We don't do this for CppCodegen and Wasm, because those codegens are behind.
            // We also don't do this for multifile because scanner doesn't simulate inlining (this would be
            // fixable by using a CompilationGroup for the scanner that has a bigger worldview, but
            // let's cross that bridge when we get there).
            bool useScanner = _useScanner ||
                              (_optimizationMode != OptimizationMode.None && !_isCppCodegen && !_isWasmCodegen && !_isReadyToRunCodeGen && !_multiFile);

            useScanner &= !_noScanner;

            builder.UseILProvider(ilProvider);

            ILScanResults scanResults = null;

            if (useScanner)
            {
                ILScannerBuilder scannerBuilder = builder.GetILScannerBuilder()
                                                  .UseCompilationRoots(compilationRoots)
                                                  .UseMetadataManager(metadataManager);

                if (_scanDgmlLogFileName != null)
                {
                    scannerBuilder.UseDependencyTracking(_generateFullScanDgmlLog ? DependencyTrackingLevel.All : DependencyTrackingLevel.First);
                }

                IILScanner scanner = scannerBuilder.ToILScanner();

                scanResults = scanner.Scan();

                if (metadataManager is UsageBasedMetadataManager usageBasedManager)
                {
                    metadataManager = usageBasedManager.ToAnalysisBasedMetadataManager();
                }
            }

            var logger = new Logger(Console.Out, _isVerbose);

            DebugInformationProvider debugInfoProvider = _enableDebugInfo ?
                                                         (_ilDump == null ? new DebugInformationProvider() : new ILAssemblyGeneratingMethodDebugInfoProvider(_ilDump, new EcmaOnlyDebugInformationProvider())) :
                                                         new NullDebugInformationProvider();

            DependencyTrackingLevel trackingLevel = _dgmlLogFileName == null ?
                                                    DependencyTrackingLevel.None : (_generateFullDgmlLog ? DependencyTrackingLevel.All : DependencyTrackingLevel.First);

            compilationRoots.Add(metadataManager);

            builder
            .UseBackendOptions(_codegenOptions)
            .UseMethodBodyFolding(_methodBodyFolding)
            .UseMetadataManager(metadataManager)
            .UseLogger(logger)
            .UseDependencyTracking(trackingLevel)
            .UseCompilationRoots(compilationRoots)
            .UseOptimizationMode(_optimizationMode)
            .UseDebugInfoProvider(debugInfoProvider);

            if (scanResults != null)
            {
                // If we have a scanner, feed the vtable analysis results to the compilation.
                // This could be a command line switch if we really wanted to.
                builder.UseVTableSliceProvider(scanResults.GetVTableLayoutInfo());

                // If we have a scanner, feed the generic dictionary results to the compilation.
                // This could be a command line switch if we really wanted to.
                builder.UseGenericDictionaryLayoutProvider(scanResults.GetDictionaryLayoutInfo());

                // If we feed any outputs of the scanner into the compilation, it's essential
                // we use scanner's devirtualization manager. It prevents optimizing codegens
                // from accidentally devirtualizing cases that can never happen at runtime
                // (e.g. devirtualizing a method on a type that never gets allocated).
                builder.UseDevirtualizationManager(scanResults.GetDevirtualizationManager());
            }

            ICompilation compilation = builder.ToCompilation();

            ObjectDumper dumper = _mapFileName != null ? new ObjectDumper(_mapFileName) : null;

            CompilationResults compilationResults = compilation.Compile(_outputFilePath, dumper);

            if (_exportsFile != null)
            {
                ExportsFileWriter defFileWriter = new ExportsFileWriter(typeSystemContext, _exportsFile);
                foreach (var compilationRoot in compilationRoots)
                {
                    if (compilationRoot is ExportedMethodsRootProvider provider)
                    {
                        defFileWriter.AddExportedMethods(provider.ExportedMethods);
                    }
                }

                defFileWriter.EmitExportedMethods();
            }

            if (_dgmlLogFileName != null)
            {
                compilationResults.WriteDependencyLog(_dgmlLogFileName);
            }

            if (scanResults != null)
            {
                SimdHelper simdHelper = new SimdHelper();

                if (_scanDgmlLogFileName != null)
                {
                    scanResults.WriteDependencyLog(_scanDgmlLogFileName);
                }

                // If the scanner and compiler don't agree on what to compile, the outputs of the scanner might not actually be usable.
                // We are going to check this two ways:
                // 1. The methods and types generated during compilation are a subset of method and types scanned
                // 2. The methods and types scanned are a subset of methods and types compiled (this has a chance to hold for unoptimized builds only).

                // Check that methods and types generated during compilation are a subset of method and types scanned
                bool scanningFail = false;
                DiffCompilationResults(ref scanningFail, compilationResults.CompiledMethodBodies, scanResults.CompiledMethodBodies,
                                       "Methods", "compiled", "scanned", method => !(method.GetTypicalMethodDefinition() is EcmaMethod) || method.Name == "ThrowPlatformNotSupportedException");
                DiffCompilationResults(ref scanningFail, compilationResults.ConstructedEETypes, scanResults.ConstructedEETypes,
                                       "EETypes", "compiled", "scanned", type => !(type.GetTypeDefinition() is EcmaType));

                // If optimizations are enabled, the results will for sure not match in the other direction due to inlining, etc.
                // But there's at least some value in checking the scanner doesn't expand the universe too much in debug.
                if (_optimizationMode == OptimizationMode.None)
                {
                    // Check that methods and types scanned are a subset of methods and types compiled

                    // If we find diffs here, they're not critical, but still might be causing a Size on Disk regression.
                    bool dummy = false;

                    // We additionally skip methods in SIMD module because there's just too many intrisics to handle and IL scanner
                    // doesn't expand them. They would show up as noisy diffs.
                    DiffCompilationResults(ref dummy, scanResults.CompiledMethodBodies, compilationResults.CompiledMethodBodies,
                                           "Methods", "scanned", "compiled", method => !(method.GetTypicalMethodDefinition() is EcmaMethod) || simdHelper.IsSimdType(method.OwningType));
                    DiffCompilationResults(ref dummy, scanResults.ConstructedEETypes, compilationResults.ConstructedEETypes,
                                           "EETypes", "scanned", "compiled", type => !(type.GetTypeDefinition() is EcmaType));
                }

                if (scanningFail)
                {
                    throw new Exception("Scanning failure");
                }
            }

            if (debugInfoProvider is IDisposable)
            {
                ((IDisposable)debugInfoProvider).Dispose();
            }

            return(0);
        }
Exemplo n.º 7
0
 public CombinedILProvider(ILProvider primaryILProvider, PInvokeILProvider pinvokeILProvider)
 {
     _primaryILProvider = primaryILProvider;
     _pinvokeProvider   = pinvokeILProvider;
 }
Exemplo n.º 8
0
 public Logger(TextWriter writer, ILProvider ilProvider, bool isVerbose, IEnumerable <int> suppressedWarnings, bool singleWarn, IEnumerable <string> singleWarnEnabledModules, IEnumerable <string> singleWarnDisabledModules)
     : this(new TextLogWriter(writer), ilProvider, isVerbose, suppressedWarnings, singleWarn, singleWarnEnabledModules, singleWarnDisabledModules)
 {
 }
Exemplo n.º 9
0
 public Logger(ILogWriter writer, ILProvider ilProvider, bool isVerbose)
     : this(writer, ilProvider, isVerbose, Array.Empty <int>(), singleWarn : false, Array.Empty <string>(), Array.Empty <string>())
 {
 }
Exemplo n.º 10
0
 public InterproceduralState(ILProvider ilProvider, ValueSet <MethodBodyValue> methodBodies, HoistedLocalState hoistedLocals, InterproceduralStateLattice lattice)
 => (_ilProvider, MethodBodies, HoistedLocals, this.lattice) = (ilProvider, methodBodies, hoistedLocals, lattice);
Exemplo n.º 11
0
        private MetadataLoadedInfo LoadMetadata()
        {
            HashSet <ModuleDesc> metadataModules          = new HashSet <ModuleDesc>();
            MetadataType         typeWithMetadataMappings = (MetadataType)_metadataDescribingModule.GetTypeByCustomAttributeTypeName(MetadataMappingTypeName);

            MethodDesc fullMetadataMethod           = typeWithMetadataMappings.GetMethod("Metadata", null);
            MethodDesc weakMetadataMethod           = typeWithMetadataMappings.GetMethod("WeakMetadata", null);
            MethodDesc requiredGenericTypesMethod   = typeWithMetadataMappings.GetMethod("RequiredGenericTypes", null);
            MethodDesc requiredGenericMethodsMethod = typeWithMetadataMappings.GetMethod("RequiredGenericMethods", null);
            MethodDesc requiredGenericFieldsMethod  = typeWithMetadataMappings.GetMethod("RequiredGenericFields", null);
            MethodDesc requiredTemplatesMethod      = typeWithMetadataMappings.GetMethod("CompilerDeterminedInstantiations", null);

            ILProvider ilProvider = new ILProvider(null);

            MetadataLoadedInfo result = new MetadataLoadedInfo();

            if (fullMetadataMethod != null)
            {
                MethodIL fullMethodIL = ilProvider.GetMethodIL(fullMetadataMethod);
                ReadMetadataMethod(fullMethodIL, result.AllTypeMappings, result.MethodMappings, result.FieldMappings, metadataModules);
                foreach (var mapping in result.AllTypeMappings)
                {
                    result.TypesWithStrongMetadataMappings.Add(mapping.Key);
                }
            }

            if (weakMetadataMethod != null)
            {
                MethodIL weakMethodIL = ilProvider.GetMethodIL(weakMetadataMethod);
                Dictionary <MethodDesc, int> weakMethodMappings = new Dictionary <MethodDesc, int>();
                Dictionary <FieldDesc, int>  weakFieldMappings  = new Dictionary <FieldDesc, int>();
                ReadMetadataMethod(weakMethodIL, result.AllTypeMappings, weakMethodMappings, weakFieldMappings, metadataModules);
                if ((weakMethodMappings.Count > 0) || (weakFieldMappings.Count > 0))
                {
                    // the format does not permit weak field/method mappings
                    throw new BadImageFormatException();
                }
            }

            if (requiredGenericTypesMethod != null)
            {
                foreach (var type in ReadRequiredGenericsEntities(ilProvider.GetMethodIL(requiredGenericTypesMethod)))
                {
                    Debug.Assert(type is DefType);
                    result.RequiredGenericTypes.Add((TypeDesc)type);
                }
            }

            if (requiredGenericMethodsMethod != null)
            {
                foreach (var method in ReadRequiredGenericsEntities(ilProvider.GetMethodIL(requiredGenericMethodsMethod)))
                {
                    result.RequiredGenericMethods.Add((MethodDesc)method);
                }
            }

            if (requiredGenericFieldsMethod != null)
            {
                foreach (var field in ReadRequiredGenericsEntities(ilProvider.GetMethodIL(requiredGenericFieldsMethod)))
                {
                    result.RequiredGenericFields.Add((FieldDesc)field);
                }
            }

            if (requiredTemplatesMethod != null)
            {
                ReadRequiredTemplates(ilProvider.GetMethodIL(requiredTemplatesMethod),
                                      result.RequiredTemplateTypes,
                                      result.RequiredTemplateMethods,
                                      result.RequiredTemplateFields);
            }

            result.MetadataModules = ImmutableArray.CreateRange(metadataModules);

            ImmutableArray <ModuleDesc> .Builder externalMetadataModulesBuilder = ImmutableArray.CreateBuilder <ModuleDesc>();
            ImmutableArray <ModuleDesc> .Builder localMetadataModulesBuilder    = ImmutableArray.CreateBuilder <ModuleDesc>();
            foreach (ModuleDesc module in result.MetadataModules)
            {
                if (!_compilationModules.Contains(module))
                {
                    externalMetadataModulesBuilder.Add(module);
                }
                else
                {
                    localMetadataModulesBuilder.Add(module);
                }
            }
            result.ExternalMetadataModules = externalMetadataModulesBuilder.ToImmutable();
            result.LocalMetadataModules    = localMetadataModulesBuilder.ToImmutable();

            foreach (var pair in result.MethodMappings)
            {
                MethodDesc reflectableMethod = pair.Key;

                if (reflectableMethod.HasInstantiation)
                {
                    continue;
                }

                if (reflectableMethod.OwningType.HasInstantiation)
                {
                    continue;
                }

                MethodDesc typicalDynamicInvokeStub;
                if (!_dynamicInvokeStubs.Value.TryGetValue(reflectableMethod, out typicalDynamicInvokeStub))
                {
                    continue;
                }

                MethodDesc instantiatiatedDynamicInvokeStub = InstantiateCanonicalDynamicInvokeMethodForMethod(typicalDynamicInvokeStub, reflectableMethod);
                result.DynamicInvokeCompiledMethods.Add(instantiatiatedDynamicInvokeStub);
            }

            foreach (var reflectableMethod in result.RequiredGenericMethods)
            {
                MethodDesc typicalDynamicInvokeStub;
                if (!_dynamicInvokeStubs.Value.TryGetValue(reflectableMethod.GetTypicalMethodDefinition(), out typicalDynamicInvokeStub))
                {
                    continue;
                }

                MethodDesc instantiatiatedDynamicInvokeStub = InstantiateCanonicalDynamicInvokeMethodForMethod(typicalDynamicInvokeStub, reflectableMethod);
                result.DynamicInvokeCompiledMethods.Add(instantiatiatedDynamicInvokeStub);
            }

            return(result);
        }
Exemplo n.º 12
0
 public InterproceduralStateLattice(
     ILProvider ilProvider,
     ValueSetLattice <MethodBodyValue> methodBodyLattice,
     DictionaryLattice <HoistedLocalKey, MultiValue, ValueSetLattice <SingleValue> > hoistedLocalsLattice)
 => (_ilProvider, MethodBodyLattice, HoistedLocalsLattice) = (ilProvider, methodBodyLattice, hoistedLocalsLattice);
Exemplo n.º 13
0
 internal ILScannerBuilder(CompilerTypeSystemContext context, CompilationModuleGroup compilationGroup, NameMangler mangler, ILProvider ilProvider, PInvokeILEmitterConfiguration pinvokePolicy)
 {
     _context          = context;
     _compilationGroup = compilationGroup;
     _nameMangler      = mangler;
     _metadataManager  = new EmptyMetadataManager(context);
     _ilProvider       = ilProvider;
     _pinvokePolicy    = pinvokePolicy;
 }
Exemplo n.º 14
0
 public PreinitializationManager(TypeSystemContext context, CompilationModuleGroup compilationGroup, ILProvider ilprovider, bool enableInterpreter)
 {
     _supportsLazyCctors = context.SystemModule.GetType("System.Runtime.CompilerServices", "ClassConstructorRunner", throwIfNotFound: false) != null;
     _preinitHashTable   = new PreinitializationInfoHashtable(compilationGroup, ilprovider);
     _enableInterpreter  = enableInterpreter;
 }
Exemplo n.º 15
0
 internal ILScannerBuilder(CompilerTypeSystemContext context, CompilationModuleGroup compilationGroup, NameMangler mangler, ILProvider ilProvider, PreinitializationManager preinitializationManager)
 {
     _context                  = context;
     _compilationGroup         = compilationGroup;
     _nameMangler              = mangler;
     _metadataManager          = new AnalysisBasedMetadataManager(context);
     _ilProvider               = ilProvider;
     _preinitializationManager = preinitializationManager;
 }
Exemplo n.º 16
0
 public Logger(TextWriter writer, ILProvider ilProvider, bool isVerbose)
     : this(new TextLogWriter(writer), ilProvider, isVerbose)
 {
 }
Exemplo n.º 17
0
 public abstract CompilationBuilder UseILProvider(ILProvider ilProvider);
Exemplo n.º 18
0
 public TypeAnnotationsHashtable(Logger logger, ILProvider ilProvider) => (_logger, _ilProvider) = (logger, ilProvider);
Exemplo n.º 19
0
 public ILCache(ILProvider provider)
 {
     ILProvider = provider;
 }
Exemplo n.º 20
0
 public FlowAnnotations(Logger logger, ILProvider ilProvider)
 {
     _hashtable = new TypeAnnotationsHashtable(logger, ilProvider);
     _logger    = logger;
 }
        private MetadataLoadedInfo LoadMetadata()
        {
            HashSet<ModuleDesc> metadataModules = new HashSet<ModuleDesc>();
            MetadataType typeWithMetadataMappings = (MetadataType)_metadataDescribingModule.GetTypeByCustomAttributeTypeName(MetadataMappingTypeName);

            MethodDesc fullMetadataMethod = typeWithMetadataMappings.GetMethod("Metadata", null);
            MethodDesc weakMetadataMethod = typeWithMetadataMappings.GetMethod("WeakMetadata", null);

            ILProvider ilProvider = new ILProvider(null);

            MetadataLoadedInfo result = new MetadataLoadedInfo();

            if (fullMetadataMethod != null)
            {
                MethodIL fullMethodIL = ilProvider.GetMethodIL(fullMetadataMethod);
                ReadMetadataMethod(fullMethodIL, ref result.AllTypeMappings, ref result.MethodMappings, ref result.FieldMappings, ref metadataModules);
                foreach (var mapping in result.AllTypeMappings)
                {
                    result.TypesWithStrongMetadataMappings.Add(mapping.Key);
                }
            }

            if (weakMetadataMethod != null)
            {
                MethodIL weakMethodIL = ilProvider.GetMethodIL(weakMetadataMethod);
                Dictionary<MethodDesc, int> weakMethodMappings = new Dictionary<MethodDesc, int>();
                Dictionary<FieldDesc, int> weakFieldMappings = new Dictionary<FieldDesc, int>();
                ReadMetadataMethod(weakMethodIL, ref result.AllTypeMappings, ref weakMethodMappings, ref weakFieldMappings, ref metadataModules);
                if ((weakMethodMappings.Count > 0) || (weakFieldMappings.Count > 0))
                {
                    // the format does not permit weak field/method mappings
                    throw new BadImageFormatException();
                }
            }

            result.MetadataModules = ImmutableArray.CreateRange(metadataModules);

            ImmutableArray<ModuleDesc>.Builder externalMetadataModulesBuilder = ImmutableArray.CreateBuilder<ModuleDesc>();
            ImmutableArray<ModuleDesc>.Builder localMetadataModulesBuilder = ImmutableArray.CreateBuilder<ModuleDesc>();
            foreach (ModuleDesc module in result.MetadataModules)
            {
                if (!_compilationModules.Contains(module))
                    externalMetadataModulesBuilder.Add(module);
                else
                    localMetadataModulesBuilder.Add(module);
            }
            result.ExternalMetadataModules = externalMetadataModulesBuilder.ToImmutable();
            result.LocalMetadataModules = localMetadataModulesBuilder.ToImmutable();

            // TODO! Replace with something more complete that capture the generic instantiations that the pre-analysis
            // indicates should have been present
            foreach (var pair in result.MethodMappings)
            {
                MethodDesc reflectableMethod = pair.Key;

                if (reflectableMethod.HasInstantiation)
                    continue;

                if (reflectableMethod.OwningType.HasInstantiation)
                    continue;

                MethodDesc typicalDynamicInvokeStub;
                if (!_dynamicInvokeStubs.Value.TryGetValue(reflectableMethod, out typicalDynamicInvokeStub))
                    continue;

                MethodDesc instantiatiatedDynamicInvokeStub = InstantiateCanonicalDynamicInvokeMethodForMethod(typicalDynamicInvokeStub, reflectableMethod);
                result.DynamicInvokeCompiledMethods.Add(instantiatiatedDynamicInvokeStub);
            }

            return result;
        }
Exemplo n.º 22
0
 public TypeCacheHashtable(ILProvider ilProvider, Logger logger) => (_ilProvider, _logger) = (ilProvider, logger);
Exemplo n.º 23
0
 public ILCache(ILProvider provider, CompilationModuleGroup compilationModuleGroup)
 {
     ILProvider = provider;
     _compilationModuleGroup = compilationModuleGroup;
 }
Exemplo n.º 24
0
            internal TypeCache(MetadataType type, Logger?logger, ILProvider ilProvider)
            {
                Debug.Assert(type == type.GetTypeDefinition());
                Debug.Assert(!CompilerGeneratedNames.IsGeneratedMemberName(type.Name));

                Type = type;

                var callGraph          = new CompilerGeneratedCallGraph();
                var userDefinedMethods = new HashSet <MethodDesc>();

                void ProcessMethod(MethodDesc method)
                {
                    Debug.Assert(method == method.GetTypicalMethodDefinition());

                    bool isStateMachineMember = CompilerGeneratedNames.IsStateMachineType(((MetadataType)method.OwningType).Name);

                    if (!CompilerGeneratedNames.IsLambdaOrLocalFunction(method.Name))
                    {
                        if (!isStateMachineMember)
                        {
                            // If it's not a nested function, track as an entry point to the call graph.
                            var added = userDefinedMethods.Add(method);
                            Debug.Assert(added);
                        }
                    }
                    else
                    {
                        // We don't expect lambdas or local functions to be emitted directly into
                        // state machine types.
                        Debug.Assert(!isStateMachineMember);
                    }

                    // Discover calls or references to lambdas or local functions. This includes
                    // calls to local functions, and lambda assignments (which use ldftn).
                    var methodBody = ilProvider.GetMethodIL(method);

                    if (methodBody != null)
                    {
                        ILReader reader = new ILReader(methodBody.GetILBytes());
                        while (reader.HasNext)
                        {
                            ILOpcode   opcode = reader.ReadILOpcode();
                            MethodDesc?lambdaOrLocalFunction;
                            switch (opcode)
                            {
                            case ILOpcode.ldftn:
                            case ILOpcode.ldtoken:
                            case ILOpcode.call:
                            case ILOpcode.callvirt:
                            case ILOpcode.newobj:
                                lambdaOrLocalFunction = methodBody.GetObject(reader.ReadILToken(), NotFoundBehavior.ReturnNull) as MethodDesc;
                                break;

                            default:
                                lambdaOrLocalFunction = null;
                                reader.Skip(opcode);
                                break;
                            }

                            if (lambdaOrLocalFunction == null)
                            {
                                continue;
                            }

                            lambdaOrLocalFunction = lambdaOrLocalFunction.GetTypicalMethodDefinition();

                            if (lambdaOrLocalFunction.IsConstructor &&
                                lambdaOrLocalFunction.OwningType is MetadataType generatedType &&
                                // Don't consider calls in the same type, like inside a static constructor
                                method.OwningType != generatedType &&
                                CompilerGeneratedNames.IsLambdaDisplayClass(generatedType.Name))
                            {
                                Debug.Assert(generatedType.IsTypeDefinition);

                                // fill in null for now, attribute providers will be filled in later
                                _generatedTypeToTypeArgumentInfo ??= new Dictionary <MetadataType, TypeArgumentInfo>();

                                if (!_generatedTypeToTypeArgumentInfo.TryAdd(generatedType, new TypeArgumentInfo(method, null)))
                                {
                                    var alreadyAssociatedMethod = _generatedTypeToTypeArgumentInfo[generatedType].CreatingMethod;
                                    logger?.LogWarning(new MessageOrigin(method), DiagnosticId.MethodsAreAssociatedWithUserMethod, method.GetDisplayName(), alreadyAssociatedMethod.GetDisplayName(), generatedType.GetDisplayName());
                                }
                                continue;
                            }

                            if (!CompilerGeneratedNames.IsLambdaOrLocalFunction(lambdaOrLocalFunction.Name))
                            {
                                continue;
                            }

                            if (isStateMachineMember)
                            {
                                callGraph.TrackCall((MetadataType)method.OwningType, lambdaOrLocalFunction);
                            }
                            else
                            {
                                callGraph.TrackCall(method, lambdaOrLocalFunction);
                            }
                        }
                    }

                    if (TryGetStateMachineType(method, out MetadataType? stateMachineType))
                    {
                        Debug.Assert(stateMachineType.ContainingType == type ||
                                     (CompilerGeneratedNames.IsGeneratedMemberName(stateMachineType.ContainingType.Name) &&
                                      stateMachineType.ContainingType.ContainingType == type));
                        Debug.Assert(stateMachineType == stateMachineType.GetTypeDefinition());

                        callGraph.TrackCall(method, stateMachineType);

                        _compilerGeneratedTypeToUserCodeMethod ??= new Dictionary <MetadataType, MethodDesc>();
                        if (!_compilerGeneratedTypeToUserCodeMethod.TryAdd(stateMachineType, method))
                        {
                            var alreadyAssociatedMethod = _compilerGeneratedTypeToUserCodeMethod[stateMachineType];
                            logger?.LogWarning(new MessageOrigin(method), DiagnosticId.MethodsAreAssociatedWithStateMachine, method.GetDisplayName(), alreadyAssociatedMethod.GetDisplayName(), stateMachineType.GetDisplayName());
                        }
                        // Already warned above if multiple methods map to the same type
                        // Fill in null for argument providers now, the real providers will be filled in later
                        _generatedTypeToTypeArgumentInfo ??= new Dictionary <MetadataType, TypeArgumentInfo>();
                        _generatedTypeToTypeArgumentInfo[stateMachineType] = new TypeArgumentInfo(method, null);
                    }
                }

                // Look for state machine methods, and methods which call local functions.
                foreach (MethodDesc method in type.GetMethods())
                {
                    ProcessMethod(method);
                }

                // Also scan compiler-generated state machine methods (in case they have calls to nested functions),
                // and nested functions inside compiler-generated closures (in case they call other nested functions).

                // State machines can be emitted into lambda display classes, so we need to go down at least two
                // levels to find calls from iterator nested functions to other nested functions. We just recurse into
                // all compiler-generated nested types to avoid depending on implementation details.

                foreach (var nestedType in GetCompilerGeneratedNestedTypes(type))
                {
                    foreach (var method in nestedType.GetMethods())
                    {
                        ProcessMethod(method);
                    }
                }

                // Now we've discovered the call graphs for calls to nested functions.
                // Use this to map back from nested functions to the declaring user methods.

                // Note: This maps all nested functions back to the user code, not to the immediately
                // declaring local function. The IL doesn't contain enough information in general for
                // us to determine the nesting of local functions and lambdas.

                // Note: this only discovers nested functions which are referenced from the user
                // code or its referenced nested functions. There is no reliable way to determine from
                // IL which user code an unused nested function belongs to.

                foreach (var userDefinedMethod in userDefinedMethods)
                {
                    var callees = callGraph.GetReachableMembers(userDefinedMethod);
                    if (!callees.Any())
                    {
                        continue;
                    }

                    _compilerGeneratedMembers ??= new Dictionary <MethodDesc, List <TypeSystemEntity> >();
                    _compilerGeneratedMembers.Add(userDefinedMethod, new List <TypeSystemEntity>(callees));

                    foreach (var compilerGeneratedMember in callees)
                    {
                        switch (compilerGeneratedMember)
                        {
                        case MethodDesc nestedFunction:
                            Debug.Assert(CompilerGeneratedNames.IsLambdaOrLocalFunction(nestedFunction.Name));
                            // Nested functions get suppressions from the user method only.
                            _compilerGeneratedMethodToUserCodeMethod ??= new Dictionary <MethodDesc, MethodDesc>();
                            if (!_compilerGeneratedMethodToUserCodeMethod.TryAdd(nestedFunction, userDefinedMethod))
                            {
                                var alreadyAssociatedMethod = _compilerGeneratedMethodToUserCodeMethod[nestedFunction];
                                logger?.LogWarning(new MessageOrigin(userDefinedMethod), DiagnosticId.MethodsAreAssociatedWithUserMethod, userDefinedMethod.GetDisplayName(), alreadyAssociatedMethod.GetDisplayName(), nestedFunction.GetDisplayName());
                            }
                            break;

                        case MetadataType stateMachineType:
                            // Types in the call graph are always state machine types
                            // For those all their methods are not tracked explicitly in the call graph; instead, they
                            // are represented by the state machine type itself.
                            // We are already tracking the association of the state machine type to the user code method
                            // above, so no need to track it here.
                            Debug.Assert(CompilerGeneratedNames.IsStateMachineType(stateMachineType.Name));
                            break;

                        default:
                            throw new InvalidOperationException();
                        }
                    }
                }

                // Now that we have instantiating methods fully filled out, walk the generated types and fill in the attribute
                // providers
                if (_generatedTypeToTypeArgumentInfo != null)
                {
                    foreach (var generatedType in _generatedTypeToTypeArgumentInfo.Keys)
                    {
                        Debug.Assert(generatedType == generatedType.GetTypeDefinition());

                        if (HasGenericParameters(generatedType))
                        {
                            MapGeneratedTypeTypeParameters(generatedType);
                        }
                    }
                }
Exemplo n.º 25
0
 public RemovingILProvider(ILProvider baseILProvider, RemovedFeature feature)
 {
     _baseILProvider = baseILProvider;
     _removedFeature = feature;
 }
Exemplo n.º 26
0
 public EmptyMetadataManager(CompilerTypeSystemContext typeSystemContext, StackTraceEmissionPolicy stackTraceEmissionPolicy, ILProvider ilProvider)
     : base(typeSystemContext, new FullyBlockedMetadataPolicy(), new FullyBlockedManifestResourcePolicy(), new NoDynamicInvokeThunkGenerationPolicy())
 {
     _stackTraceEmissionPolicy = stackTraceEmissionPolicy;
     _ilProvider = ilProvider;
 }