Beispiel #1
0
        static int Execute(ArgumentSyntax argSyntax)
        {
            CodeGeneratorOptions options;

            try
            {
                options = CreateCodeGeneratorOptions(argSyntax);
            }
            catch (InvalidOperationException exception)
            {
                Console.Error.WriteLine(exception.Message);
                Console.WriteLine(argSyntax.GetHelpText());
                return(1);
            }

            var codeGeneratorOptions = Options.Create(options);

            var codeGenerator = new CodeGenerator(codeGeneratorOptions);

            codeGenerator.GenerateContentTypeModels(options.StructuredModel);

            if (!options.ContentManagementApi && options.WithTypeProvider)
            {
                codeGenerator.GenerateTypeProvider();
            }

            if (!string.IsNullOrEmpty(options.BaseClass))
            {
                codeGenerator.GenerateBaseClass();
            }

            return(0);
        }
Beispiel #2
0
        private int Run(string[] args)
        {
            ArgumentSyntax syntax = ParseCommandLine(args);

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

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

            _verifier = new Verifier(this);
            _verifier.SetSystemModuleName(_systemModule);

            foreach (var kvp in _inputFilePaths)
            {
                VerifyAssembly(new AssemblyName(kvp.Key), kvp.Value);
            }

            return(0);
        }
        public CommandLineOptionsProvider(ArgumentSyntax syntax)
        {
            try
            {
                IEnumerable <Argument> appOptions = syntax.GetOptions();
                foreach (var commandOption in appOptions)
                {
                    if (commandOption.Value != null)
                    {
                        string value = commandOption.Value.ToString();

                        if (!string.IsNullOrEmpty(value))
                        {
                            var paramName = commandOption.Names.Last();

                            /// Backward compatibility <see href="https://github.com/Kentico/kontent-generators-net/issues/69"/>
                            if (paramName == "projectid")
                            {
                                paramName = $"{nameof(DeliveryOptions)}:ProjectId";
                            }

                            Data.Add(paramName, value);
                        }
                    }
                }
            }
            catch (InvalidOperationException exception)
            {
                throw new Exception(exception.Message + "\n\n" + syntax.GetHelpText());
            }
        }
Beispiel #4
0
        private int Run(string[] args)
        {
            InitializeDefaultOptions();

            ArgumentSyntax syntax = ParseCommandLine(args);

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

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

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

            // For now, we can do single file compilation only
            // TODO: Multifile
            SingleFileCompilation();

            return(0);
        }
Beispiel #5
0
        private int Run(string[] args)
        {
            ArgumentSyntax syntax = ParseCommandLine(args);

            if (_help)
            {
                _writer.WriteLine(syntax.GetHelpText());
                return(0);
            }

            if (_inputFilenames.Count == 0)
            {
                throw new ArgumentException("Input filename must be specified (--in <file>)");
            }

            // open output stream
            if (_outputFilename != null)
            {
                _writer = File.CreateText(_outputFilename);
            }
            else
            {
                _writer = Console.Out;
            }

            try
            {
                foreach (string filename in _inputFilenames)
                {
                    R2RReader r2r = new R2RReader(filename);
                    if (_disasm)
                    {
                        _disassembler = CoreDisTools.GetDisasm(r2r.Machine);
                    }

                    Dump(r2r);

                    if (_disasm)
                    {
                        CoreDisTools.FinishDisasm(_disassembler);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Error: " + e.ToString());
                return(1);
            }
            finally
            {
                // close output stream
                _writer.Close();
            }

            return(0);
        }
Beispiel #6
0
        private int Run(string[] args)
        {
            ArgumentSyntax syntax = ParseCommandLine(args);

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

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

            _verifier = new Verifier(this);
            _verifier.SetSystemModuleName(_systemModule);

            foreach (var kvp in _inputFilePaths)
            {
                var results   = VerifyAssembly(new AssemblyName(kvp.Key), out EcmaModule module);
                int numErrors = 0;

                foreach (var result in results)
                {
                    numErrors++;
                    PrintResult(result, module, kvp.Value);
                }

                if (numErrors > 0)
                {
                    WriteLine(numErrors + " Error(s) Verifying " + kvp.Value);
                }
                else
                {
                    WriteLine("All Classes and Methods in " + kvp.Value + " Verified.");
                }
            }

            return(0);
        }
Beispiel #7
0
        private int Run(string[] args)
        {
            ArgumentSyntax syntax = ParseCommandLine(args);

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

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

            _typeSystemContext = new SimpleTypeSystemContext();
            _typeSystemContext.InputFilePaths     = _inputFilePaths;
            _typeSystemContext.ReferenceFilePaths = _referenceFilePaths;

            _typeSystemContext.SetSystemModule(_typeSystemContext.GetModuleForSimpleName(SystemModuleSimpleName));

            foreach (var inputPath in _inputFilePaths.Values)
            {
                _numErrors = 0;

                VerifyModule(_typeSystemContext.GetModuleFromPath(inputPath));

                if (_numErrors > 0)
                {
                    Console.WriteLine(_numErrors + " Error(s) Verifying " + inputPath);
                }
                else
                {
                    Console.WriteLine("All Classes and Methods in " + inputPath + " Verified.");
                }
            }

            return(0);
        }
Beispiel #8
0
        private string Process(Configurator configurator, string value, bool getHelpText)
        {
            // Parse the directive value
            IEnumerable <string> arguments = ArgumentSplitter.Split(value);
            ArgumentSyntax       parsed    = null;
            string    helpText             = null;
            TSettings settings             = new TSettings();

            try
            {
                parsed = ArgumentSyntax.Parse(arguments, syntax =>
                {
                    syntax.HandleErrors = !getHelpText;
                    Define(syntax, settings);
                    if (getHelpText)
                    {
                        helpText = syntax.GetHelpText();
                    }
                });
            }
            catch (Exception)
            {
                if (!getHelpText)
                {
                    throw;
                }
            }
            if (getHelpText)
            {
                return(helpText);
            }
            if (parsed.HasErrors)
            {
                throw new Exception(parsed.GetHelpText());
            }

            Process(configurator, settings);
            return(null);
        }
Beispiel #9
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;
            }

            InstructionSetSupportBuilder instructionSetSupportBuilder = new InstructionSetSupportBuilder(_targetArchitecture);

            // The runtime expects certain baselines that the codegen can assume as well.
            if ((_targetArchitecture == TargetArchitecture.X86) || (_targetArchitecture == TargetArchitecture.X64))
            {
                instructionSetSupportBuilder.AddSupportedInstructionSet("sse");
                instructionSetSupportBuilder.AddSupportedInstructionSet("sse2");
            }
            else if (_targetArchitecture == TargetArchitecture.ARM64)
            {
                instructionSetSupportBuilder.AddSupportedInstructionSet("base");
                instructionSetSupportBuilder.AddSupportedInstructionSet("neon");
            }

            if (_instructionSet != null)
            {
                List <string> instructionSetParams = new List <string>();

                // Normalize instruction set format to include implied +.
                string[] instructionSetParamsInput = _instructionSet.Split(',');
                for (int i = 0; i < instructionSetParamsInput.Length; i++)
                {
                    string instructionSet = instructionSetParamsInput[i];

                    if (String.IsNullOrEmpty(instructionSet))
                    {
                        throw new CommandLineException("Instruction set must not be empty");
                    }

                    char firstChar = instructionSet[0];
                    if ((firstChar != '+') && (firstChar != '-'))
                    {
                        instructionSet = "+" + instructionSet;
                    }
                    instructionSetParams.Add(instructionSet);
                }

                Dictionary <string, bool> instructionSetSpecification = new Dictionary <string, bool>();
                foreach (string instructionSetSpecifier in instructionSetParams)
                {
                    string instructionSet = instructionSetSpecifier.Substring(1, instructionSetSpecifier.Length - 1);

                    bool enabled = instructionSetSpecifier[0] == '+' ? true : false;
                    if (enabled)
                    {
                        if (!instructionSetSupportBuilder.AddSupportedInstructionSet(instructionSet))
                        {
                            throw new CommandLineException($"Unrecognized instruction set '{instructionSet}'");
                        }
                    }
                    else
                    {
                        if (!instructionSetSupportBuilder.RemoveInstructionSetSupport(instructionSet))
                        {
                            throw new CommandLineException($"Unrecognized instruction set '{instructionSet}'");
                        }
                    }
                }
            }

            instructionSetSupportBuilder.ComputeInstructionSetFlags(out var supportedInstructionSet, out var unsupportedInstructionSet,
                                                                    (string specifiedInstructionSet, string impliedInstructionSet) =>
                                                                    throw new CommandLineException(String.Format("Unsupported combination of instruction sets: {0}/{1}", specifiedInstructionSet, impliedInstructionSet)));

            InstructionSetSupportBuilder optimisticInstructionSetSupportBuilder = new InstructionSetSupportBuilder(_targetArchitecture);

            // Optimistically assume some instruction sets are present.
            if ((_targetArchitecture == TargetArchitecture.X86) || (_targetArchitecture == TargetArchitecture.X64))
            {
                // We set these hardware features as enabled always, as most
                // of hardware in the wild supports them. Note that we do not indicate support for AVX, or any other
                // instruction set which uses the VEX encodings as the presence of those makes otherwise acceptable
                // code be unusable on hardware which does not support VEX encodings, as well as emulators that do not
                // support AVX instructions.
                //
                // The compiler is able to generate runtime IsSupported checks for the following instruction sets.
                optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("ssse3");
                optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("aes");
                optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("pclmul");
                optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("lzcnt");

                // NOTE: we don't optimistically enable SSE4.1/SSE4.2 because RyuJIT can opportunistically use
                // these instructions in e.g. optimizing Math.Round or Vector<T> operations without IsSupported guards.

                // If SSE4.2 was enabled, we can also opportunistically enable POPCNT
                Debug.Assert(InstructionSet.X64_SSE42 == InstructionSet.X86_SSE42);
                if (supportedInstructionSet.HasInstructionSet(InstructionSet.X64_SSE42))
                {
                    optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("popcnt");
                }

                // If AVX was enabled, we can opportunistically enable FMA/BMI
                Debug.Assert(InstructionSet.X64_AVX == InstructionSet.X86_AVX);
                if (supportedInstructionSet.HasInstructionSet(InstructionSet.X64_AVX))
                {
                    optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("fma");
                    optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("bmi1");
                    optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("bmi2");
                }
            }

            optimisticInstructionSetSupportBuilder.ComputeInstructionSetFlags(out var optimisticInstructionSet, out _,
                                                                              (string specifiedInstructionSet, string impliedInstructionSet) => throw new NotSupportedException());
            optimisticInstructionSet.Remove(unsupportedInstructionSet);
            optimisticInstructionSet.Add(supportedInstructionSet);

            var instructionSetSupport = new InstructionSetSupport(supportedInstructionSet,
                                                                  unsupportedInstructionSet,
                                                                  optimisticInstructionSet,
                                                                  InstructionSetSupportBuilder.GetNonSpecifiableInstructionSetsForArch(_targetArchitecture),
                                                                  _targetArchitecture);

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

            //
            // Initialize type system context
            //

            SharedGenericsMode genericsMode = SharedGenericsMode.CanonicalReferenceTypes;

            var simdVectorLength = (_isCppCodegen || _isWasmCodegen) ? SimdVectorLength.None : instructionSetSupport.GetVectorTSimdVector();
            var targetAbi        = _isCppCodegen ? TargetAbi.CppCodegen : TargetAbi.CoreRT;
            var targetDetails    = new TargetDetails(_targetArchitecture, _targetOS, targetAbi, simdVectorLength);
            CompilerTypeSystemContext typeSystemContext =
                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;
            if (!typeSystemContext.InputFilePaths.ContainsKey(_systemModuleName) &&
                !typeSystemContext.ReferenceFilePaths.ContainsKey(_systemModuleName))
            {
                throw new CommandLineException($"System module {_systemModuleName} does not exists. Make sure that you specify --systemmodule");
            }

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

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

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

                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));
                    compilationRoots.Add(new ExpectedIsaFeaturesRootProvider(instructionSetSupport));
                }

                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 (_isCppCodegen)
            {
                builder = new CppCodegenCompilationBuilder(typeSystemContext, compilationGroup);
            }
            else
            {
                builder = new RyuJitCompilationBuilder(typeSystemContext, compilationGroup);
            }

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

            builder.UseCompilationUnitPrefix(compilationUnitPrefix);

            PInvokeILEmitterConfiguration pinvokePolicy;

            if (!_isCppCodegen && !_isWasmCodegen)
            {
                pinvokePolicy = new ConfigurablePInvokePolicy(typeSystemContext.Target);
            }
            else
            {
                pinvokePolicy = new DirectPInvokePolicy();
            }

            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 == "SerializationGuard")
                {
                    removedFeatures |= RemovedFeature.SerializationGuard;
                }
                else if (feature == "XmlNonFileStream")
                {
                    removedFeatures |= RemovedFeature.XmlDownloadNonFileStream;
                }
            }

            ILProvider ilProvider = new CoreRTILProvider();

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

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

            MetadataBlockingPolicy              mdBlockingPolicy;
            ManifestResourceBlockingPolicy      resBlockingPolicy;
            UsageBasedMetadataGenerationOptions metadataGenerationOptions = UsageBasedMetadataGenerationOptions.IteropILScanning;

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

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

                metadataGenerationOptions |= UsageBasedMetadataGenerationOptions.AnonymousTypeHeuristic;
                if (_completeTypesMetadata)
                {
                    metadataGenerationOptions |= UsageBasedMetadataGenerationOptions.CompleteTypesOnly;
                }
                if (_scanReflection)
                {
                    metadataGenerationOptions |= UsageBasedMetadataGenerationOptions.ReflectionILScanning;
                }
                if (_rootAllApplicationAssemblies)
                {
                    metadataGenerationOptions |= UsageBasedMetadataGenerationOptions.FullUserAssemblyRooting;
                }
            }
            else
            {
                mdBlockingPolicy  = new FullyBlockedMetadataBlockingPolicy();
                resBlockingPolicy = new FullyBlockedManifestResourceBlockingPolicy();
            }

            DynamicInvokeThunkGenerationPolicy invokeThunkGenerationPolicy = new DefaultDynamicInvokeThunkGenerationPolicy();

            MetadataManager metadataManager = new UsageBasedMetadataManager(
                compilationGroup,
                typeSystemContext,
                mdBlockingPolicy,
                resBlockingPolicy,
                _metadataLogFileName,
                stackTracePolicy,
                invokeThunkGenerationPolicy,
                ilProvider,
                metadataGenerationOptions);

            InteropStateManager interopStateManager = new InteropStateManager(typeSystemContext.GeneratedAssembly);
            InteropStubManager  interopStubManager  = new UsageBasedInteropStubManager(interopStateManager, pinvokePolicy);

            // 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 && !_multiFile);

            useScanner &= !_noScanner;

            // Enable static data preinitialization in optimized builds.
            bool preinitStatics = _preinitStatics ||
                                  (_optimizationMode != OptimizationMode.None && !_isCppCodegen && !_multiFile);

            preinitStatics &= !_noPreinitStatics;

            var preinitManager = new PreinitializationManager(typeSystemContext, compilationGroup, ilProvider, preinitStatics);

            builder
            .UseILProvider(ilProvider)
            .UsePreinitializationManager(preinitManager);

            ILScanResults scanResults = null;

            if (useScanner)
            {
                ILScannerBuilder scannerBuilder = builder.GetILScannerBuilder()
                                                  .UseCompilationRoots(compilationRoots)
                                                  .UseMetadataManager(metadataManager)
                                                  .UseSingleThread(enable: _singleThreaded)
                                                  .UseInteropStubManager(interopStubManager);

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

                IILScanner scanner = scannerBuilder.ToILScanner();

                scanResults = scanner.Scan();

                metadataManager = ((UsageBasedMetadataManager)metadataManager).ToAnalysisBasedMetadataManager();

                interopStubManager = scanResults.GetInteropStubManager(interopStateManager, pinvokePolicy);
            }

            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);
            compilationRoots.Add(interopStubManager);

            builder
            .UseInstructionSetSupport(instructionSetSupport)
            .UseBackendOptions(_codegenOptions)
            .UseMethodBodyFolding(enable: _methodBodyFolding)
            .UseSingleThread(enable: _singleThreaded)
            .UseMetadataManager(metadataManager)
            .UseInteropStubManager(interopStubManager)
            .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)
            {
                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" || method.Name == "ThrowArgumentOutOfRangeException");
                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) || method.OwningType.IsIntrinsic);
                    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();
            }

            preinitManager.LogStatistics(logger);

            return(0);
        }
