Crossgen2 pipeline optimize (#51154)
authort-mustafin <66252296+t-mustafin@users.noreply.github.com>
Mon, 10 May 2021 19:43:32 +0000 (22:43 +0300)
committerGitHub <noreply@github.com>
Mon, 10 May 2021 19:43:32 +0000 (12:43 -0700)
* Initial implementation of crossgen2 pipeline mode

- Add --out-near-input option, which adds .ni. suffix to input filepath
  and stores resulting ni.dll near original dll. In this mode --out option can be skipped.
- Add --single-file-compilation mode, which allows to compile all input files separately.

* [crossgen2] Optimize pipeline mode

Load input and reference modules only once by crossgen2 start.

Signed-off-by: Timur Mustafin <t.mustafin@partner.samsung.com>
* Feedback: make typeSystemContext with opened files

Construct new typeSystemContext with already opened PEReaders and PDBReaders.

Signed-off-by: Timur Mustafin <t.mustafin@partner.samsung.com>
Co-authored-by: Gleb Balykov <g.balykov@samsung.com>
src/coreclr/tools/Common/Compiler/CompilerTypeSystemContext.cs
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs
src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilerContext.cs
src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs
src/coreclr/tools/aot/crossgen2/Program.cs
src/coreclr/tools/aot/crossgen2/Properties/Resources.resx

index 4499457..1dc0fd8 100644 (file)
@@ -183,14 +183,25 @@ namespace ILCompiler
             }
         }
 
-        private EcmaModule AddModule(string filePath, string expectedSimpleName, bool useForBinding)
+        private EcmaModule AddModule(string filePath, string expectedSimpleName, bool useForBinding, ModuleData oldModuleData = null)
         {
+            PEReader peReader = null;
             MemoryMappedViewAccessor mappedViewAccessor = null;
             PdbSymbolReader pdbReader = null;
             try
             {
-                PEReader peReader = OpenPEFile(filePath, out mappedViewAccessor);
-                pdbReader = PortablePdbSymbolReader.TryOpenEmbedded(peReader, GetMetadataStringDecoder()) ?? OpenAssociatedSymbolFile(filePath, peReader);
+                if (oldModuleData == null)
+                {
+                    peReader = OpenPEFile(filePath, out mappedViewAccessor);
+                    pdbReader = PortablePdbSymbolReader.TryOpenEmbedded(peReader, GetMetadataStringDecoder()) ?? OpenAssociatedSymbolFile(filePath, peReader);
+                }
+                else
+                {
+                    filePath = oldModuleData.FilePath;
+                    peReader = oldModuleData.Module.PEReader;
+                    mappedViewAccessor = oldModuleData.MappedViewAccessor;
+                    pdbReader = oldModuleData.Module.PdbReader;
+                }
 
                 EcmaModule module = EcmaModule.Create(this, peReader, containingAssembly: null, pdbReader);
 
@@ -237,6 +248,14 @@ namespace ILCompiler
             }
         }
 
