Beispiel #1
0
        private IReadOnlyCollection <MethodDesc> CreateInitializerList(TypeSystemContext context)
        {
            List <ModuleDesc> assembliesWithInitalizers = new List <ModuleDesc>();

            // Build a list of assemblies that have an initializer that needs to run before
            // any user code runs.
            foreach (string initAssemblyName in _initAssemblies)
            {
                ModuleDesc assembly = context.ResolveAssembly(new AssemblyName(initAssemblyName));
                assembliesWithInitalizers.Add(assembly);
            }

            var libraryInitializers = new LibraryInitializers(context, assembliesWithInitalizers);

            List <MethodDesc> initializerList = new List <MethodDesc>(libraryInitializers.LibraryInitializerMethods);

            // If there are any AppContext switches the user wishes to enable, generate code that sets them.
            if (_appContextSwitches.Count > 0)
            {
                MethodDesc appContextInitMethod = new Internal.IL.Stubs.StartupCode.AppContextInitializerMethod(
                    context.GeneratedAssembly.GetGlobalModuleType(), _appContextSwitches);
                initializerList.Add(appContextInitMethod);
            }

            return(initializerList);
        }
Beispiel #2
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.ARMEL;
                }
                else if (_targetArchitectureStr.Equals("arm64", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.ARM64;
                }
                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;
            }
            //
            // Initialize type system context
            //

            SharedGenericsMode genericsMode = _useSharedGenerics || (!_isCppCodegen && !_isWasmCodegen) ?
                                              SharedGenericsMode.CanonicalReferenceTypes : SharedGenericsMode.Disabled;

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

            //
            // 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;
                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;
                    }

                    // TODO: Wasm fails to compile some of the exported methods due to missing opcodes
                    if (!_isWasmCodegen)
                    {
                        compilationRoots.Add(new ExportedMethodsRootProvider(module));
                    }
                }

                if (entrypointModule != null)
                {
                    // TODO: Wasm fails to compile some of the library initializers
                    if (!_isWasmCodegen)
                    {
                        LibraryInitializers libraryInitializers =
                            new LibraryInitializers(typeSystemContext, _isCppCodegen);
                        compilationRoots.Add(new MainMethodRootProvider(entrypointModule, libraryInitializers.LibraryInitializerMethods));
                    }
                    else
                    {
                        compilationRoots.Add(new RawMainMethodRootProvider(entrypointModule));
                    }
                }

                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)
                    {
                        throw new Exception("No entrypoint module");
                    }

                    // TODO: Wasm fails to compile some of the xported methods due to missing opcodes
                    if (!_isWasmCodegen)
                    {
                        compilationRoots.Add(new ExportedMethodsRootProvider((EcmaModule)typeSystemContext.SystemModule));
                    }

                    compilationGroup = new SingleFileCompilationModuleGroup(typeSystemContext);
                }

                foreach (var rdXmlFilePath in _rdXmlFilePaths)
                {
                    compilationRoots.Add(new RdXmlRootProvider(typeSystemContext, rdXmlFilePath));
                }
            }

            //
            // Compile
            //

            CompilationBuilder builder;

            if (_isWasmCodegen)
            {
                builder = new WebAssemblyCodegenCompilationBuilder(typeSystemContext, compilationGroup);
            }
            else if (_isCppCodegen)
            {
                builder = new CppCodegenCompilationBuilder(typeSystemContext, compilationGroup);
            }
            else
            {
                builder = new RyuJitCompilationBuilder(typeSystemContext, compilationGroup);
            }

            bool useScanner = _useScanner ||
                              (_optimizationMode != OptimizationMode.None && !_isCppCodegen && !_isWasmCodegen);

            useScanner &= !_noScanner;

            ILScanResults scanResults = null;

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

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

                IILScanner scanner = scannerBuilder.ToILScanner();

                scanResults = scanner.Scan();
            }

            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);

            CompilerGeneratedMetadataManager metadataManager = new CompilerGeneratedMetadataManager(compilationGroup, typeSystemContext, _metadataLogFileName);

            builder
            .UseBackendOptions(_codegenOptions)
            .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());
            }

            ICompilation compilation = builder.ToCompilation();

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

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

            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));
                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.IsInSimdModule(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);
        }