Beispiel #10
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 && _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 =
                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;
                    }

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

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

                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 (_isCppCodegen)
            {
                builder = new CppCodegenCompilationBuilder(typeSystemContext, compilationGroup);
            }
            else
            {
                builder = new RyuJitCompilationBuilder(typeSystemContext, compilationGroup);
            }

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

            builder.UseCompilationUnitPrefix(compilationUnitPrefix);

            PInvokeILEmitterConfiguration pinvokePolicy;

            if (!_isCppCodegen && !_isWasmCodegen)
            {
                pinvokePolicy = new ConfigurablePInvokePolicy(typeSystemContext.Target);
            }
            else
            {
                pinvokePolicy = new DirectPInvokePolicy();
            }

            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 = 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 (supportsReflection)
            {
                metadataManager = new UsageBasedMetadataManager(
                    compilationGroup,
                    typeSystemContext,
                    mdBlockingPolicy,
                    resBlockingPolicy,
                    _metadataLogFileName,
                    stackTracePolicy,
                    invokeThunkGenerationPolicy,
                    ilProvider,
                    metadataGenerationOptions);
            }
            else
            {
                metadataManager = new EmptyMetadataManager(typeSystemContext, stackTracePolicy, ilProvider);
            }

            InteropStateManager interopStateManager = new InteropStateManager(typeSystemContext.GeneratedAssembly);
            InteropStubManager  interopStubManager  = new UsageBasedInteropStubManager(interopStateManager, pinvokePolicy);

            // 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 && !_multiFile);

            useScanner &= !_noScanner;

            builder.UseILProvider(ilProvider);

            ILScanResults scanResults = null;

            if (useScanner)
            {
                ILScannerBuilder scannerBuilder = builder.GetILScannerBuilder()
                                                  .UseCompilationRoots(compilationRoots)
                                                  .UseMetadataManager(metadataManager)
                                                  .UseSingleThread(enable: _singleThreaded)
                                                  .UseInteropStubManager(interopStubManager);

                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();
                }
                else
                {
                    // MetadataManager collects a bunch of state (e.g. list of compiled method bodies) that we need to reset.
                    Debug.Assert(metadataManager is EmptyMetadataManager);
                    metadataManager = new EmptyMetadataManager(typeSystemContext, stackTracePolicy, ilProvider);
                }

                interopStubManager = scanResults.GetInteropStubManager(interopStateManager, pinvokePolicy);
            }

            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);
            compilationRoots.Add(interopStubManager);

            builder
            .UseBackendOptions(_codegenOptions)
            .UseMethodBodyFolding(enable: _methodBodyFolding)
            .UseSingleThread(enable: _singleThreaded)
            .UseMetadataManager(metadataManager)
            .UseInteropStubManager(interopStubManager)
            .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);
        }
