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); }
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()); } }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); } } } } }
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); }
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" }); } }
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); } }
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(); } }
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); }
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); }
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); }
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); }
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); }
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(); } }
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); }
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); }
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); }
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, }); }
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); }