Beispiel #3
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.ARMEL;
                }
                else if (_targetArchitectureStr.Equals("arm64", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.ARM64;
                }
                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");
                }
            }

            //
            // Initialize type system context
            //

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

            var typeSystemContext = new CompilerTypeSystemContext(new TargetDetails(_targetArchitecture, _targetOS, TargetAbi.CoreRT), genericsMode);

            //
            // 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;
                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;
                    }

                    compilationRoots.Add(new ExportedMethodsRootProvider(module));
                }

                if (entrypointModule != null)
                {
                    LibraryInitializers libraryInitializers =
                        new LibraryInitializers(typeSystemContext, _isCppCodegen);
                    compilationRoots.Add(new MainMethodRootProvider(entrypointModule, libraryInitializers.LibraryInitializerMethods));
                }

                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)
                    {
                        throw new Exception("No entrypoint module");
                    }

                    compilationRoots.Add(new ExportedMethodsRootProvider((EcmaModule)typeSystemContext.SystemModule));

                    compilationGroup = new SingleFileCompilationModuleGroup(typeSystemContext);
                }

                foreach (var rdXmlFilePath in _rdXmlFilePaths)
                {
                    compilationRoots.Add(new RdXmlRootProvider(typeSystemContext, rdXmlFilePath));
                }
            }

            //
            // Compile
            //

            CompilationBuilder builder;

            if (_isCppCodegen)
            {
                builder = new CppCodegenCompilationBuilder(typeSystemContext, compilationGroup);
            }
            else
            {
                builder = new RyuJitCompilationBuilder(typeSystemContext, compilationGroup);
            }

            var logger = _isVerbose ? new Logger(Console.Out, true) : Logger.Null;

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

            CompilerGeneratedMetadataManager metadataManager = new CompilerGeneratedMetadataManager(compilationGroup, typeSystemContext, _metadataLogFileName);

            ICompilation compilation = builder
                                       .UseBackendOptions(_codegenOptions)
                                       .UseMetadataManager(metadataManager)
                                       .UseLogger(logger)
                                       .UseDependencyTracking(trackingLevel)
                                       .UseCompilationRoots(compilationRoots)
                                       .UseOptimizationMode(_optimizationMode)
                                       .UseDebugInfo(_enableDebugInfo)
                                       .ToCompilation();

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

            compilation.Compile(_outputFilePath, dumper);

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

            return(0);
        }
Beispiel #4
0
        private int Run(string[] args)
        {
            InitializeDefaultOptions();

            ArgumentSyntax syntax = ParseCommandLine(args);

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

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

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

            //
            // Initialize type system context
            //

            SharedGenericsMode genericsMode = _useSharedGenerics ?
                                              SharedGenericsMode.CanonicalReferenceTypes : SharedGenericsMode.Disabled;

            var typeSystemContext = new CompilerTypeSystemContext(new TargetDetails(_targetArchitecture, _targetOS), genericsMode);

            typeSystemContext.InputFilePaths     = _inputFilePaths;
            typeSystemContext.ReferenceFilePaths = _referenceFilePaths;

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

            //
            // 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;
                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;
                    }

                    compilationRoots.Add(new ExportedMethodsRootProvider(module));
                }

                if (entrypointModule != null)
                {
                    LibraryInitializers libraryInitializers =
                        new LibraryInitializers(typeSystemContext, _isCppCodegen);
                    compilationRoots.Add(new MainMethodRootProvider(entrypointModule, libraryInitializers.LibraryInitializerMethods));
                }

                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);
                    }

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

                    compilationRoots.Add(new ExportedMethodsRootProvider((EcmaModule)typeSystemContext.SystemModule));

                    compilationGroup = new SingleFileCompilationModuleGroup(typeSystemContext);
                }

                foreach (var rdXmlFilePath in _rdXmlFilePaths)
                {
                    compilationRoots.Add(new RdXmlRootProvider(typeSystemContext, rdXmlFilePath));
                }
            }

            //
            // Compile
            //

            CompilationBuilder builder;

            if (_isCppCodegen)
            {
                builder = new CppCodegenCompilationBuilder(typeSystemContext, compilationGroup);
            }
            else
            {
                builder = new RyuJitCompilationBuilder(typeSystemContext, compilationGroup);
            }

            var logger = _isVerbose ? new Logger(Console.Out, true) : Logger.Null;

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

            ICompilation compilation = builder
                                       .UseBackendOptions(_codegenOptions)
                                       .UseLogger(logger)
                                       .UseDependencyTracking(trackingLevel)
                                       .UseCompilationRoots(compilationRoots)
                                       .UseOptimizationMode(_optimizationMode)
                                       .UseDebugInfo(_enableDebugInfo)
                                       .ToCompilation();

            compilation.Compile(_outputFilePath);

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

            return(0);
        }