Beispiel #11
0
        public CommandLineOptions(string[] args)
        {
            InputFilePaths = Array.Empty <string>();
            InputBubbleReferenceFilePaths = Array.Empty <string>();
            UnrootedInputFilePaths        = Array.Empty <string>();
            ReferenceFilePaths            = Array.Empty <string>();
            MibcFilePaths  = Array.Empty <string>();
            CodegenOptions = Array.Empty <string>();

            PerfMapFormatVersion   = DefaultPerfMapFormatVersion;
            Parallelism            = Environment.ProcessorCount;
            SingleMethodGenericArg = null;

            bool forceHelp = false;

            if (args.Length == 0)
            {
                forceHelp = true;
            }

            foreach (string arg in args)
            {
                if (arg == "-?")
                {
                    forceHelp = true;
                }
            }

            if (forceHelp)
            {
                args = new string[] { "--help" };
            }

            ArgumentSyntax argSyntax = ArgumentSyntax.Parse(args, syntax =>
            {
                syntax.ApplicationName = typeof(Program).Assembly.GetName().Name.ToString();

                // HandleHelp writes to error, fails fast with crash dialog and lacks custom formatting.
                syntax.HandleHelp   = false;
                syntax.HandleErrors = true;

                syntax.DefineOptionList("u|unrooted-input-file-paths", ref UnrootedInputFilePaths, SR.UnrootedInputFilesToCompile);
                syntax.DefineOptionList("r|reference", ref ReferenceFilePaths, SR.ReferenceFiles);
                syntax.DefineOption("instruction-set", ref InstructionSet, SR.InstructionSets);
                syntax.DefineOptionList("m|mibc", ref MibcFilePaths, SR.MibcFiles);
                syntax.DefineOption("o|out|outputfilepath", ref OutputFilePath, SR.OutputFilePath);
                syntax.DefineOption("crp|compositerootpath", ref CompositeRootPath, SR.CompositeRootPath);
                syntax.DefineOption("O|optimize", ref Optimize, SR.EnableOptimizationsOption);
                syntax.DefineOption("Od|optimize-disabled", ref OptimizeDisabled, SR.DisableOptimizationsOption);
                syntax.DefineOption("Os|optimize-space", ref OptimizeSpace, SR.OptimizeSpaceOption);
                syntax.DefineOption("Ot|optimize-time", ref OptimizeTime, SR.OptimizeSpeedOption);
                syntax.DefineOption("inputbubble", ref InputBubble, SR.InputBubbleOption);
                syntax.DefineOptionList("inputbubbleref", ref InputBubbleReferenceFilePaths, SR.InputBubbleReferenceFiles);
                syntax.DefineOption("composite", ref Composite, SR.CompositeBuildMode);
                syntax.DefineOption("compositekeyfile", ref CompositeKeyFile, SR.CompositeKeyFile);
                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);
                syntax.DefineOption("embed-pgo-data", ref EmbedPgoData, SR.EmbedPgoDataOption);
                syntax.DefineOption("dgmllog|dgml-log-file-name", ref DgmlLogFileName, SR.SaveDependencyLogOption);
                syntax.DefineOption("fulllog|generate-full-dmgl-log", ref GenerateFullDgmlLog, SR.SaveDetailedLogOption);
                syntax.DefineOption("verbose", ref Verbose, SR.VerboseLoggingOption);
                syntax.DefineOption("systemmodule", ref SystemModule, SR.SystemModuleOverrideOption);
                syntax.DefineOption("waitfordebugger", ref WaitForDebugger, SR.WaitForDebuggerOption);
                syntax.DefineOptionList("codegenopt|codegen-options", ref CodegenOptions, SR.CodeGenOptions);
                syntax.DefineOption("resilient", ref Resilient, SR.ResilientOption);

                syntax.DefineOption("targetarch", ref TargetArch, SR.TargetArchOption);
                syntax.DefineOption("targetos", ref TargetOS, SR.TargetOSOption);
                syntax.DefineOption("jitpath", ref JitPath, SR.JitPathOption);

                syntax.DefineOption("print-repro-instructions", ref PrintReproInstructions, SR.PrintReproInstructionsOption);
                syntax.DefineOption("singlemethodtypename", ref SingleMethodTypeName, SR.SingleMethodTypeName);
                syntax.DefineOption("singlemethodname", ref SingleMethodName, SR.SingleMethodMethodName);
                syntax.DefineOption("singlemethodindex", ref SingleMethodIndex, SR.SingleMethodIndex);
                syntax.DefineOptionList("singlemethodgenericarg", ref SingleMethodGenericArg, SR.SingleMethodGenericArgs);

                syntax.DefineOption("parallelism", ref Parallelism, SR.ParalellismOption);
                syntax.DefineOption("custom-pe-section-alignment", ref CustomPESectionAlignment, SR.CustomPESectionAlignmentOption);
                syntax.DefineOption("map", ref Map, SR.MapFileOption);
                syntax.DefineOption("mapcsv", ref MapCsv, SR.MapCsvFileOption);
                syntax.DefineOption("pdb", ref Pdb, SR.PdbFileOption);
                syntax.DefineOption("pdb-path", ref PdbPath, SR.PdbFilePathOption);
                syntax.DefineOption("perfmap", ref PerfMap, SR.PerfMapFileOption);
                syntax.DefineOption("perfmap-path", ref PerfMapPath, SR.PerfMapFilePathOption);
                syntax.DefineOption("perfmap-format-version", ref PerfMapFormatVersion, SR.PerfMapFormatVersionOption);

                syntax.DefineOption("method-layout", ref MethodLayout, SR.MethodLayoutOption);
                syntax.DefineOption("file-layout", ref FileLayout, SR.FileLayoutOption);
                syntax.DefineOption("verify-type-and-field-layout", ref VerifyTypeAndFieldLayout, SR.VerifyTypeAndFieldLayoutOption);
                syntax.DefineOption("callchain-profile", ref CallChainProfileFile, SR.CallChainProfileFile);

                syntax.DefineOption("make-repro-path", ref MakeReproPath, SR.MakeReproPathHelp);

                syntax.DefineOption("h|help", ref Help, SR.HelpOption);

                syntax.DefineParameterList("in", ref InputFilePaths, SR.InputFilesToCompile);
            });

            if (Help)
            {
                List <string> extraHelp = new List <string>();
                extraHelp.Add(SR.OptionPassingHelp);
                extraHelp.Add("");
                extraHelp.Add(SR.DashDashHelp);
                extraHelp.Add("");

                string[]           ValidArchitectures = new string[] { "arm", "armel", "arm64", "x86", "x64" };
                string[]           ValidOS            = new string[] { "windows", "linux", "osx" };
                TargetOS           defaultOs;
                TargetArchitecture defaultArch;
                Program.ComputeDefaultOptions(out defaultOs, out defaultArch);

                extraHelp.Add(String.Format(SR.SwitchWithDefaultHelp, "--targetos", String.Join("', '", ValidOS), defaultOs.ToString().ToLowerInvariant()));

                extraHelp.Add("");

                extraHelp.Add(String.Format(SR.SwitchWithDefaultHelp, "--targetarch", String.Join("', '", ValidArchitectures), defaultArch.ToString().ToLowerInvariant()));

                extraHelp.Add("");

                extraHelp.Add(SR.InstructionSetHelp);
                foreach (string arch in ValidArchitectures)
                {
                    StringBuilder archString = new StringBuilder();

                    archString.Append(arch);
                    archString.Append(": ");

                    TargetArchitecture targetArch = Program.GetTargetArchitectureFromArg(arch, out _);
                    bool first = true;
                    foreach (var instructionSet in Internal.JitInterface.InstructionSetFlags.ArchitectureToValidInstructionSets(targetArch))
                    {
                        // Only instruction sets with are specifiable should be printed to the help text
                        if (instructionSet.Specifiable)
                        {
                            if (first)
                            {
                                first = false;
                            }
                            else
                            {
                                archString.Append(", ");
                            }
                            archString.Append(instructionSet.Name);
                        }
                    }

                    extraHelp.Add(archString.ToString());
                }

                argSyntax.ExtraHelpParagraphs = extraHelp;

                HelpText = argSyntax.GetHelpText();
            }

            if (MakeReproPath != null)
            {
                // Create a repro package in the specified path
                // This package will have the set of input files needed for compilation
                // + the original command line arguments
                // + a rsp file that should work to directly run out of the zip file

                string makeReproPath = MakeReproPath;
                Directory.CreateDirectory(makeReproPath);

                List <string> crossgenDetails = new List <string>();
                crossgenDetails.Add("CrossGen2 version");
                try
                {
                    crossgenDetails.Add(Environment.GetCommandLineArgs()[0]);
                } catch  {}
                try
                {
                    crossgenDetails.Add(System.Diagnostics.FileVersionInfo.GetVersionInfo(Environment.GetCommandLineArgs()[0]).ToString());
                } catch  {}

                crossgenDetails.Add("------------------------");
                crossgenDetails.Add("Actual Command Line Args");
                crossgenDetails.Add("------------------------");
                crossgenDetails.AddRange(args);
                foreach (string arg in args)
                {
                    if (arg.StartsWith('@'))
                    {
                        string rspFileName = arg.Substring(1);
                        crossgenDetails.Add("------------------------");
                        crossgenDetails.Add(rspFileName);
                        crossgenDetails.Add("------------------------");
                        try
                        {
                            crossgenDetails.AddRange(File.ReadAllLines(rspFileName));
                        } catch  {}
                    }
                }

                HashCode hashCodeOfArgs = new HashCode();
                foreach (string s in crossgenDetails)
                {
                    hashCodeOfArgs.Add(s);
                }

                string zipFileName = ((uint)hashCodeOfArgs.ToHashCode()).ToString();

                if (OutputFilePath != null)
                {
                    zipFileName = zipFileName + "_" + Path.GetFileName(OutputFilePath);
                }

                zipFileName = Path.Combine(MakeReproPath, Path.ChangeExtension(zipFileName, ".zip"));

                Console.WriteLine($"Creating {zipFileName}");
                using (var archive = ZipFile.Open(zipFileName, ZipArchiveMode.Create))
                {
                    ZipArchiveEntry commandEntry = archive.CreateEntry("crossgen2command.txt");
                    using (StreamWriter writer = new StreamWriter(commandEntry.Open()))
                    {
                        foreach (string s in crossgenDetails)
                        {
                            writer.WriteLine(s);
                        }
                    }

                    HashSet <string> inputOptionNames = new HashSet <string>();
                    inputOptionNames.Add("-r");
                    inputOptionNames.Add("-u");
                    inputOptionNames.Add("-m");
                    inputOptionNames.Add("--inputbubbleref");
                    Dictionary <string, string> inputToReproPackageFileName = new Dictionary <string, string>();

                    List <string> rspFile = new List <string>();
                    foreach (var option in argSyntax.GetOptions())
                    {
                        if (option.GetDisplayName() == "--make-repro-path")
                        {
                            continue;
                        }

                        if (option.Value != null && !option.Value.Equals(option.DefaultValue))
                        {
                            if (option.IsList)
                            {
                                if (inputOptionNames.Contains(option.GetDisplayName()))
                                {
                                    Dictionary <string, string> dictionary = new Dictionary <string, string>();
                                    foreach (string optInList in (IEnumerable)option.Value)
                                    {
                                        Helpers.AppendExpandedPaths(dictionary, optInList, false);
                                    }
                                    foreach (string inputFile in dictionary.Values)
                                    {
                                        rspFile.Add($"{option.GetDisplayName()}:{ConvertFromInputPathToReproPackagePath(inputFile)}");
                                    }
                                }
                                else
                                {
                                    foreach (object optInList in (IEnumerable)option.Value)
                                    {
                                        rspFile.Add($"{option.GetDisplayName()}:{optInList}");
                                    }
                                }
                            }
                            else
                            {
                                rspFile.Add($"{option.GetDisplayName()}:{option.Value}");
                            }
                        }
                    }

                    foreach (var parameter in argSyntax.GetParameters())
                    {
                        if (parameter.Value != null)
                        {
                            if (parameter.IsList)
                            {
                                foreach (object optInList in (IEnumerable)parameter.Value)
                                {
                                    rspFile.Add($"{ConvertFromInputPathToReproPackagePath((string)optInList)}");
                                }
                            }
                            else
                            {
                                rspFile.Add($"{ConvertFromInputPathToReproPackagePath((string)parameter.Value.ToString())}");
                            }
                        }
                    }

                    ZipArchiveEntry rspEntry = archive.CreateEntry("crossgen2repro.rsp");
                    using (StreamWriter writer = new StreamWriter(rspEntry.Open()))
                    {
                        foreach (string s in rspFile)
                        {
                            writer.WriteLine(s);
                        }
                    }

                    string ConvertFromInputPathToReproPackagePath(string inputPath)
                    {
                        if (inputToReproPackageFileName.TryGetValue(inputPath, out string reproPackagePath))
                        {
                            return(reproPackagePath);
                        }

                        try
                        {
                            string inputFileDir = inputToReproPackageFileName.Count.ToString();
                            reproPackagePath = Path.Combine(inputFileDir, Path.GetFileName(inputPath));
                            archive.CreateEntryFromFile(inputPath, reproPackagePath);
                            inputToReproPackageFileName.Add(inputPath, reproPackagePath);

                            return(reproPackagePath);
                        }
                        catch
                        {
                            return(inputPath);
                        }
                    }
                }
            }
        }