+        protected void InheritOpenModules(CompilerTypeSystemContext oldTypeSystemContext)
+        {
+            foreach (ModuleData oldModuleData in ModuleHashtable.Enumerator.Get(oldTypeSystemContext._moduleHashtable))
+            {
+                AddModule(null, null, true, oldModuleData);
+            }
+        }
+
         protected override RuntimeInterfacesAlgorithm GetRuntimeInterfacesAlgorithmForDefType(DefType type)
         {
             return _metadataRuntimeInterfacesAlgorithm;
index 910dffe..cd77cbe 100644 (file)
@@ -19,6 +19,8 @@ namespace ILCompiler
 {
     public sealed class ReadyToRunCodegenCompilationBuilder : CompilationBuilder
     {
+        private static bool _isJitInitialized = false;
+
         private readonly IEnumerable<string> _inputFiles;
         private readonly string _compositeRootPath;
         private bool _ibcTuning;
@@ -277,7 +279,11 @@ namespace ILCompiler
             if (_ibcTuning)
                 corJitFlags.Add(CorJitFlag.CORJIT_FLAG_BBINSTR);
 
-            JitConfigProvider.Initialize(_context.Target, corJitFlags, _ryujitOptions, _jitPath);
+            if (!_isJitInitialized)
+            {
+                JitConfigProvider.Initialize(_context.Target, corJitFlags, _ryujitOptions, _jitPath);
+                _isJitInitialized = true;
+            }
 
             return new ReadyToRunCodegenCompilation(
                 graph,
index 4c8f977..5790516 100644 (file)
@@ -26,7 +26,7 @@ namespace ILCompiler
         private VectorOfTFieldLayoutAlgorithm _vectorOfTFieldLayoutAlgorithm;
         private VectorFieldLayoutAlgorithm _vectorFieldLayoutAlgorithm;
 
-        public ReadyToRunCompilerContext(TargetDetails details, SharedGenericsMode genericsMode, bool bubbleIncludesCorelib)
+        public ReadyToRunCompilerContext(TargetDetails details, SharedGenericsMode genericsMode, bool bubbleIncludesCorelib, CompilerTypeSystemContext oldTypeSystemContext = null)
             : base(details, genericsMode)
         {
             _r2rFieldLayoutAlgorithm = new ReadyToRunMetadataFieldLayoutAlgorithm();
@@ -43,6 +43,11 @@ namespace ILCompiler
 
             // No architecture has completely stable handling of Vector<T> in the abi (Arm64 may change to SVE)
             _vectorOfTFieldLayoutAlgorithm = new VectorOfTFieldLayoutAlgorithm(_r2rFieldLayoutAlgorithm, _vectorFieldLayoutAlgorithm, matchingVectorType, bubbleIncludesCorelib);
+
+            if (oldTypeSystemContext != null)
+            {
+                InheritOpenModules(oldTypeSystemContext);
+            }
         }
 
         public override FieldLayoutAlgorithm GetLayoutAlgorithmForType(DefType type)
index 9097636..f5a6846 100644 (file)
@@ -33,6 +33,8 @@ namespace ILCompiler
         public bool Composite;
         public bool CompileNoMethods;
         public bool EmbedPgoData;
+        public bool OutNearInput;
+        public bool SingleFileCompilation;
 
         public string DgmlLogFileName;
         public bool GenerateFullDgmlLog;
@@ -100,6 +102,8 @@ namespace ILCompiler
                 syntax.DefineOption("inputbubble", ref InputBubble, SR.InputBubbleOption);
                 syntax.DefineOption("composite", ref Composite, SR.CompositeBuildMode);
                 syntax.DefineOption("compile-no-methods", ref CompileNoMethods, SR.CompileNoMethodsOption);
+                syntax.DefineOption("out-near-input", ref OutNearInput, SR.OutNearInputOption);
+                syntax.DefineOption("single-file-compilation", ref SingleFileCompilation, SR.SingleFileCompilationOption);
                 syntax.DefineOption("tuning", ref Tuning, SR.TuningImageOption);
                 syntax.DefineOption("partial", ref Partial, SR.PartialImageOption);
                 syntax.DefineOption("compilebubblegenerics", ref CompileBubbleGenerics, SR.BubbleGenericsOption);
index aad491a..836c08c 100644 (file)
@@ -25,9 +25,16 @@ namespace ILCompiler
         public TargetArchitecture _targetArchitecture;
         private bool _armelAbi = false;
         public OptimizationMode _optimizationMode;
+
+        // File names as strings in args
         private Dictionary<string, string> _inputFilePaths = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
         private Dictionary<string, string> _unrootedInputFilePaths = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
         private Dictionary<string, string> _referenceFilePaths = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+
+        // Modules and their names after loading
+        private Dictionary<string, string> _allInputFilePaths = new Dictionary<string, string>();
+        private List<ModuleDesc> _referenceableModules = new List<ModuleDesc>();
+
         private CompilerTypeSystemContext _typeSystemContext;
         private ReadyToRunMethodLayoutAlgorithm _methodLayout;
         private ReadyToRunFileLayoutAlgorithm _fileLayout;
@@ -293,134 +300,208 @@ namespace ILCompiler
 
         private int Run(string[] args)
         {
-            using (PerfEventSource.StartStopEvents.CompilationEvents())
-            {
-                ICompilation compilation;
-                using (PerfEventSource.StartStopEvents.LoadingEvents())
-                {
-                    InitializeDefaultOptions();
+            InitializeDefaultOptions();
 
-                    ProcessCommandLine(args);
+            ProcessCommandLine(args);
 
-                    if (_commandLineOptions.Help)
-                    {
-                        Console.WriteLine(_commandLineOptions.HelpText);
-                        return 1;
-                    }
+            if (_commandLineOptions.Help)
+            {
+                Console.WriteLine(_commandLineOptions.HelpText);
+                return 1;
+            }
 
-                    if (_commandLineOptions.OutputFilePath == null)
-                        throw new CommandLineException(SR.MissingOutputFile);
+            if (_commandLineOptions.OutputFilePath == null && !_commandLineOptions.OutNearInput)
+                throw new CommandLineException(SR.MissingOutputFile);
 
-                    ConfigureTarget();
-                    InstructionSetSupport instructionSetSupport = ConfigureInstructionSetSupport();
+            ConfigureTarget();
+            InstructionSetSupport instructionSetSupport = ConfigureInstructionSetSupport();
 
-                    //
-                    // Initialize type system context
-                    //
+            SharedGenericsMode genericsMode = SharedGenericsMode.CanonicalReferenceTypes;
 
-                    SharedGenericsMode genericsMode = SharedGenericsMode.CanonicalReferenceTypes;
+            var targetDetails = new TargetDetails(_targetArchitecture, _targetOS, _armelAbi ? TargetAbi.CoreRTArmel : TargetAbi.CoreRT, instructionSetSupport.GetVectorTSimdVector());
 
-                    var targetDetails = new TargetDetails(_targetArchitecture, _targetOS, _armelAbi ? TargetAbi.CoreRTArmel : TargetAbi.CoreRT, instructionSetSupport.GetVectorTSimdVector());
-
-                    bool versionBubbleIncludesCoreLib = false;
-                    if (_commandLineOptions.InputBubble)
-                    {
-                        versionBubbleIncludesCoreLib = true;
-                    }
-                    else
+            bool versionBubbleIncludesCoreLib = false;
+            if (_commandLineOptions.InputBubble)
+            {
+                versionBubbleIncludesCoreLib = true;
+            }
+            else
+            {
+                if (!_commandLineOptions.SingleFileCompilation)
+                {
+                    foreach (var inputFile in _inputFilePaths)
                     {
-                        foreach (var inputFile in _inputFilePaths)
+                        if (String.Compare(inputFile.Key, "System.Private.CoreLib", StringComparison.OrdinalIgnoreCase) == 0)
                         {
-                            if (String.Compare(inputFile.Key, "System.Private.CoreLib", StringComparison.OrdinalIgnoreCase) == 0)
-                            {
-                                versionBubbleIncludesCoreLib = true;
-                                break;
-                            }
+                            versionBubbleIncludesCoreLib = true;
+                            break;
                         }
-                        if (!versionBubbleIncludesCoreLib)
+                    }
+                }
+                if (!versionBubbleIncludesCoreLib)
+                {
+                    foreach (var inputFile in _unrootedInputFilePaths)
+                    {
+                        if (String.Compare(inputFile.Key, "System.Private.CoreLib", StringComparison.OrdinalIgnoreCase) == 0)
                         {
-                            foreach (var inputFile in _unrootedInputFilePaths)
-                            {
-                                if (String.Compare(inputFile.Key, "System.Private.CoreLib", StringComparison.OrdinalIgnoreCase) == 0)
-                                {
-                                    versionBubbleIncludesCoreLib = true;
-                                    break;
-                                }
-                            }
+                            versionBubbleIncludesCoreLib = true;
+                            break;
                         }
                     }
+                }
+            }
 
-                    _typeSystemContext = new ReadyToRunCompilerContext(targetDetails, genericsMode, versionBubbleIncludesCoreLib);
+            //
+            // Initialize type system context
+            //
+            _typeSystemContext = new ReadyToRunCompilerContext(targetDetails, genericsMode, versionBubbleIncludesCoreLib);
 
-                    string compositeRootPath = _commandLineOptions.CompositeRootPath;
+            string compositeRootPath = _commandLineOptions.CompositeRootPath;
 
-                    //
-                    // 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> allInputFilePaths = new Dictionary<string, string>();
-                    Dictionary<string, string> inputFilePaths = new Dictionary<string, string>();
-                    List<ModuleDesc> referenceableModules = new List<ModuleDesc>();
-                    foreach (var inputFile in _inputFilePaths)
+            // Collections for already loaded modules
+            Dictionary<string, string> inputFilePaths = new Dictionary<string, string>();
+            Dictionary<string, string> unrootedInputFilePaths = new Dictionary<string, string>();
+            HashSet<ModuleDesc> versionBubbleModulesHash = new HashSet<ModuleDesc>();
+
+            using (PerfEventSource.StartStopEvents.LoadingEvents())
+            {
+                //
+                // 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 = inFilePaths;
+                //
+
+                foreach (var inputFile in _inputFilePaths)
+                {
+                    try
                     {
-                        try
+                        var module = _typeSystemContext.GetModuleFromPath(inputFile.Value);
+                        _allInputFilePaths.Add(inputFile.Key, inputFile.Value);
+                        inputFilePaths.Add(inputFile.Key, inputFile.Value);
+                        _referenceableModules.Add(module);
+                        if (compositeRootPath == null)
                         {
-                            var module = _typeSystemContext.GetModuleFromPath(inputFile.Value);
-                            allInputFilePaths.Add(inputFile.Key, inputFile.Value);
-                            inputFilePaths.Add(inputFile.Key, inputFile.Value);
-                            referenceableModules.Add(module);
-                            if (compositeRootPath == null)
-                            {
-                                compositeRootPath = Path.GetDirectoryName(inputFile.Value);
-                            }
-                        }
-                        catch (TypeSystemException.BadImageFormatException)
-                        {
-                            // Keep calm and carry on.
+                            compositeRootPath = Path.GetDirectoryName(inputFile.Value);
                         }
                     }
+                    catch (TypeSystemException.BadImageFormatException)
+                    {
+                        // Keep calm and carry on.
+                    }
+                }
 
-                    Dictionary<string, string> unrootedInputFilePaths = new Dictionary<string, string>();
-                    foreach (var unrootedInputFile in _unrootedInputFilePaths)
+                foreach (var unrootedInputFile in _unrootedInputFilePaths)
+                {
+                    try
                     {
-                        try
+                        var module = _typeSystemContext.GetModuleFromPath(unrootedInputFile.Value);
+                        if (!_allInputFilePaths.ContainsKey(unrootedInputFile.Key))
                         {
-                            var module = _typeSystemContext.GetModuleFromPath(unrootedInputFile.Value);
-                            if (!allInputFilePaths.ContainsKey(unrootedInputFile.Key))
+                            _allInputFilePaths.Add(unrootedInputFile.Key, unrootedInputFile.Value);
+                            unrootedInputFilePaths.Add(unrootedInputFile.Key, unrootedInputFile.Value);
+                            _referenceableModules.Add(module);
+                            if (compositeRootPath == null)
                             {
-                                allInputFilePaths.Add(unrootedInputFile.Key, unrootedInputFile.Value);
-                                unrootedInputFilePaths.Add(unrootedInputFile.Key, unrootedInputFile.Value);
-                                referenceableModules.Add(module);
-                                if (compositeRootPath == null)
-                                {
-                                    compositeRootPath = Path.GetDirectoryName(unrootedInputFile.Value);
-                                }
+                                compositeRootPath = Path.GetDirectoryName(unrootedInputFile.Value);
                             }
                         }
-                        catch (TypeSystemException.BadImageFormatException)
+                    }
+                    catch (TypeSystemException.BadImageFormatException)
+                    {
+                        // Keep calm and carry on.
+                    }
+                }
+
+                CheckManagedCppInputFiles(_allInputFilePaths.Values);
+
+                _typeSystemContext.InputFilePaths = _allInputFilePaths;
+                _typeSystemContext.ReferenceFilePaths = _referenceFilePaths;
+
+                if (_typeSystemContext.InputFilePaths.Count == 0)
+                {
+                    if (_commandLineOptions.InputFilePaths.Count > 0)
+                    {
+                        Console.WriteLine(SR.InputWasNotLoadable);
+                        return 2;
+                    }
+                    throw new CommandLineException(SR.NoInputFiles);
+                }
+
+                foreach (var referenceFile in _referenceFilePaths.Values)
+                {
+                    try
+                    {
+                        EcmaModule module = _typeSystemContext.GetModuleFromPath(referenceFile);
+                        _referenceableModules.Add(module);
+                        if (_commandLineOptions.InputBubble)
                         {
-                            // Keep calm and carry on.
+                            // In large version bubble mode add reference paths to the compilation group
+                            versionBubbleModulesHash.Add(module);
                         }
                     }
+                    catch { } // Ignore non-managed pe files
+                }
+            }
+
+            string systemModuleName = _commandLineOptions.SystemModule ?? DefaultSystemModule;
+            _typeSystemContext.SetSystemModule((EcmaModule)_typeSystemContext.GetModuleForSimpleName(systemModuleName));
+            CompilerTypeSystemContext typeSystemContext = _typeSystemContext;
+
+            if (_commandLineOptions.SingleFileCompilation)
+            {
+                var singleCompilationInputFilePaths = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
+
+                foreach (var inputFile in inputFilePaths)
+                {
+                    var singleCompilationVersionBubbleModulesHash = new HashSet<ModuleDesc>(versionBubbleModulesHash);
+
+                    singleCompilationInputFilePaths.Clear();
+                    singleCompilationInputFilePaths.Add(inputFile.Key, inputFile.Value);
+                    typeSystemContext.InputFilePaths = singleCompilationInputFilePaths;
+
+                    if (!_commandLineOptions.InputBubble)
+                    {
+                        bool singleCompilationVersionBubbleIncludesCoreLib = versionBubbleIncludesCoreLib || (String.Compare(inputFile.Key, "System.Private.CoreLib", StringComparison.OrdinalIgnoreCase) == 0);
+
+                        typeSystemContext = new ReadyToRunCompilerContext(targetDetails, genericsMode, singleCompilationVersionBubbleIncludesCoreLib, _typeSystemContext);
+                        typeSystemContext.SetSystemModule((EcmaModule)typeSystemContext.GetModuleForSimpleName(systemModuleName));
+                    }
+
+                    RunSingleCompilation(singleCompilationInputFilePaths, instructionSetSupport, compositeRootPath, unrootedInputFilePaths, singleCompilationVersionBubbleModulesHash, typeSystemContext);
+                }
+            }
+            else
+            {
+                RunSingleCompilation(inputFilePaths, instructionSetSupport, compositeRootPath, unrootedInputFilePaths, versionBubbleModulesHash, typeSystemContext);
+            }
+
+            return 0;
+        }
 
-                    CheckManagedCppInputFiles(allInputFilePaths.Values);
+        private void RunSingleCompilation(Dictionary<string, string> inFilePaths, InstructionSetSupport instructionSetSupport, string compositeRootPath, Dictionary<string, string> unrootedInputFilePaths, HashSet<ModuleDesc> versionBubbleModulesHash, CompilerTypeSystemContext typeSystemContext)
+        {
+            //
+            // Initialize output filename
+            //
+            var outFile = _commandLineOptions.OutNearInput ? inFilePaths.First().Value.Replace(".dll", ".ni.dll") : _commandLineOptions.OutputFilePath;
 
-                    _typeSystemContext.InputFilePaths = allInputFilePaths;
-                    _typeSystemContext.ReferenceFilePaths = _referenceFilePaths;
+            using (PerfEventSource.StartStopEvents.CompilationEvents())
+            {
+                ICompilation compilation;
+                using (PerfEventSource.StartStopEvents.LoadingEvents())
+                {
 
                     List<EcmaModule> inputModules = new List<EcmaModule>();
                     List<EcmaModule> rootingModules = new List<EcmaModule>();
-                    HashSet<ModuleDesc> versionBubbleModulesHash = new HashSet<ModuleDesc>();
                     Guid? inputModuleMvid = null;
 
-                    foreach (var inputFile in inputFilePaths)
+                    foreach (var inputFile in inFilePaths)
                     {
-                        EcmaModule module = _typeSystemContext.GetModuleFromPath(inputFile.Value);
+                        EcmaModule module = typeSystemContext.GetModuleFromPath(inputFile.Value);
                         inputModules.Add(module);
                         rootingModules.Add(module);
                         versionBubbleModulesHash.Add(module);
@@ -438,30 +519,17 @@ namespace ILCompiler
 
                     foreach (var unrootedInputFile in unrootedInputFilePaths)
                     {
-                        EcmaModule module = _typeSystemContext.GetModuleFromPath(unrootedInputFile.Value);
+                        EcmaModule module = typeSystemContext.GetModuleFromPath(unrootedInputFile.Value);
                         inputModules.Add(module);
                         versionBubbleModulesHash.Add(module);
                     }
 
-                    string systemModuleName = _commandLineOptions.SystemModule ?? DefaultSystemModule;
-                    _typeSystemContext.SetSystemModule((EcmaModule)_typeSystemContext.GetModuleForSimpleName(systemModuleName));
-
-                    if (_typeSystemContext.InputFilePaths.Count == 0)
-                    {
-                        if (_commandLineOptions.InputFilePaths.Count > 0)
-                        {
-                            Console.WriteLine(SR.InputWasNotLoadable);
-                            return 2;
-                        }
-                        throw new CommandLineException(SR.NoInputFiles);
-                    }
-
                     //
                     // Initialize compilation group and compilation roots
                     //
 
                     // Single method mode?
-                    MethodDesc singleMethod = CheckAndParseSingleMethodModeArguments(_typeSystemContext);
+                    MethodDesc singleMethod = CheckAndParseSingleMethodModeArguments(typeSystemContext);
 
                     var logger = new Logger(Console.Out, _commandLineOptions.Verbose);
 
@@ -471,26 +539,6 @@ namespace ILCompiler
                         mibcFiles.Add(file);
                     }
 
-                    foreach (var referenceFile in _referenceFilePaths.Values)
-                    {
-                        try
-                        {
-                            EcmaModule module = _typeSystemContext.GetModuleFromPath(referenceFile);
-                            if (versionBubbleModulesHash.Contains(module))
-                            {
-                                // Ignore reference assemblies that have also been passed as inputs
-                                continue;
-                            }
-                            referenceableModules.Add(module);
-                            if (_commandLineOptions.InputBubble)
-                            {
-                                // In large version bubble mode add reference paths to the compilation group
-                                versionBubbleModulesHash.Add(module);
-                            }
-                        }
-                        catch { } // Ignore non-managed pe files
-                    }
-
                     List<ModuleDesc> versionBubbleModules = new List<ModuleDesc>(versionBubbleModulesHash);
 
                     if (!_commandLineOptions.Composite && inputModules.Count != 1)
@@ -504,7 +552,7 @@ namespace ILCompiler
                     {
                         // Compiling just a single method
                         compilationGroup = new SingleMethodCompilationModuleGroup(
-                            _typeSystemContext,
+                            typeSystemContext,
                             _commandLineOptions.Composite,
                             _commandLineOptions.InputBubble,
                             inputModules,
@@ -516,7 +564,7 @@ namespace ILCompiler
                     else if (_commandLineOptions.CompileNoMethods)
                     {
                         compilationGroup = new NoMethodsCompilationModuleGroup(
-                            _typeSystemContext,
+                            typeSystemContext,
                             _commandLineOptions.Composite,
                             _commandLineOptions.InputBubble,
                             inputModules,
@@ -527,7 +575,7 @@ namespace ILCompiler
                     {
                         // Single assembly compilation.
                         compilationGroup = new ReadyToRunSingleAssemblyCompilationModuleGroup(
-                            _typeSystemContext,
+                            typeSystemContext,
                             _commandLineOptions.Composite,
                             _commandLineOptions.InputBubble,
                             inputModules,
@@ -540,19 +588,19 @@ namespace ILCompiler
 
                     if (!string.IsNullOrEmpty(_commandLineOptions.CallChainProfileFile))
                     {
-                        jsonProfile = new CallChainProfile(_commandLineOptions.CallChainProfileFile, _typeSystemContext, referenceableModules);
+                        jsonProfile = new CallChainProfile(_commandLineOptions.CallChainProfileFile, typeSystemContext, _referenceableModules);
                     }
 
                     // Examine profile guided information as appropriate
                     ProfileDataManager profileDataManager =
                         new ProfileDataManager(logger,
-                        referenceableModules,
+                        _referenceableModules,
                         inputModules,
                         versionBubbleModules,
                         _commandLineOptions.CompileBubbleGenerics ? inputModules[0] : null,
                         mibcFiles,
                         jsonProfile,
-                        _typeSystemContext,
+                        typeSystemContext,
                         compilationGroup,
                         _commandLineOptions.EmbedPgoData);
 
@@ -578,11 +626,12 @@ namespace ILCompiler
                         }
                     }
                     // In single-file compilation mode, use the assembly's DebuggableAttribute to determine whether to optimize
-                    // or produce debuggable code if an explicit optimization level was not specified on the command line 
-                    if (_optimizationMode == OptimizationMode.None && !_commandLineOptions.OptimizeDisabled && !_commandLineOptions.Composite)
+                    // or produce debuggable code if an explicit optimization level was not specified on the command line
+                    OptimizationMode optimizationMode = _optimizationMode;
+                    if (optimizationMode == OptimizationMode.None && !_commandLineOptions.OptimizeDisabled && !_commandLineOptions.Composite)
                     {
                         System.Diagnostics.Debug.Assert(inputModules.Count == 1);
-                        _optimizationMode = ((EcmaAssembly)inputModules[0].Assembly).HasOptimizationsDisabled() ? OptimizationMode.None : OptimizationMode.Blended;
+                        optimizationMode = ((EcmaAssembly)inputModules[0].Assembly).HasOptimizationsDisabled() ? OptimizationMode.None : OptimizationMode.Blended;
                     }
 
                     //
@@ -590,7 +639,7 @@ namespace ILCompiler
                     //
 
                     ReadyToRunCodegenCompilationBuilder builder = new ReadyToRunCodegenCompilationBuilder(
-                        _typeSystemContext, compilationGroup, allInputFilePaths.Values, compositeRootPath);
+                        typeSystemContext, compilationGroup, _allInputFilePaths.Values, compositeRootPath);
                     string compilationUnitPrefix = "";
                     builder.UseCompilationUnitPrefix(compilationUnitPrefix);
 
@@ -614,13 +663,13 @@ namespace ILCompiler
                         .UseInstructionSetSupport(instructionSetSupport)
                         .UseCustomPESectionAlignment(_commandLineOptions.CustomPESectionAlignment)
                         .UseVerifyTypeAndFieldLayout(_commandLineOptions.VerifyTypeAndFieldLayout)
-                        .GenerateOutputFile(_commandLineOptions.OutputFilePath)
+                        .GenerateOutputFile(outFile)
                         .UseILProvider(ilProvider)
                         .UseBackendOptions(_commandLineOptions.CodegenOptions)
                         .UseLogger(logger)
                         .UseDependencyTracking(trackingLevel)
                         .UseCompilationRoots(compilationRoots)
-                        .UseOptimizationMode(_optimizationMode);
+                        .UseOptimizationMode(optimizationMode);
 
                     if (_commandLineOptions.PrintReproInstructions)
                         builder.UsePrintReproInstructions(CreateReproArgumentString);
@@ -628,15 +677,13 @@ namespace ILCompiler
                     compilation = builder.ToCompilation();
 
                 }
-                compilation.Compile(_commandLineOptions.OutputFilePath);
+                compilation.Compile(outFile);
 
                 if (_commandLineOptions.DgmlLogFileName != null)
                     compilation.WriteDependencyLog(_commandLineOptions.DgmlLogFileName);
 
                 compilation.Dispose();
             }
-
-            return 0;
         }
 
         private void CheckManagedCppInputFiles(IEnumerable<string> inputPaths)
index 9c84701..d94483a 100644 (file)
   <data name="OptimizeSpeedOption" xml:space="preserve">
     <value>Enable optimizations, favor code speed</value>
   </data>
+  <data name="OutNearInputOption" xml:space="preserve">
+    <value>Create output files near input files with ni.dll suffix</value>
+  </data>
   <data name="OutputFilePath" xml:space="preserve">
     <value>Output file path</value>
   </data>
   <data name="PrintReproInstructionsOption" xml:space="preserve">
     <value>When compiling each method, print out the set of arguments needed to compile that method only</value>
   </data>
+  <data name="SingleFileCompilationOption" xml:space="preserve">
+    <value>Compile each of the input files separately</value>
+  </data>
   <data name="SingleMethodGenericArgs" xml:space="preserve">
     <value>Single method compilation: generic arguments to the method</value>
   </data>
   <data name="PerfMapFilePathOption" xml:space="preserve">
     <value>Explicit specification of the PerfMap file path</value>
   </data>
-</root>
\ No newline at end of file
+</root>