Beispiel #12
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 #13
0
        public CommandLineOptions(string[] args)
        {
            InputFilePaths = Array.Empty <string>();
            InputBubbleReferenceFilePaths = Array.Empty <string>();
            UnrootedInputFilePaths        = Array.Empty <string>();
            ReferenceFilePaths            = Array.Empty <string>();
            MibcFilePaths  = Array.Empty <string>();
            CodegenOptions = Array.Empty <string>();

            PerfMapFormatVersion   = DefaultPerfMapFormatVersion;
            Parallelism            = Environment.ProcessorCount;
            SingleMethodGenericArg = null;

            bool forceHelp = false;

            if (args.Length == 0)
            {
                forceHelp = true;
            }

            foreach (string arg in args)
            {
                if (arg == "-?")
                {
                    forceHelp = true;
                }
            }

            if (forceHelp)
            {
                args = new string[] { "--help" };
            }

            ArgumentSyntax argSyntax = ArgumentSyntax.Parse(args, syntax =>
            {
                syntax.ApplicationName = typeof(Program).Assembly.GetName().Name.ToString();

                // HandleHelp writes to error, fails fast with crash dialog and lacks custom formatting.
                syntax.HandleHelp   = false;
                syntax.HandleErrors = true;

                syntax.DefineOptionList("u|unrooted-input-file-paths", ref UnrootedInputFilePaths, SR.UnrootedInputFilesToCompile);
                syntax.DefineOptionList("r|reference", ref ReferenceFilePaths, SR.ReferenceFiles);
                syntax.DefineOption("instruction-set", ref InstructionSet, SR.InstructionSets);
                syntax.DefineOptionList("m|mibc", ref MibcFilePaths, SR.MibcFiles);
                syntax.DefineOption("o|out|outputfilepath", ref OutputFilePath, SR.OutputFilePath);
                syntax.DefineOption("crp|compositerootpath", ref CompositeRootPath, SR.CompositeRootPath);
                syntax.DefineOption("O|optimize", ref Optimize, SR.EnableOptimizationsOption);
                syntax.DefineOption("Od|optimize-disabled", ref OptimizeDisabled, SR.DisableOptimizationsOption);
                syntax.DefineOption("Os|optimize-space", ref OptimizeSpace, SR.OptimizeSpaceOption);
                syntax.DefineOption("Ot|optimize-time", ref OptimizeTime, SR.OptimizeSpeedOption);
                syntax.DefineOption("inputbubble", ref InputBubble, SR.InputBubbleOption);
                syntax.DefineOptionList("inputbubbleref", ref InputBubbleReferenceFilePaths, SR.InputBubbleReferenceFiles);
                syntax.DefineOption("composite", ref Composite, SR.CompositeBuildMode);
                syntax.DefineOption("compositekeyfile", ref CompositeKeyFile, SR.CompositeKeyFile);
                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);
                syntax.DefineOption("embed-pgo-data", ref EmbedPgoData, SR.EmbedPgoDataOption);
                syntax.DefineOption("dgmllog|dgml-log-file-name", ref DgmlLogFileName, SR.SaveDependencyLogOption);
                syntax.DefineOption("fulllog|generate-full-dmgl-log", ref GenerateFullDgmlLog, SR.SaveDetailedLogOption);
                syntax.DefineOption("verbose", ref Verbose, SR.VerboseLoggingOption);
                syntax.DefineOption("systemmodule", ref SystemModule, SR.SystemModuleOverrideOption);
                syntax.DefineOption("waitfordebugger", ref WaitForDebugger, SR.WaitForDebuggerOption);
                syntax.DefineOptionList("codegenopt|codegen-options", ref CodegenOptions, SR.CodeGenOptions);
                syntax.DefineOption("resilient", ref Resilient, SR.ResilientOption);
                syntax.DefineOption("imagebase", ref ImageBase, SR.ImageBase);

                syntax.DefineOption("targetarch", ref TargetArch, SR.TargetArchOption);
                syntax.DefineOption("targetos", ref TargetOS, SR.TargetOSOption);
                syntax.DefineOption("jitpath", ref JitPath, SR.JitPathOption);

                syntax.DefineOption("print-repro-instructions", ref PrintReproInstructions, SR.PrintReproInstructionsOption);
                syntax.DefineOption("singlemethodtypename", ref SingleMethodTypeName, SR.SingleMethodTypeName);
                syntax.DefineOption("singlemethodname", ref SingleMethodName, SR.SingleMethodMethodName);
                syntax.DefineOption("singlemethodindex", ref SingleMethodIndex, SR.SingleMethodIndex);
                syntax.DefineOptionList("singlemethodgenericarg", ref SingleMethodGenericArg, SR.SingleMethodGenericArgs);

                syntax.DefineOption("parallelism", ref Parallelism, SR.ParalellismOption);
                syntax.DefineOption("custom-pe-section-alignment", ref CustomPESectionAlignment, SR.CustomPESectionAlignmentOption);
                syntax.DefineOption("map", ref Map, SR.MapFileOption);
                syntax.DefineOption("mapcsv", ref MapCsv, SR.MapCsvFileOption);
                syntax.DefineOption("pdb", ref Pdb, SR.PdbFileOption);
                syntax.DefineOption("pdb-path", ref PdbPath, SR.PdbFilePathOption);
                syntax.DefineOption("perfmap", ref PerfMap, SR.PerfMapFileOption);
                syntax.DefineOption("perfmap-path", ref PerfMapPath, SR.PerfMapFilePathOption);
                syntax.DefineOption("perfmap-format-version", ref PerfMapFormatVersion, SR.PerfMapFormatVersionOption);

                syntax.DefineOption("method-layout", ref MethodLayout, SR.MethodLayoutOption);
                syntax.DefineOption("file-layout", ref FileLayout, SR.FileLayoutOption);
                syntax.DefineOption("verify-type-and-field-layout", ref VerifyTypeAndFieldLayout, SR.VerifyTypeAndFieldLayoutOption);
                syntax.DefineOption("callchain-profile", ref CallChainProfileFile, SR.CallChainProfileFile);

                syntax.DefineOption("make-repro-path", ref MakeReproPath, SR.MakeReproPathHelp);

                syntax.DefineOption("h|help", ref Help, SR.HelpOption);

                syntax.DefineParameterList("in", ref InputFilePaths, SR.InputFilesToCompile);
            });

            if (Help)
            {
                List <string> extraHelp = new List <string>();
                extraHelp.Add(SR.OptionPassingHelp);
                extraHelp.Add("");
                extraHelp.Add(SR.DashDashHelp);
                extraHelp.Add("");

                string[]           ValidArchitectures = new string[] { "arm", "armel", "arm64", "x86", "x64" };
                string[]           ValidOS            = new string[] { "windows", "linux", "osx" };
                TargetOS           defaultOs;
                TargetArchitecture defaultArch;
                Program.ComputeDefaultOptions(out defaultOs, out defaultArch);

                extraHelp.Add(String.Format(SR.SwitchWithDefaultHelp, "--targetos", String.Join("', '", ValidOS), defaultOs.ToString().ToLowerInvariant()));

                extraHelp.Add("");

                extraHelp.Add(String.Format(SR.SwitchWithDefaultHelp, "--targetarch", String.Join("', '", ValidArchitectures), defaultArch.ToString().ToLowerInvariant()));

                extraHelp.Add("");

                extraHelp.Add(SR.InstructionSetHelp);
                foreach (string arch in ValidArchitectures)
                {
                    StringBuilder archString = new StringBuilder();

                    archString.Append(arch);
                    archString.Append(": ");

                    TargetArchitecture targetArch = Program.GetTargetArchitectureFromArg(arch, out _);
                    bool first = true;
                    foreach (var instructionSet in Internal.JitInterface.InstructionSetFlags.ArchitectureToValidInstructionSets(targetArch))
                    {
                        // Only instruction sets with are specifiable should be printed to the help text
                        if (instructionSet.Specifiable)
                        {
                            if (first)
                            {
                                first = false;
                            }
                            else
                            {
                                archString.Append(", ");
                            }
                            archString.Append(instructionSet.Name);
                        }
                    }

                    extraHelp.Add(archString.ToString());
                }

                argSyntax.ExtraHelpParagraphs = extraHelp;

                HelpText = argSyntax.GetHelpText();
            }

            if (MakeReproPath != null)
            {
                // Create a repro package in the specified path
                // This package will have the set of input files needed for compilation
                // + the original command line arguments
                // + a rsp file that should work to directly run out of the zip file

                Helpers.MakeReproPackage(MakeReproPath, OutputFilePath, args, argSyntax, new[] { "-r", "-u", "-m", "--inputbubbleref" });
            }
        }
Beispiel #14
0
        void DefineArgumentSyntax(ArgumentSyntax syntax)
        {
            bool activeCommandIsCommandAssociatedWithTraceProcessing = false;

            syntax.ApplicationName = typeof(Program).Assembly.GetName().Name.ToString();

            // HandleHelp writes to error, fails fast with crash dialog and lacks custom formatting.
            syntax.HandleHelp   = false;
            syntax.HandleErrors = false;

            string command = "";

            void CommonOptions()
            {
                string traceFile = null;

                syntax.DefineOption(
                    name: "t|trace",
                    value: ref traceFile,
                    help: "Specify the trace file to be parsed.",
                    requireValue: true);
                if (traceFile != null)
                {
                    TraceFile = new FileInfo(traceFile);
                }

                OutputOption();

                int pidLocal = 0;

                if (syntax.DefineOption(
                        name: "pid",
                        value: ref pidLocal,
                        help: "The pid within the trace of the process to examine. If this is a multi-process trace, at least one of --pid or --process-name must be specified",
                        requireValue: true).IsSpecified)
                {
                    Pid = pidLocal;
                }

                syntax.DefineOption(
                    name: "process-name",
                    value: ref ProcessName,
                    help: "The process name within the trace of the process to examine. If this is a multi-process trace, at least one of --pid or --process-name must be specified.",
                    requireValue: false);

                int clrInstanceIdLocal = 0;

                if (syntax.DefineOption(
                        name: "clr-instance-id",
                        value: ref clrInstanceIdLocal,
                        help: "If the process contains multiple .NET runtimes, the instance ID must be specified.",
                        requireValue: true).IsSpecified)
                {
                    ClrInstanceId = clrInstanceIdLocal;
                }

                Reference = DefineFileOptionList(name: "r|reference", help: "If a reference is not located on disk at the same location as used in the process, it may be specified with a --reference parameter. Multiple --reference parameters may be specified. The wild cards * and ? are supported by this option.");

                ExcludeEventsBefore = Double.MinValue;
                syntax.DefineOption(
                    name: "exclude-events-before",
                    value: ref ExcludeEventsBefore,
                    help: "Exclude data from events before specified time. Time is specified as milliseconds from the start of the trace.",
                    valueConverter: Convert.ToDouble,
                    requireValue: true);

                ExcludeEventsAfter = Double.MaxValue;
                syntax.DefineOption(
                    name: "exclude-events-after",
                    value: ref ExcludeEventsAfter,
                    help: "Exclude data from events after specified time. Time is specified as milliseconds from the start of the trace.",
                    valueConverter: Convert.ToDouble,
                    requireValue: true);

                VerbosityOption();
            }

            void OutputOption()
            {
                string outputFile = null;

                syntax.DefineOption(
                    name: "o|output",
                    value: ref outputFile,
                    help: "Specify the output filename to be created.",
                    requireValue: true);
                if (outputFile != null)
                {
                    OutputFileName = new FileInfo(outputFile);
                }
            }

            void VerbosityOption()
            {
                Verbosity verbosity = Verbosity.normal;

                syntax.DefineOption(name: "v|verbosity", value: ref verbosity, help: "Adjust verbosity level. Supported levels are minimal, normal, detailed, and diagnostic.", valueConverter: VerbosityConverter, requireValue: true);
                BasicProgressMessages = (int)verbosity >= (int)Verbosity.normal;
                Warnings                 = (int)verbosity >= (int)Verbosity.normal;
                VerboseWarnings          = (int)verbosity >= (int)Verbosity.detailed;
                DetailedProgressMessages = (int)verbosity >= (int)Verbosity.detailed;
                DisplayProcessedEvents   = (int)verbosity >= (int)Verbosity.diagnostic;
            }

            void CompressedOption()
            {
                bool compressed = false;

                syntax.DefineOption(name: "compressed", value: ref compressed, help: "Generate compressed mibc", requireValue: false);
                Uncompressed = !compressed;
            }

            void HelpOption()
            {
                syntax.DefineOption("h|help", ref Help, "Display this usage message.");
            }

            var mibcCommand = syntax.DefineCommand(name: "create-mibc", value: ref command, help: "Transform a trace file into a Mibc profile data file.");

            if (mibcCommand.IsActive)
            {
                activeCommandIsCommandAssociatedWithTraceProcessing = true;
                HelpArgs          = new string[] { "create-mibc", "--help", "--trace", "trace", "--output", "output" };
                FileType          = PgoFileType.mibc;
                GenerateCallGraph = true;
                ProcessJitEvents  = true;
                ProcessR2REvents  = true;
#if DEBUG
                ValidateOutputFile = true;
#else
                ValidateOutputFile = false;
#endif
                CommonOptions();
                CompressedOption();

                string preciseDebugInfoFile = null;
                syntax.DefineOption(name: "precise-debug-info-file", ref preciseDebugInfoFile, "Name of file of newline separated JSON objects containing precise debug info");
                if (preciseDebugInfoFile != null)
                {
                    PreciseDebugInfoFile = new FileInfo(preciseDebugInfoFile);
                }

                syntax.DefineOption(name: "spgo", value: ref Spgo, help: "Base profile on samples in the input. Uses last branch records if available and otherwise raw IP samples.", requireValue: false);
                syntax.DefineOption(name: "spgo-min-samples", value: ref SpgoMinSamples, help: $"The minimum number of total samples a function must have before generating profile data for it with SPGO. Default: {SpgoMinSamples}", requireValue: false);

                syntax.DefineOption(name: "include-full-graphs", value: ref IncludeFullGraphs, help: "Include all blocks and edges in the written .mibc file, regardless of profile counts", requireValue: false);

                HelpOption();
            }

            JitTraceOptions = JitTraceOptions.none;
#if DEBUG
            // Usage of the jittrace format requires using logic embedded in the runtime repository and isn't suitable for general consumer use at this time
            // Build it in debug and check builds to ensure that it doesn't bitrot, and remains available for use by developers willing to build the repo
            var jittraceCommand = syntax.DefineCommand(name: "create-jittrace", value: ref command, help: "Transform a trace file into a jittrace runtime file.");
            if (jittraceCommand.IsActive)
            {
                activeCommandIsCommandAssociatedWithTraceProcessing = true;
                HelpArgs           = new string[] { "create-jittrace", "--help", "--trace", "trace", "--output", "output" };
                FileType           = PgoFileType.jittrace;
                ProcessJitEvents   = true;
                ProcessR2REvents   = false;
                ValidateOutputFile = false;
                CommonOptions();

                bool sorted = false;
                syntax.DefineOption(name: "sorted", value: ref sorted, help: "Generate sorted output.", requireValue: false);
                if (sorted)
                {
                    JitTraceOptions |= JitTraceOptions.sorted;
                }

                bool showtimestamp = false;
                syntax.DefineOption(name: "showtimestamp", value: ref showtimestamp, help: "Show timestamps in output.", requireValue: false);
                if (showtimestamp)
                {
                    JitTraceOptions |= JitTraceOptions.showtimestamp;
                }

                syntax.DefineOption(name: "includeReadyToRun", value: ref ProcessR2REvents, help: "Include ReadyToRun methods in the trace file.", requireValue: false);
                HelpOption();
            }
#endif

            var mergeCommand = syntax.DefineCommand(name: "merge", value: ref command, help: "Merge multiple Mibc profile data files into one file.");
            if (mergeCommand.IsActive)
            {
                HelpArgs = new string[] { "merge", "--help", "--output", "output", "--input", "input" };

                InputFilesToMerge = DefineFileOptionList(name: "i|input", help: "Input .mibc files to be merged. Multiple input arguments are specified as --input file1.mibc --input file2.mibc");
                OutputOption();

                IReadOnlyList <string> assemblyNamesAsStrings = null;
                syntax.DefineOptionList(name: "include-reference", value: ref assemblyNamesAsStrings, help: "If specified, include in Mibc file only references to the specified assemblies. Assemblies are specified as assembly names, not filenames. For instance, `System.Private.CoreLib` not `System.Private.CoreLib.dll`. Multiple --include-reference options may be specified.", requireValue: true);
                if (assemblyNamesAsStrings != null)
                {
                    foreach (string asmName in assemblyNamesAsStrings)
                    {
                        try
                        {
                            IncludedAssemblies.Add(new AssemblyName(asmName));
                        }
                        catch
                        {
                            throw new FormatException($"Unable to parse '{asmName}' as an Assembly Name.");
                        }
                    }
                }

                syntax.DefineOption(name: "inherit-timestamp", value: ref InheritTimestamp, help: "If specified, set the output's timestamp to the max timestamp of the input files");

                VerbosityOption();
                CompressedOption();
                HelpOption();
#if DEBUG
                ValidateOutputFile = true;
#else
                ValidateOutputFile = false;
#endif
            }

            var dumpCommand = syntax.DefineCommand(name: "dump", value: ref command, help: "Dump the contents of a Mibc file.");
            if (dumpCommand.IsActive)
            {
                DumpMibc = true;
                HelpArgs = new string[] { "dump", "--help", "input", "output" };

                VerbosityOption();
                HelpOption();

                string inputFileToDump = null;
                syntax.DefineParameter(name: "input", ref inputFileToDump, "Name of the input mibc file to dump.");
                if (inputFileToDump != null)
                {
                    InputFileToDump = new FileInfo(inputFileToDump);
                }

                string outputFile = null;
                syntax.DefineParameter(name: "output", ref outputFile, "Name of the output dump file.");
                if (outputFile != null)
                {
                    OutputFileName = new FileInfo(outputFile);
                }
            }

            var compareMibcCommand = syntax.DefineCommand(name: "compare-mibc", value: ref command, help: "Compare two .mibc files");
            if (compareMibcCommand.IsActive)
            {
                HelpArgs    = new[] { "compare-mibc", "--input", "first.mibc", "--input", "second.mibc" };
                CompareMibc = DefineFileOptionList(name: "i|input", help: "The input .mibc files to be compared. Specify as --input file1.mibc --input file2.mibc");
                if (CompareMibc.Count != 2)
                {
                    Help = true;
                }

                syntax.DefineOption(name: "dump-worst-overlap-graphs", value: ref DumpWorstOverlapGraphs, help: "Number of graphs to dump to .dot format in dump-worst-overlap-graphs-to directory");
                string dumpWorstOverlapGraphsTo = null;
                syntax.DefineOption(name: "dump-worst-overlap-graphs-to", value: ref dumpWorstOverlapGraphsTo, help: "Number of graphs to dump to .dot format in dump-worst-overlap-graphs-to directory");
                if (dumpWorstOverlapGraphsTo != null)
                {
                    DumpWorstOverlapGraphsTo = new DirectoryInfo(dumpWorstOverlapGraphsTo);
                }
            }

            if (syntax.ActiveCommand == null)
            {
                // No command specified
                Help = true;
            }

            if (activeCommandIsCommandAssociatedWithTraceProcessing)
            {
                HelpText =
                    @$ "{syntax.GetHelpText()}
Example tracing commands used to generate the input to this tool:
" "dotnet-trace collect -p 73060 --providers Microsoft-Windows-DotNETRuntime:0x1E000080018:4" "
 - Capture events from process 73060 where we capture both JIT and R2R events using EventPipe tracing

" "dotnet-trace collect -p 73060 --providers Microsoft-Windows-DotNETRuntime:0x1C000080018:4" "
 - Capture events from process 73060 where we capture only JIT events using EventPipe tracing

" "perfview collect -LogFile:logOfCollection.txt -DataFile:jittrace.etl -Zip:false -merge:false -providers:Microsoft-Windows-DotNETRuntime:0x1E000080018:4" "
 - Capture Jit and R2R events via perfview of all processes running using ETW tracing
";
            }
            else
            {
                HelpText = syntax.GetHelpText();
            }

            List <FileInfo> DefineFileOptionList(string name, string help)
            {
                IReadOnlyList <string> filesAsStrings = null;

                syntax.DefineOptionList(name: name, value: ref filesAsStrings, help: help, requireValue: true);
                List <FileInfo> referenceList = new List <FileInfo>();

                if (filesAsStrings != null)
                {
                    foreach (string pattern in filesAsStrings)
                    {
                        Dictionary <string, string> paths = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);
                        Helpers.AppendExpandedPaths(paths, pattern, false);
                        foreach (string file in paths.Values)
                        {
                            referenceList.Add(new FileInfo(file));
                        }
                    }
                }
                return(referenceList);
            }
        }
Beispiel #15
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 (_options.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
            //

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

            CompilationModuleGroup compilationGroup;

            if (singleMethod != null)
            {
                compilationGroup = new SingleMethodCompilationModuleGroup(typeSystemContext, singleMethod);
            }
            else if (_multiFile)
            {
                compilationGroup = new MultiFileCompilationModuleGroup(typeSystemContext);
            }
            else
            {
                compilationGroup = new SingleFileCompilationModuleGroup(typeSystemContext);
            }

            //
            // Compile
            //

            Compilation compilation = new Compilation(_options, typeSystemContext, compilationGroup);

            compilation.Log = _options.Verbose ? Console.Out : TextWriter.Null;
            compilation.Compile();

            return(0);
        }
        public CommandLineOptions(string[] args)
        {
            InputFilePaths         = Array.Empty <string>();
            UnrootedInputFilePaths = Array.Empty <string>();
            ReferenceFilePaths     = Array.Empty <string>();
            MibcFilePaths          = Array.Empty <string>();
            CodegenOptions         = Array.Empty <string>();

            Parallelism            = Environment.ProcessorCount;
            SingleMethodGenericArg = null;

            ArgumentSyntax argSyntax = ArgumentSyntax.Parse(args, syntax =>
            {
                syntax.ApplicationName = typeof(Program).Assembly.GetName().Name.ToString();

                // HandleHelp writes to error, fails fast with crash dialog and lacks custom formatting.
                syntax.HandleHelp   = false;
                syntax.HandleErrors = true;

                syntax.DefineOptionList("u|unrooted-input-file-paths", ref UnrootedInputFilePaths, SR.UnrootedInputFilesToCompile);
                syntax.DefineOptionList("r|reference", ref ReferenceFilePaths, SR.ReferenceFiles);
                syntax.DefineOption("instruction-set", ref InstructionSet, SR.InstructionSets);
                syntax.DefineOptionList("m|mibc", ref MibcFilePaths, SR.MibcFiles);
                syntax.DefineOption("o|out|outputfilepath", ref OutputFilePath, SR.OutputFilePath);
                syntax.DefineOption("crp|compositerootpath", ref CompositeRootPath, SR.CompositeRootPath);
                syntax.DefineOption("O|optimize", ref Optimize, SR.EnableOptimizationsOption);
                syntax.DefineOption("Os|optimize-space", ref OptimizeSpace, SR.OptimizeSpaceOption);
                syntax.DefineOption("Ot|optimize-time", ref OptimizeTime, SR.OptimizeSpeedOption);
                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("tuning", ref Tuning, SR.TuningImageOption);
                syntax.DefineOption("partial", ref Partial, SR.PartialImageOption);
                syntax.DefineOption("compilebubblegenerics", ref CompileBubbleGenerics, SR.BubbleGenericsOption);
                syntax.DefineOption("dgmllog|dgml-log-file-name", ref DgmlLogFileName, SR.SaveDependencyLogOption);
                syntax.DefineOption("fulllog|generate-full-dmgl-log", ref GenerateFullDgmlLog, SR.SaveDetailedLogOption);
                syntax.DefineOption("verbose", ref Verbose, SR.VerboseLoggingOption);
                syntax.DefineOption("systemmodule", ref SystemModule, SR.SystemModuleOverrideOption);
                syntax.DefineOption("waitfordebugger", ref WaitForDebugger, SR.WaitForDebuggerOption);
                syntax.DefineOptionList("codegenopt|codegen-options", ref CodegenOptions, SR.CodeGenOptions);
                syntax.DefineOption("resilient", ref Resilient, SR.ResilientOption);

                syntax.DefineOption("targetarch", ref TargetArch, SR.TargetArchOption);
                syntax.DefineOption("targetos", ref TargetOS, SR.TargetOSOption);
                syntax.DefineOption("jitpath", ref JitPath, SR.JitPathOption);

                syntax.DefineOption("singlemethodtypename", ref SingleMethodTypeName, SR.SingleMethodTypeName);
                syntax.DefineOption("singlemethodname", ref SingleMethodName, SR.SingleMethodMethodName);
                syntax.DefineOptionList("singlemethodgenericarg", ref SingleMethodGenericArg, SR.SingleMethodGenericArgs);

                syntax.DefineOption("parallelism", ref Parallelism, SR.ParalellismOption);
                syntax.DefineOption("custom-pe-section-alignment", ref CustomPESectionAlignment, SR.CustomPESectionAlignmentOption);
                syntax.DefineOption("map", ref Map, SR.MapFileOption);
                syntax.DefineOption("mapcsv", ref MapCsv, SR.MapCsvFileOption);

                syntax.DefineOption("method-layout", ref MethodLayout, SR.MethodLayoutOption);
                syntax.DefineOption("file-layout", ref FileLayout, SR.FileLayoutOption);
                syntax.DefineOption("verify-type-and-field-layout", ref VerifyTypeAndFieldLayout, SR.VerifyTypeAndFieldLayoutOption);

                syntax.DefineOption("h|help", ref Help, SR.HelpOption);

                syntax.DefineParameterList("in", ref InputFilePaths, SR.InputFilesToCompile);
            });

            if (Help)
            {
                HelpText = argSyntax.GetHelpText();
            }
        }
Beispiel #17
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)
                {
                    compilationRoots.Add(new MainMethodRootProvider(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);
                    }

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

                    // System.Private.Reflection.Execution needs to establish a communication channel with System.Private.CoreLib
                    // at process startup. This is done through an eager constructor that calls into CoreLib and passes it
                    // a callback object.
                    //
                    // Since CoreLib cannot reference anything, the type and it's eager constructor won't be added to the compilation
                    // unless we explictly add it.

                    var refExec = typeSystemContext.GetModuleForSimpleName("System.Private.Reflection.Execution", false);
                    if (refExec != null)
                    {
                        var exec = refExec.GetType("Internal.Reflection.Execution", "ReflectionExecution");
                        compilationRoots.Add(new SingleMethodRootProvider(exec.GetStaticConstructor()));
                    }

                    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)
                                       .ToCompilation();

            compilation.Compile(_outputFilePath);

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

            return(0);
        }
Beispiel #18
0
        private static ICommand ParseCommandLine2(string[] args)
        {
            var command = Commands.Unknown;

            var nologo                                = false;
            var outputFolder                          = String.Empty;
            var outputFile                            = String.Empty;
            var sourceFile                            = String.Empty;
            var verbose                               = false;
            IReadOnlyList <string> files              = Array.Empty <string>();
            IReadOnlyList <string> defines            = Array.Empty <string>();
            IReadOnlyList <string> includePaths       = Array.Empty <string>();
            IReadOnlyList <int>    suppressedWarnings = Array.Empty <int>();
            IReadOnlyList <string> locFiles           = Array.Empty <string>();

            ArgumentSyntax parsed = null;

            try
            {
                parsed = ArgumentSyntax.Parse(args, syntax =>
                {
                    syntax.HandleErrors = false;
                    //syntax.HandleHelp = false;
                    syntax.ErrorOnUnexpectedArguments = false;

                    syntax.DefineCommand("build", ref command, Commands.Build, "Build to final output");
                    syntax.DefineOptionList("d|D|define", ref defines, "Preprocessor name value pairs");
                    syntax.DefineOptionList("I|includePath", ref includePaths, "Include search paths");
                    syntax.DefineOption("nologo", ref nologo, false, "Do not display logo");
                    syntax.DefineOption("o|out", ref outputFile, "Output file");
                    syntax.DefineOptionList("sw", ref suppressedWarnings, false, "Do not display logo");
                    syntax.DefineOption("v|verbose", ref verbose, false, "Display verbose messages");
                    syntax.DefineOptionList("l|loc", ref locFiles, "Localization files to load (.wxl)");
                    syntax.DefineParameterList("files", ref files, "Source files to compile (.wxs)");

                    syntax.DefineCommand("preprocess", ref command, Commands.Preprocess, "Preprocess a source files");
                    syntax.DefineOptionList("d|D|define", ref defines, "Preprocessor name value pairs");
                    syntax.DefineOptionList("I|includePath", ref includePaths, "Include search paths");
                    syntax.DefineOption("nologo", ref nologo, false, "Do not display logo");
                    syntax.DefineOption("o|out", ref outputFile, "Output file");
                    syntax.DefineParameter("file", ref sourceFile, "File to process");

                    syntax.DefineCommand("compile", ref command, Commands.Compile, "Compile source files");
                    syntax.DefineOptionList("I|includePath", ref includePaths, "Include search paths");
                    syntax.DefineOption("nologo", ref nologo, false, "Do not display logo");
                    syntax.DefineOption("o|out", ref outputFolder, "Output folder");
                    syntax.DefineOptionList("sw", ref suppressedWarnings, false, "Do not display logo");
                    syntax.DefineOption("v|verbose", ref verbose, false, "Display verbose messages");
                    syntax.DefineParameterList("files", ref files, "Source files to compile (.wxs)");

                    syntax.DefineCommand("link", ref command, Commands.Link, "Link intermediate files");
                    syntax.DefineOption("nologo", ref nologo, "Do not display logo");
                    syntax.DefineOption("o|out", ref outputFile, "Output intermediate file (.wir)");
                    syntax.DefineParameterList("files", ref files, "Intermediate files to link (.wir)");

                    syntax.DefineCommand("bind", ref command, Commands.Bind, "Bind to final output");
                    syntax.DefineOption("nologo", ref nologo, false, "Do not display logo");
                    syntax.DefineOption("o|out", ref outputFile, "Output file");
                    syntax.DefineParameterList("files", ref files, "Intermediate files to bind (.wir)");

                    syntax.DefineCommand("version", ref command, Commands.Version, "Display version information");
                });

                if (IsHelpRequested(parsed))
                {
                    var width = Console.WindowWidth - 2;
                    var text  = parsed.GetHelpText(width < 20 ? 72 : width);
                    Console.Error.WriteLine(text);

                    return(null);
                }

                //var u = result.GetArguments();

                //var p = result.GetActiveParameters();

                //var o = result.GetActiveOptions();

                //var a = result.GetActiveArguments();

                //var h = result.GetHelpText();

                //foreach (var x in p)
                //{
                //    Console.WriteLine("{0}", x.Name);
                //}

                switch (command)
                {
                case Commands.Build:
                {
                    var sourceFiles = GatherSourceFiles(files, outputFolder);
                    var variables   = GatherPreprocessorVariables(defines);
                    return(new BuildCommand(sourceFiles, variables, locFiles, outputFile));
                }

                case Commands.Compile:
                {
                    var sourceFiles = GatherSourceFiles(files, outputFolder);
                    var variables   = GatherPreprocessorVariables(defines);
                    return(new CompileCommand(sourceFiles, variables));
                }

                case Commands.Version:
                    return(new VersionCommand());
                }

                //var preprocessorVariables = this.GatherPreprocessorVariables();

                //foreach (var sourceFile in sourceFiles)
                //{
                //    var document = preprocessor.Process(sourceFile.SourcePath, preprocessorVariables);

                //    var intermediate = compiler.Compile(document);

                //    intermediate.Save(sourceFile.OutputPath);
                //}
            }
            //catch (ArgumentSyntaxException e)
            //{
            //    if (IsHelpRequested(parsed))
            //    {
            //        var width = Console.WindowWidth - 2;
            //        var text = parsed.GetHelpText(width < 20 ? 72 : width);
            //        Console.Error.WriteLine(text);
            //    }
            //    else
            //    {
            //        Console.Error.WriteLine(e.Message);
            //    }
            //}

            return(null);
        }
Beispiel #19
0
        private int Run(string[] args)
        {
            ArgumentSyntax syntax = ParseCommandLine(args);

            // open output stream
            if (_outputFilename != null)
            {
                _writer = File.CreateText(_outputFilename);
            }
            else
            {
                _writer = Console.Out;
            }

            if (_help)
            {
                _writer.WriteLine(syntax.GetHelpText());
                return(0);
            }

            Disassembler disassembler = null;

            try
            {
                if (_inputFilenames.Count == 0)
                {
                    throw new ArgumentException("Input filename must be specified (--in <file>)");
                }

                if (_diff && _inputFilenames.Count < 2)
                {
                    throw new ArgumentException("Need at least 2 input files in diff mode");
                }

                R2RReader previousReader = null;

                foreach (string filename in _inputFilenames)
                {
                    // parse the ReadyToRun image
                    R2RReader r2r = new R2RReader(filename);

                    if (_disasm)
                    {
                        if (r2r.InputArchitectureSupported() && r2r.DisassemblerArchitectureSupported())
                        {
                            disassembler = new Disassembler(r2r.Image, r2r.Machine);
                        }
                        else
                        {
                            throw new ArgumentException($"The architecture of input file {filename} ({r2r.Machine.ToString()}) or the architecture of the disassembler tools ({System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture.ToString()}) is not supported.");
                        }
                    }

                    if (_xml)
                    {
                        _dumper = new XmlDumper(_ignoreSensitive, r2r, _writer, _raw, _header, _disasm, disassembler, _unwind, _gc, _sectionContents);
                    }
                    else
                    {
                        _dumper = new TextDumper(r2r, _writer, _raw, _header, _disasm, disassembler, _unwind, _gc, _sectionContents);
                    }

                    if (!_diff)
                    {
                        // output the ReadyToRun info
                        Dump(r2r);
                    }
                    else if (previousReader != null)
                    {
                        new R2RDiff(previousReader, r2r, _writer).Run();
                    }

                    previousReader = r2r;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Error: " + e.ToString());
                if (e is ArgumentException)
                {
                    Console.WriteLine();
                    Console.WriteLine(syntax.GetHelpText());
                }
                if (_xml)
                {
                    XmlDocument document = new XmlDocument();
                    XmlNode     node     = document.CreateNode("element", "Error", "");
                    node.InnerText = e.Message;
                    document.AppendChild(node);
                    if (_writer != null)
                    {
                        document.Save(_writer);
                    }
                }
                return(1);
            }
            finally
            {
                if (disassembler != null)
                {
                    disassembler.Dispose();
                }
                // close output stream
                _writer.Close();
            }

            return(0);
        }
Beispiel #20
0
        private int Run(string[] args)
        {
            ArgumentSyntax syntax = ParseCommandLine(args);

            // open output stream
            if (_outputFilename != null)
            {
                _writer = File.CreateText(_outputFilename);
            }
            else
            {
                _writer = Console.Out;
            }

            if (_help)
            {
                _writer.WriteLine(syntax.GetHelpText());
                return(0);
            }

            try
            {
                if (_inputFilenames.Count == 0)
                {
                    throw new ArgumentException("Input filename must be specified (--in <file>)");
                }

                foreach (string filename in _inputFilenames)
                {
                    R2RReader r2r = new R2RReader(filename);

                    if (_disasm)
                    {
                        _disassembler = CoreDisTools.GetDisasm(r2r.Machine);
                    }

                    if (_xml)
                    {
                        _dumper = new XmlDumper(_ignoreSensitive, r2r, _writer, _raw, _header, _disasm, _disassembler, _unwind, _gc, _sectionContents);
                    }
                    else
                    {
                        _dumper = new TextDumper(r2r, _writer, _raw, _header, _disasm, _disassembler, _unwind, _gc, _sectionContents);
                    }

                    Dump(r2r);

                    if (_disasm)
                    {
                        CoreDisTools.FinishDisasm(_disassembler);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Error: " + e.ToString());
                if (e is ArgumentException)
                {
                    Console.WriteLine();
                    Console.WriteLine(syntax.GetHelpText());
                }
                if (_xml)
                {
                    XmlDocument document = new XmlDocument();
                    XmlNode     node     = document.CreateNode("element", "Error", "");
                    node.InnerText = e.Message;
                    document.AppendChild(node);
                    if (_writer != null)
                    {
                        document.Save(_writer);
                    }
                }
                return(1);
            }
            finally
            {
                // close output stream
                _writer.Close();
            }

            return(0);
        }
Beispiel #21
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);
        }
Beispiel #22
0
        void DefineArgumentSyntax(ArgumentSyntax syntax)
        {
            bool activeCommandIsCommandAssociatedWithTraceProcessing = false;

            syntax.ApplicationName = typeof(Program).Assembly.GetName().Name.ToString();

            // HandleHelp writes to error, fails fast with crash dialog and lacks custom formatting.
            syntax.HandleHelp   = false;
            syntax.HandleErrors = false;

            string command = "";

            void CommonOptions()
            {
                string traceFile = null;

                FailIfUnspecified(syntax.DefineOption(
                                      name: "t|trace",
                                      value: ref traceFile,
                                      help: "Specify the trace file to be parsed.",
                                      requireValue: true));
                if (traceFile != null)
                {
                    TraceFile = new FileInfo(traceFile);
                }

                string outputFile = null;

                FailIfUnspecified(syntax.DefineOption(
                                      name: "o|output",
                                      value: ref outputFile,
                                      help: "Specify the output filename to be created.",
                                      requireValue: true));
                if (outputFile != null)
                {
                    OutputFileName = new FileInfo(outputFile);
                }

                int pidLocal = 0;

                if (syntax.DefineOption(
                        name: "pid",
                        value: ref pidLocal,
                        help: "The pid within the trace of the process to examine. If this is a multi-process trace, at least one of --pid or --process-name must be specified",
                        requireValue: true).IsSpecified)
                {
                    Pid = pidLocal;
                }

                syntax.DefineOption(
                    name: "process-name",
                    value: ref ProcessName,
                    help: "The process name within the trace of the process to examine. If this is a multi-process trace, at least one of --pid or --process-name must be specified.",
                    requireValue: false);

                int clrInstanceIdLocal = 0;

                if (syntax.DefineOption(
                        name: "clr-instance-id",
                        value: ref clrInstanceIdLocal,
                        help: "If the process contains multiple .NET runtimes, the instance ID must be specified.",
                        requireValue: true).IsSpecified)
                {
                    ClrInstanceId = clrInstanceIdLocal;
                }

                IReadOnlyList <string> referencesAsStrings = null;

                syntax.DefineOptionList(name: "r|reference", value: ref referencesAsStrings, help: "If a reference is not located on disk at the same location as used in the process, it may be specified with a --reference parameter. Multiple --reference parameters may be specified. The wild cards * and ? are supported by this option.", requireValue: true);
                List <FileInfo> referenceList = new List <FileInfo>();

                Reference = referenceList;
                if (referencesAsStrings != null)
                {
                    foreach (string pattern in referencesAsStrings)
                    {
                        Dictionary <string, string> paths = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);
                        Helpers.AppendExpandedPaths(paths, pattern, false);
                        foreach (string file in paths.Values)
                        {
                            referenceList.Add(new FileInfo(file));
                        }
                    }
                }

                syntax.DefineOption(
                    name: "exclude-events-before",
                    value: ref ExcludeEventsBefore,
                    help: "Exclude data from events before specified time. Time is specified as milliseconds from the start of the trace.",
                    valueConverter: Convert.ToDouble,
                    requireValue: true);

                syntax.DefineOption(
                    name: "exclude-events-after",
                    value: ref ExcludeEventsAfter,
                    help: "Exclude data from events after specified time. Time is specified as milliseconds from the start of the trace.",
                    valueConverter: Convert.ToDouble,
                    requireValue: true);

                Verbosity verbosity = default(Verbosity);

                syntax.DefineOption(name: "v|verbosity", value: ref verbosity, help: "Adjust verbosity level. Supported levels are minimal, normal, detailed, and diagnostic.", valueConverter: VerbosityConverter, requireValue: true);
                BasicProgressMessages = (int)verbosity >= (int)Verbosity.normal;
                Warnings               = (int)verbosity >= (int)Verbosity.normal;
                VerboseWarnings        = (int)verbosity >= (int)Verbosity.detailed;
                DisplayProcessedEvents = (int)verbosity >= (int)Verbosity.diagnostic;
            }

            void HelpOption()
            {
                syntax.DefineOption("h|help", ref Help, "Display this usage message.");
            }

            var mibcCommand = syntax.DefineCommand(name: "create-mibc", value: ref command, help: "Transform a trace file into a Mibc profile data file.");

            if (mibcCommand.IsActive)
            {
                activeCommandIsCommandAssociatedWithTraceProcessing = true;
                HelpArgs          = new string[] { "create-mibc", "--help", "--trace", "trace", "--output", "output" };
                FileType          = PgoFileType.mibc;
                GenerateCallGraph = true;
                ProcessJitEvents  = true;
                ProcessR2REvents  = true;
#if Debug
                ValidateOutputFile = true;
#else
                ValidateOutputFile = false;
#endif
                CommonOptions();
                bool compressed = false;
                syntax.DefineOption(name: "compressed", value: ref compressed, help: "Generate compressed mibc", requireValue: false);
                Uncompressed = !compressed;

                HelpOption();
            }

            JitTraceOptions = jittraceoptions.none;
#if DEBUG
            // Usage of the jittrace format requires using logic embedded in the runtime repository and isn't suitable for general consumer use at this time
            // Build it in debug and check builds to ensure that it doesn't bitrot, and remains available for use by developers willing to build the repo
            var jittraceCommand = syntax.DefineCommand(name: "create-jittrace", value: ref command, help: "Transform a trace file into a jittrace runtime file.");
            if (jittraceCommand.IsActive)
            {
                activeCommandIsCommandAssociatedWithTraceProcessing = true;
                HelpArgs           = new string[] { "create-jittrace", "--help", "--trace", "trace", "--output", "output" };
                FileType           = PgoFileType.jittrace;
                ProcessJitEvents   = true;
                ProcessR2REvents   = false;
                ValidateOutputFile = false;
                CommonOptions();

                bool sorted = false;
                syntax.DefineOption(name: "sorted", value: ref sorted, help: "Generate sorted output.", requireValue: false);
                if (sorted)
                {
                    JitTraceOptions |= jittraceoptions.sorted;
                }

                bool showtimestamp = false;
                syntax.DefineOption(name: "showtimestamp", value: ref showtimestamp, help: "Show timestamps in output.", requireValue: false);
                if (showtimestamp)
                {
                    JitTraceOptions |= jittraceoptions.showtimestamp;
                }

                syntax.DefineOption(name: "includeReadyToRun", value: ref ProcessR2REvents, help: "Include ReadyToRun methods in the trace file.", requireValue: false);
                HelpOption();
            }
#endif

            if (syntax.ActiveCommand == null)
            {
                // No command specified
                Help = true;
            }

            if (activeCommandIsCommandAssociatedWithTraceProcessing)
            {
                HelpText =
                    @$ "{syntax.GetHelpText()}
Example tracing commands used to generate the input to this tool:
" "dotnet-trace collect -p 73060 --providers Microsoft-Windows-DotNETRuntime:0x1E000080018:4" "
 - Capture events from process 73060 where we capture both JIT and R2R events using EventPipe tracing

" "dotnet-trace collect -p 73060 --providers Microsoft-Windows-DotNETRuntime:0x1C000080018:4" "
 - Capture events from process 73060 where we capture only JIT events using EventPipe tracing

" "perfview collect -LogFile:logOfCollection.txt -DataFile:jittrace.etl -Zip:false -merge:false -providers:Microsoft-Windows-DotNETRuntime:0x1E000080018:4" "
 - Capture Jit and R2R events via perfview of all processes running using ETW tracing
";
            }
            else
            {
                HelpText = syntax.GetHelpText();
            }
        }
Beispiel #23
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
            //

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

            CompilationModuleGroup compilationGroup;

            if (singleMethod != null)
            {
                compilationGroup = new SingleMethodCompilationModuleGroup(typeSystemContext, singleMethod);
            }
            else if (_multiFile)
            {
                compilationGroup = new MultiFileCompilationModuleGroup(typeSystemContext);
            }
            else
            {
                compilationGroup = new SingleFileCompilationModuleGroup(typeSystemContext);
            }

            //
            // 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)
                                       .ToCompilation();

            compilation.Compile(_outputFilePath);

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

            return(0);
        }
Beispiel #24
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
                {
                    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");
                }
            }

            using (PerfEventSource.StartStopEvents.CompilationEvents())
            {
                ICompilation compilation;
                using (PerfEventSource.StartStopEvents.LoadingEvents())
                {
                    //
                    // Initialize type system context
                    //

                    SharedGenericsMode genericsMode = SharedGenericsMode.CanonicalReferenceTypes;

                    var targetDetails = new TargetDetails(_targetArchitecture, _targetOS, TargetAbi.CoreRT, SimdVectorLength.None);
                    CompilerTypeSystemContext typeSystemContext = new ReadyToRunCompilerContext(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);

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

                    List <ModuleDesc> referenceableModules = new List <ModuleDesc>();
                    foreach (var inputFile in inputFilePaths)
                    {
                        try
                        {
                            referenceableModules.Add(typeSystemContext.GetModuleFromPath(inputFile.Value));
                        }
                        catch { } // Ignore non-managed pe files
                    }

                    foreach (var referenceFile in _referenceFilePaths.Values)
                    {
                        try
                        {
                            referenceableModules.Add(typeSystemContext.GetModuleFromPath(referenceFile));
                        }
                        catch { } // Ignore non-managed pe files
                    }

                    ProfileDataManager profileDataManager = new ProfileDataManager(logger, referenceableModules);

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

                        List <EcmaModule> inputModules = new List <EcmaModule>();

                        foreach (var inputFile in typeSystemContext.InputFilePaths)
                        {
                            EcmaModule module = typeSystemContext.GetModuleFromPath(inputFile.Value);
                            compilationRoots.Add(new ReadyToRunRootProvider(module, profileDataManager));
                            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, _includeGenericsFromVersionBubble,
                            _partial ? profileDataManager : null);
                    }

                    //
                    // Compile
                    //

                    string inputFilePath = "";
                    foreach (var input in typeSystemContext.InputFilePaths)
                    {
                        inputFilePath = input.Value;
                        break;
                    }
                    CompilationBuilder builder = new ReadyToRunCodegenCompilationBuilder(typeSystemContext, compilationGroup, inputFilePath,
                                                                                         ibcTuning: _tuning,
                                                                                         resilient: _resilient);

                    string compilationUnitPrefix = "";
                    builder.UseCompilationUnitPrefix(compilationUnitPrefix);

                    ILProvider ilProvider = new ReadyToRunILProvider();


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

                    builder
                    .UseILProvider(ilProvider)
                    .UseBackendOptions(_codegenOptions)
                    .UseLogger(logger)
                    .UseDependencyTracking(trackingLevel)
                    .UseCompilationRoots(compilationRoots)
                    .UseOptimizationMode(_optimizationMode);

                    compilation = builder.ToCompilation();
                }
                compilation.Compile(_outputFilePath);
            }

            return(0);
        }
Beispiel #25
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 #26
0
        public static ICommandLineOptions ParseCommandLineOptions(string[] args)
        {
            bool overwriteOutput        = false;
            IReadOnlyList <string> file = Array.Empty <string>();
            string outFile                                = DefaultName;
            string description                            = string.Empty;
            IReadOnlyList <string> target                 = Array.Empty <string>();
            IReadOnlyList <string> result                 = Array.Empty <string>();
            bool showNonPortableApis                      = true;
            bool showBreakingChanges                      = false;
            bool showRetargettingIssues                   = false;
            bool noDefaultIgnoreFile                      = false;
            IReadOnlyList <string> ignoreAssemblyFile     = Array.Empty <string>();
            IReadOnlyList <string> suppressBreakingChange = Array.Empty <string>();
            string     targetMap                          = string.Empty;
            string     endpoint                           = "https://portability.dot.net";
            AppCommand command                            = default;

            ArgumentSyntax argSyntax = default;

            try
            {
                ArgumentSyntax.Parse(args, syntax =>
                {
                    syntax.HandleErrors = false;

                    syntax.DefineCommand("analyze", ref command, AppCommand.AnalyzeAssemblies, LocalizedStrings.CmdAnalyzeMessage);
                    syntax.DefineOptionList("f|file", ref file, LocalizedStrings.CmdAnalyzeFileInput);
                    syntax.DefineOption("o|out", ref outFile, LocalizedStrings.CmdAnalyzeOutputFileName);
                    syntax.DefineOption("d|description", ref description, LocalizedStrings.CmdAnalyzeDescription);
                    syntax.DefineOption("e|endpoint", ref endpoint, LocalizedStrings.CmdEndpoint);
                    syntax.DefineOptionList("t|target", ref target, LocalizedStrings.CmdAnalyzeTarget);
                    syntax.DefineOptionList("r|resultFormat", ref result, LocalizedStrings.CmdAnalyzeResultFormat);
                    syntax.DefineOption("p|showNonPortableApis", ref showNonPortableApis, LocalizedStrings.CmdAnalyzeShowNonPortableApis);
                    syntax.DefineOption("b|showBreakingChanges", ref showBreakingChanges, LocalizedStrings.CmdAnalyzeShowBreakingChanges);
                    syntax.DefineOption("u|showRetargettingIssues", ref showRetargettingIssues, LocalizedStrings.CmdAnalyzeShowRetargettingIssues);
                    syntax.DefineOption("force", ref overwriteOutput, LocalizedStrings.OverwriteFile);
                    syntax.DefineOption("noDefaultIgnoreFile", ref noDefaultIgnoreFile, LocalizedStrings.CmdAnalyzeNoDefaultIgnoreFile);
                    syntax.DefineOptionList("i|ignoreAssemblyFile", ref ignoreAssemblyFile, LocalizedStrings.CmdAnalyzeIgnoreAssembliesFile);
                    syntax.DefineOptionList("s|suppressBreakingChange", ref suppressBreakingChange, LocalizedStrings.CmdAnalyzeSuppressBreakingChange);
                    syntax.DefineOption("targetMap", ref targetMap, LocalizedStrings.CmdAnalyzeTargetMap);

#if !FEATURE_OFFLINE
                    syntax.DefineCommand("dump", ref command, AppCommand.DumpAnalysis, LocalizedStrings.CmdDumpAnalysis);
                    syntax.DefineOptionList("f|file", ref file, LocalizedStrings.CmdAnalyzeFileInput);
                    syntax.DefineOption("o|out", ref outFile, LocalizedStrings.CmdAnalyzeOutputFileName);
#endif

                    syntax.DefineCommand("listTargets", ref command, AppCommand.ListTargets, LocalizedStrings.ListTargets);
                    syntax.DefineOption("e|endpoint", ref endpoint, LocalizedStrings.CmdEndpoint);

                    syntax.DefineCommand("listOutputFormats", ref command, AppCommand.ListOutputFormats, LocalizedStrings.ListOutputFormats);
                    syntax.DefineOption("e|endpoint", ref endpoint, LocalizedStrings.CmdEndpoint);

                    syntax.DefineCommand("docId", ref command, AppCommand.DocIdSearch, LocalizedStrings.CmdDocId);
                    syntax.DefineOption("e|endpoint", ref endpoint, LocalizedStrings.CmdEndpoint);

                    argSyntax = syntax;
                });
            }
            catch (ArgumentSyntaxException e)
            {
                Console.WriteLine();

                Console.WriteLine(e.Message);

                if (argSyntax != null)
                {
                    Console.WriteLine(argSyntax.GetHelpText());
                }

                return(new ConsoleApiPortOptions(AppCommand.Exit));
            }

            // Set OverwriteOutputFile to true if the output file name is explicitly specified
            if (!string.Equals(DefaultName, outFile, StringComparison.Ordinal))
            {
                overwriteOutput = true;
            }

            var(inputFiles, invalidFiles) = ProcessInputAssemblies(file);

            return(new ConsoleApiPortOptions(command)
            {
                BreakingChangeSuppressions = suppressBreakingChange,
                Description = description,
                IgnoredAssemblyFiles = ignoreAssemblyFile,
                InputAssemblies = inputFiles,
                InvalidInputFiles = invalidFiles,
                OutputFileName = outFile,
                OutputFormats = result,
                OverwriteOutputFile = overwriteOutput,
                RequestFlags = GetRequestFlags(showBreakingChanges, showRetargettingIssues, showNonPortableApis),
                ServiceEndpoint = endpoint,
                TargetMapFile = targetMap,
                Targets = target,
            });
        }
Beispiel #27
0
        private int Run(string[] args)
        {
            ArgumentSyntax syntax = ParseCommandLine(args);

            // open output stream
            if (_outputFilename != null)
            {
                _writer = File.CreateText(_outputFilename);
            }
            else
            {
                _writer = Console.Out;
            }

            if (_help)
            {
                _writer.WriteLine(syntax.GetHelpText());
                return(0);
            }

            Disassembler disassembler = null;

            try
            {
                if (_inputFilenames.Count == 0)
                {
                    throw new ArgumentException("Input filename must be specified (--in <file>)");
                }

                if (_diff && _inputFilenames.Count < 2)
                {
                    throw new ArgumentException("Need at least 2 input files in diff mode");
                }

                R2RReader previousReader = null;

                foreach (string filename in _inputFilenames)
                {
                    // parse the ReadyToRun image
                    R2RReader r2r = new R2RReader(filename);

                    if (_disasm)
                    {
                        // TODO: Fix R2RDump issue where an x64 R2R image cannot be dissassembled with the x86 CoreDisTools
                        // For the short term, we want to error out with a decent message explaining the unexpected error
                        // Issue #19564: https://github.com/dotnet/coreclr/issues/19564
                        if (r2r.InputArchitectureMatchesDisassemblerArchitecture())
                        {
                            disassembler = new Disassembler(r2r.Image, r2r.Machine);
                        }
                        else
                        {
                            throw new ArgumentException($"The architecture of input file {filename} is {r2r.Machine.ToString()} and does not match the architecture of the disassembler tools {System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture.ToString()}");
                        }
                    }

                    if (_xml)
                    {
                        _dumper = new XmlDumper(_ignoreSensitive, r2r, _writer, _raw, _header, _disasm, disassembler, _unwind, _gc, _sectionContents);
                    }
                    else
                    {
                        _dumper = new TextDumper(r2r, _writer, _raw, _header, _disasm, disassembler, _unwind, _gc, _sectionContents);
                    }

                    if (!_diff)
                    {
                        // output the ReadyToRun info
                        Dump(r2r);
                    }
                    else if (previousReader != null)
                    {
                        new R2RDiff(previousReader, r2r, _writer).Run();
                    }

                    previousReader = r2r;
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Error: " + e.ToString());
                if (e is ArgumentException)
                {
                    Console.WriteLine();
                    Console.WriteLine(syntax.GetHelpText());
                }
                if (_xml)
                {
                    XmlDocument document = new XmlDocument();
                    XmlNode     node     = document.CreateNode("element", "Error", "");
                    node.InnerText = e.Message;
                    document.AppendChild(node);
                    if (_writer != null)
                    {
                        document.Save(_writer);
                    }
                }
                return(1);
            }
            finally
            {
                if (disassembler != null)
                {
                    disassembler.Dispose();
                }
                // close output stream
                _writer.Close();
            }

            return(0);
        }