public TargetRegisterMap(TargetOS os) { switch (os) { case TargetOS.Windows: Arg0 = Register.RCX; Arg1 = Register.RDX; Arg2 = Register.R8; Arg3 = Register.R9; Result = Register.RAX; break; case TargetOS.Linux: case TargetOS.OSX: case TargetOS.FreeBSD: Arg0 = Register.RDI; Arg1 = Register.RSI; Arg2 = Register.RDX; Arg3 = Register.RCX; Result = Register.RAX; break; default: throw new NotImplementedException(); } }
private void InitializeDefaultOptions() { _options = new CompilationOptions(); #if FXCORE // We could offer this as a command line option, but then we also need to // load a different RyuJIT, so this is a future nice to have... if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) _targetOS = TargetOS.Windows; else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) _targetOS = TargetOS.Linux; else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) _targetOS = TargetOS.OSX; else throw new NotImplementedException(); switch (RuntimeInformation.ProcessArchitecture) { case Architecture.X86: _targetArchitecture = TargetArchitecture.X86; break; case Architecture.X64: _targetArchitecture = TargetArchitecture.X64; break; case Architecture.Arm: _targetArchitecture = TargetArchitecture.ARM; break; case Architecture.Arm64: _targetArchitecture = TargetArchitecture.ARM64; break; default: throw new NotImplementedException(); } #else _targetOS = TargetOS.Windows; _targetArchitecture = TargetArchitecture.X64; #endif }
public Script(string Name, string Content, TargetPlatform platform = TargetPlatform.UNKNOWN, TargetOS os = TargetOS.UNKNOWN, TargetArch arch = TargetArch.UNKNOWN) { scriptName = Name; scriptBody = Content; this.platform = platform; this.os = os; this.arch = arch; }
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 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; } // // 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)); } } else if (_nativeLib) { EcmaModule module = (EcmaModule)typeSystemContext.SystemModule; LibraryInitializers libraryInitializers = new LibraryInitializers(typeSystemContext, _isCppCodegen); compilationRoots.Add(new NativeLibraryInitializerRootProvider(module, 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 && !_nativeLib) { 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); } 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); } // 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; 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); var stackTracePolicy = _emitStackTraceData ? (StackTraceEmissionPolicy) new EcmaMethodStackTraceEmissionPolicy() : new NoStackTraceEmissionPolicy(); CompilerGeneratedMetadataManager metadataManager = new CompilerGeneratedMetadataManager( compilationGroup, typeSystemContext, _metadataLogFileName, stackTracePolicy); 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()); // 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 (_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 void Write(string perfMapFileName, int perfMapFormatVersion, IEnumerable <MethodInfo> methods, IEnumerable <AssemblyInfo> inputAssemblies, TargetOS targetOS, TargetArchitecture targetArch) { if (perfMapFormatVersion > CurrentFormatVersion) { throw new NotSupportedException(perfMapFormatVersion.ToString()); } using (TextWriter writer = new StreamWriter(perfMapFileName)) { IEnumerable <AssemblyInfo> orderedInputs = inputAssemblies.OrderBy(asm => asm.Name, StringComparer.OrdinalIgnoreCase); PerfMapWriter perfMapWriter = new PerfMapWriter(writer); List <byte> inputHash = new List <byte>(); foreach (AssemblyInfo inputAssembly in orderedInputs) { inputHash.AddRange(inputAssembly.Mvid.ToByteArray()); } inputHash.Add((byte)targetOS); inputHash.Add((byte)targetArch); Guid outputGuid = new Guid(MD5.HashData(inputHash.ToArray())); perfMapWriter.WriteLine(outputGuid.ToString(), (uint)PseudoRVA.OutputGuid, 0); perfMapWriter.WriteLine(targetOS.ToString(), (uint)PseudoRVA.TargetOS, 0); perfMapWriter.WriteLine(targetArch.ToString(), (uint)PseudoRVA.TargetArchitecture, 0); perfMapWriter.WriteLine(CurrentFormatVersion.ToString(), (uint)PseudoRVA.FormatVersion, 0); foreach (MethodInfo methodInfo in methods) { if (methodInfo.HotRVA != 0 && methodInfo.HotLength != 0) { perfMapWriter.WriteLine(methodInfo.Name, methodInfo.HotRVA, methodInfo.HotLength); } if (methodInfo.ColdRVA != 0 && methodInfo.ColdLength != 0) { perfMapWriter.WriteLine(methodInfo.Name, methodInfo.ColdRVA, methodInfo.ColdLength); } } } }
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"); } // TODO: read instruction sets from the command line 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. As the jit generates logic that depends on these features it will call // notifyInstructionSetUsage, which will result in generation of a fixup to verify the behavior of // code. // optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("ssse3"); optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("aes"); optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("pclmul"); optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("lzcnt"); } 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)); } 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 == "SerializationGuard") { removedFeatures |= RemovedFeature.SerializationGuard; } } 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; 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(); 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"); 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(); } return(0); }
private int Run() { InitializeDefaultOptions(); ProcessCommandLine(); if (_commandLineOptions.OutputFilePath == null) { throw new CommandLineException("Output filename must be specified (/out <file>)"); } // // Set target Architecture and OS // if (_commandLineOptions.TargetArch != null) { if (_commandLineOptions.TargetArch.Equals("x86", StringComparison.OrdinalIgnoreCase)) { _targetArchitecture = TargetArchitecture.X86; } else if (_commandLineOptions.TargetArch.Equals("x64", StringComparison.OrdinalIgnoreCase)) { _targetArchitecture = TargetArchitecture.X64; } else if (_commandLineOptions.TargetArch.Equals("arm", StringComparison.OrdinalIgnoreCase)) { _targetArchitecture = TargetArchitecture.ARM; } else if (_commandLineOptions.TargetArch.Equals("armel", StringComparison.OrdinalIgnoreCase)) { _targetArchitecture = TargetArchitecture.ARM; } else if (_commandLineOptions.TargetArch.Equals("arm64", StringComparison.OrdinalIgnoreCase)) { _targetArchitecture = TargetArchitecture.ARM64; } else { throw new CommandLineException("Target architecture is not supported"); } } if (_commandLineOptions.TargetOS != null) { if (_commandLineOptions.TargetOS.Equals("windows", StringComparison.OrdinalIgnoreCase)) { _targetOS = TargetOS.Windows; } else if (_commandLineOptions.TargetOS.Equals("linux", StringComparison.OrdinalIgnoreCase)) { _targetOS = TargetOS.Linux; } else if (_commandLineOptions.TargetOS.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; string systemModuleName = _commandLineOptions.SystemModule ?? DefaultSystemModule; 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, _commandLineOptions.Verbose); 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 (!_commandLineOptions.InputBubble) { break; } } List <ModuleDesc> versionBubbleModules = new List <ModuleDesc>(); if (_commandLineOptions.InputBubble) { // 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, _commandLineOptions.CompileBubbleGenerics, _commandLineOptions.Partial ? profileDataManager : null); } // // Compile // string inputFilePath = ""; foreach (var input in typeSystemContext.InputFilePaths) { inputFilePath = input.Value; break; } CompilationBuilder builder = new ReadyToRunCodegenCompilationBuilder(typeSystemContext, compilationGroup, inputFilePath, ibcTuning: _commandLineOptions.Tuning, resilient: _commandLineOptions.Resilient); string compilationUnitPrefix = ""; builder.UseCompilationUnitPrefix(compilationUnitPrefix); ILProvider ilProvider = new ReadyToRunILProvider(); DependencyTrackingLevel trackingLevel = _commandLineOptions.DgmlLogFileName == null ? DependencyTrackingLevel.None : (_commandLineOptions.GenerateFullDgmlLog ? DependencyTrackingLevel.All : DependencyTrackingLevel.First); builder .UseILProvider(ilProvider) .UseJitPath(_commandLineOptions.JitPath) .UseBackendOptions(_commandLineOptions.CodegenOptions) .UseLogger(logger) .UseDependencyTracking(trackingLevel) .UseCompilationRoots(compilationRoots) .UseOptimizationMode(_optimizationMode); compilation = builder.ToCompilation(); } compilation.Compile(_commandLineOptions.OutputFilePath.FullName); if (_commandLineOptions.DgmlLogFileName != null) { compilation.WriteDependencyLog(_commandLineOptions.DgmlLogFileName.FullName); } } return(0); }
public TargetRegisterMap(TargetOS os) { Arg0 = Register.R0; Arg1 = Register.R1; Result = Register.R0; }
public TargetDetails(TargetArchitecture architecture, TargetOS targetOS) { Architecture = architecture; OperatingSystem = targetOS; }
private int Run() { InitializeDefaultOptions(); ProcessCommandLine(); if (_commandLineOptions.OutputFilePath == null) { throw new CommandLineException(SR.MissingOutputFile); } // // Set target Architecture and OS // if (_commandLineOptions.TargetArch != null) { if (_commandLineOptions.TargetArch.Equals("x86", StringComparison.OrdinalIgnoreCase)) { _targetArchitecture = TargetArchitecture.X86; } else if (_commandLineOptions.TargetArch.Equals("x64", StringComparison.OrdinalIgnoreCase)) { _targetArchitecture = TargetArchitecture.X64; } else if (_commandLineOptions.TargetArch.Equals("arm", StringComparison.OrdinalIgnoreCase)) { _targetArchitecture = TargetArchitecture.ARM; } else if (_commandLineOptions.TargetArch.Equals("armel", StringComparison.OrdinalIgnoreCase)) { _targetArchitecture = TargetArchitecture.ARM; } else if (_commandLineOptions.TargetArch.Equals("arm64", StringComparison.OrdinalIgnoreCase)) { _targetArchitecture = TargetArchitecture.ARM64; } else { throw new CommandLineException(SR.TargetArchitectureUnsupported); } } if (_commandLineOptions.TargetOS != null) { if (_commandLineOptions.TargetOS.Equals("windows", StringComparison.OrdinalIgnoreCase)) { _targetOS = TargetOS.Windows; } else if (_commandLineOptions.TargetOS.Equals("linux", StringComparison.OrdinalIgnoreCase)) { _targetOS = TargetOS.Linux; } else if (_commandLineOptions.TargetOS.Equals("osx", StringComparison.OrdinalIgnoreCase)) { _targetOS = TargetOS.OSX; } else { throw new CommandLineException(SR.TargetOSUnsupported); } } InstructionSetSupportBuilder instructionSetSupportBuilder = new InstructionSetSupportBuilder(_targetArchitecture); // Ready to run images are built with certain instruction set baselines 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 (_commandLineOptions.InstructionSet != null) { List <string> instructionSetParams = new List <string>(); // At this time, instruction sets may only be specified with --input-bubble, as // we do not yet have a stable ABI for all vector parameter/return types. if (!_commandLineOptions.InputBubble) { throw new CommandLineException(SR.InstructionSetWithoutInputBubble); } // Normalize instruction set format to include implied +. string[] instructionSetParamsInput = _commandLineOptions.InstructionSet.Split(","); for (int i = 0; i < instructionSetParamsInput.Length; i++) { string instructionSet = instructionSetParamsInput[i]; if (String.IsNullOrEmpty(instructionSet)) { throw new CommandLineException(String.Format(SR.InstructionSetMustNotBe, "")); } 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(String.Format(SR.InstructionSetMustNotBe, instructionSet)); } } else { if (!instructionSetSupportBuilder.RemoveInstructionSetSupport(instructionSet)) { throw new CommandLineException(String.Format(SR.InstructionSetMustNotBe, instructionSet)); } } } } instructionSetSupportBuilder.ComputeInstructionSetFlags(out var supportedInstructionSet, out var unsupportedInstructionSet, (string specifiedInstructionSet, string impliedInstructionSet) => throw new CommandLineException(String.Format(SR.InstructionSetInvalidImplication, specifiedInstructionSet, impliedInstructionSet))); InstructionSetSupportBuilder optimisticInstructionSetSupportBuilder = new InstructionSetSupportBuilder(_targetArchitecture); // Ready to run images are built with certain instruction sets that are optimistically assumed to be present if ((_targetArchitecture == TargetArchitecture.X86) || (_targetArchitecture == TargetArchitecture.X64)) { // For ReadyToRun 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. As the jit generates logic that depends on these features it will call // notifyInstructionSetUsage, which will result in generation of a fixup to verify the behavior of // code. // optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("sse"); optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("sse2"); optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("sse4.1"); optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("sse4.2"); optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("aes"); optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("pclmul"); optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("popcnt"); optimisticInstructionSetSupportBuilder.AddSupportedInstructionSet("lzcnt"); } 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); 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, instructionSetSupport.GetVectorTSimdVector()); 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> allInputFilePaths = new Dictionary <string, string>(); Dictionary <string, string> inputFilePaths = new Dictionary <string, string>(); List <ModuleDesc> referenceableModules = new List <ModuleDesc>(); foreach (var inputFile in _inputFilePaths) { try { var module = typeSystemContext.GetModuleFromPath(inputFile.Value); allInputFilePaths.Add(inputFile.Key, inputFile.Value); inputFilePaths.Add(inputFile.Key, inputFile.Value); referenceableModules.Add(module); } catch (TypeSystemException.BadImageFormatException) { // Keep calm and carry on. } } Dictionary <string, string> unrootedInputFilePaths = new Dictionary <string, string>(); foreach (var unrootedInputFile in _unrootedInputFilePaths) { try { var module = typeSystemContext.GetModuleFromPath(unrootedInputFile.Value); if (!allInputFilePaths.ContainsKey(unrootedInputFile.Key)) { allInputFilePaths.Add(unrootedInputFile.Key, unrootedInputFile.Value); unrootedInputFilePaths.Add(unrootedInputFile.Key, unrootedInputFile.Value); referenceableModules.Add(module); } } catch (TypeSystemException.BadImageFormatException) { // Keep calm and carry on. } } typeSystemContext.InputFilePaths = allInputFilePaths; typeSystemContext.ReferenceFilePaths = _referenceFilePaths; List <EcmaModule> inputModules = new List <EcmaModule>(); List <EcmaModule> rootingModules = new List <EcmaModule>(); HashSet <ModuleDesc> versionBubbleModulesHash = new HashSet <ModuleDesc>(); foreach (var inputFile in inputFilePaths) { EcmaModule module = typeSystemContext.GetModuleFromPath(inputFile.Value); inputModules.Add(module); rootingModules.Add(module); versionBubbleModulesHash.Add(module); if (!_commandLineOptions.CompositeOrInputBubble) { break; } } foreach (var unrootedInputFile in unrootedInputFilePaths) { EcmaModule module = typeSystemContext.GetModuleFromPath(unrootedInputFile.Value); inputModules.Add(module); versionBubbleModulesHash.Add(module); } string systemModuleName = _commandLineOptions.SystemModule ?? DefaultSystemModule; typeSystemContext.SetSystemModule((EcmaModule)typeSystemContext.GetModuleForSimpleName(systemModuleName)); if (typeSystemContext.InputFilePaths.Count == 0) { throw new CommandLineException(SR.NoInputFiles); } // // Initialize compilation group and compilation roots // // Single method mode? MethodDesc singleMethod = CheckAndParseSingleMethodModeArguments(typeSystemContext); var logger = new Logger(Console.Out, _commandLineOptions.Verbose); List <string> mibcFiles = new List <string>(); if (_commandLineOptions.Mibc != null) { foreach (var file in _commandLineOptions.Mibc) { mibcFiles.Add(file.FullName); } } foreach (var referenceFile in _referenceFilePaths.Values) { try { EcmaModule module = typeSystemContext.GetModuleFromPath(referenceFile); if (versionBubbleModulesHash.Contains(module)) { // Ignore reference assemblies that have also been passed as inputs continue; } referenceableModules.Add(module); if (_commandLineOptions.InputBubble) { // In large version bubble mode add reference paths to the compilation group versionBubbleModulesHash.Add(module); } } catch { } // Ignore non-managed pe files } List <ModuleDesc> versionBubbleModules = new List <ModuleDesc>(versionBubbleModulesHash); if (!_commandLineOptions.Composite && inputModules.Count != 1) { throw new Exception(string.Format(SR.ErrorMultipleInputFilesCompositeModeOnly, string.Join("; ", inputModules))); } ReadyToRunCompilationModuleGroupBase compilationGroup; List <ICompilationRootProvider> compilationRoots = new List <ICompilationRootProvider>(); if (singleMethod != null) { // Compiling just a single method compilationGroup = new SingleMethodCompilationModuleGroup( typeSystemContext, _commandLineOptions.Composite, _commandLineOptions.InputBubble, inputModules, versionBubbleModules, _commandLineOptions.CompileBubbleGenerics, singleMethod); compilationRoots.Add(new SingleMethodRootProvider(singleMethod)); } else if (_commandLineOptions.CompileNoMethods) { compilationGroup = new NoMethodsCompilationModuleGroup( typeSystemContext, _commandLineOptions.Composite, _commandLineOptions.InputBubble, inputModules, versionBubbleModules, _commandLineOptions.CompileBubbleGenerics); } else { // Single assembly compilation. compilationGroup = new ReadyToRunSingleAssemblyCompilationModuleGroup( typeSystemContext, _commandLineOptions.Composite, _commandLineOptions.InputBubble, inputModules, versionBubbleModules, _commandLineOptions.CompileBubbleGenerics); } // Examine profile guided information as appropriate ProfileDataManager profileDataManager = new ProfileDataManager(logger, referenceableModules, inputModules, versionBubbleModules, _commandLineOptions.CompileBubbleGenerics ? inputModules[0] : null, mibcFiles, typeSystemContext, compilationGroup); if (_commandLineOptions.Partial) { compilationGroup.ApplyProfilerGuidedCompilationRestriction(profileDataManager); } else { compilationGroup.ApplyProfilerGuidedCompilationRestriction(null); } if ((singleMethod == null) && !_commandLineOptions.CompileNoMethods) { // For normal compilations add compilation roots. foreach (var module in rootingModules) { compilationRoots.Add(new ReadyToRunRootProvider( module, profileDataManager, profileDrivenPartialNGen: _commandLineOptions.Partial)); if (!_commandLineOptions.CompositeOrInputBubble) { break; } } } // // Compile // ReadyToRunCodegenCompilationBuilder builder = new ReadyToRunCodegenCompilationBuilder( typeSystemContext, compilationGroup, allInputFilePaths.Values); string compilationUnitPrefix = ""; builder.UseCompilationUnitPrefix(compilationUnitPrefix); ILProvider ilProvider = new ReadyToRunILProvider(); DependencyTrackingLevel trackingLevel = _commandLineOptions.DgmlLogFileName == null ? DependencyTrackingLevel.None : (_commandLineOptions.GenerateFullDgmlLog ? DependencyTrackingLevel.All : DependencyTrackingLevel.First); builder .UseIbcTuning(_commandLineOptions.Tuning) .UseResilience(_commandLineOptions.Resilient) .UseMapFile(_commandLineOptions.Map) .UseParallelism(_commandLineOptions.Parallelism) .UseJitPath(_commandLineOptions.JitPath) .UseInstructionSetSupport(instructionSetSupport) .GenerateOutputFile(_commandLineOptions.OutputFilePath.FullName) .UseILProvider(ilProvider) .UseBackendOptions(_commandLineOptions.CodegenOptions) .UseLogger(logger) .UseDependencyTracking(trackingLevel) .UseCompilationRoots(compilationRoots) .UseOptimizationMode(_optimizationMode); compilation = builder.ToCompilation(); } compilation.Compile(_commandLineOptions.OutputFilePath.FullName); if (_commandLineOptions.DgmlLogFileName != null) { compilation.WriteDependencyLog(_commandLineOptions.DgmlLogFileName.FullName); } } return(0); }
private int Run() { InitializeDefaultOptions(); ProcessCommandLine(); if (_commandLineOptions.OutputFilePath == null) { throw new CommandLineException(SR.MissingOutputFile); } // // Set target Architecture and OS // if (_commandLineOptions.TargetArch != null) { if (_commandLineOptions.TargetArch.Equals("x86", StringComparison.OrdinalIgnoreCase)) { _targetArchitecture = TargetArchitecture.X86; } else if (_commandLineOptions.TargetArch.Equals("x64", StringComparison.OrdinalIgnoreCase)) { _targetArchitecture = TargetArchitecture.X64; } else if (_commandLineOptions.TargetArch.Equals("arm", StringComparison.OrdinalIgnoreCase)) { _targetArchitecture = TargetArchitecture.ARM; } else if (_commandLineOptions.TargetArch.Equals("armel", StringComparison.OrdinalIgnoreCase)) { _targetArchitecture = TargetArchitecture.ARM; } else if (_commandLineOptions.TargetArch.Equals("arm64", StringComparison.OrdinalIgnoreCase)) { _targetArchitecture = TargetArchitecture.ARM64; } else { throw new CommandLineException(SR.TargetArchitectureUnsupported); } } if (_commandLineOptions.TargetOS != null) { if (_commandLineOptions.TargetOS.Equals("windows", StringComparison.OrdinalIgnoreCase)) { _targetOS = TargetOS.Windows; } else if (_commandLineOptions.TargetOS.Equals("linux", StringComparison.OrdinalIgnoreCase)) { _targetOS = TargetOS.Linux; } else if (_commandLineOptions.TargetOS.Equals("osx", StringComparison.OrdinalIgnoreCase)) { _targetOS = TargetOS.OSX; } else { throw new CommandLineException(SR.TargetOSUnsupported); } } 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>(); List <ModuleDesc> referenceableModules = new List <ModuleDesc>(); foreach (var inputFile in _inputFilePaths) { try { var module = typeSystemContext.GetModuleFromPath(inputFile.Value); inputFilePaths.Add(inputFile.Key, inputFile.Value); referenceableModules.Add(module); } catch (TypeSystemException.BadImageFormatException) { // Keep calm and carry on. } } typeSystemContext.InputFilePaths = inputFilePaths; typeSystemContext.ReferenceFilePaths = _referenceFilePaths; List <EcmaModule> inputModules = new List <EcmaModule>(); HashSet <ModuleDesc> versionBubbleModulesHash = new HashSet <ModuleDesc>(); foreach (var inputFile in typeSystemContext.InputFilePaths) { EcmaModule module = typeSystemContext.GetModuleFromPath(inputFile.Value); inputModules.Add(module); versionBubbleModulesHash.Add(module); if (!_commandLineOptions.InputBubble) { break; } } string systemModuleName = _commandLineOptions.SystemModule ?? DefaultSystemModule; typeSystemContext.SetSystemModule(typeSystemContext.GetModuleForSimpleName(systemModuleName)); if (typeSystemContext.InputFilePaths.Count == 0) { throw new CommandLineException(SR.NoInputFiles); } // // Initialize compilation group and compilation roots // // Single method mode? MethodDesc singleMethod = CheckAndParseSingleMethodModeArguments(typeSystemContext); var logger = new Logger(Console.Out, _commandLineOptions.Verbose); List <string> mibcFiles = new List <string>(); if (_commandLineOptions.Mibc != null) { foreach (var file in _commandLineOptions.Mibc) { mibcFiles.Add(file.FullName); } } foreach (var referenceFile in _referenceFilePaths.Values) { try { EcmaModule module = typeSystemContext.GetModuleFromPath(referenceFile); referenceableModules.Add(module); if (_commandLineOptions.InputBubble) { // In large version bubble mode add reference paths to the compilation group versionBubbleModulesHash.Add(module); } } catch { } // Ignore non-managed pe files } List <ModuleDesc> versionBubbleModules = new List <ModuleDesc>(versionBubbleModulesHash); ReadyToRunCompilationModuleGroupBase compilationGroup; List <ICompilationRootProvider> compilationRoots = new List <ICompilationRootProvider>(); if (singleMethod != null) { // Compiling just a single method compilationGroup = new SingleMethodCompilationModuleGroup(typeSystemContext, inputModules, versionBubbleModules, _commandLineOptions.CompileBubbleGenerics, singleMethod); compilationRoots.Add(new SingleMethodRootProvider(singleMethod)); } else { // Single assembly compilation. compilationGroup = new ReadyToRunSingleAssemblyCompilationModuleGroup( typeSystemContext, inputModules, versionBubbleModules, _commandLineOptions.CompileBubbleGenerics); } // Examine profile guided information as appropriate ProfileDataManager profileDataManager = new ProfileDataManager(logger, referenceableModules, inputModules, versionBubbleModules, _commandLineOptions.CompileBubbleGenerics ? inputModules[0] : null, mibcFiles, typeSystemContext, compilationGroup); if (_commandLineOptions.Partial) { compilationGroup.ApplyProfilerGuidedCompilationRestriction(profileDataManager); } else { compilationGroup.ApplyProfilerGuidedCompilationRestriction(null); } if (singleMethod == null) { // For non-single-method compilations add compilation roots. foreach (var module in inputModules) { compilationRoots.Add(new ReadyToRunRootProvider(module, profileDataManager, _commandLineOptions.Partial)); if (!_commandLineOptions.InputBubble) { break; } } } // // Compile // string inputFilePath = ""; foreach (var input in typeSystemContext.InputFilePaths) { inputFilePath = input.Value; break; } ReadyToRunCodegenCompilationBuilder builder = new ReadyToRunCodegenCompilationBuilder(typeSystemContext, compilationGroup, inputFilePath); string compilationUnitPrefix = ""; builder.UseCompilationUnitPrefix(compilationUnitPrefix); ILProvider ilProvider = new ReadyToRunILProvider(); DependencyTrackingLevel trackingLevel = _commandLineOptions.DgmlLogFileName == null ? DependencyTrackingLevel.None : (_commandLineOptions.GenerateFullDgmlLog ? DependencyTrackingLevel.All : DependencyTrackingLevel.First); builder .UseIbcTuning(_commandLineOptions.Tuning) .UseResilience(_commandLineOptions.Resilient) .UseMapFile(_commandLineOptions.Map) .UseParallelism(_commandLineOptions.Parallelism) .UseJitPath(_commandLineOptions.JitPath) .UseILProvider(ilProvider) .UseBackendOptions(_commandLineOptions.CodegenOptions) .UseLogger(logger) .UseDependencyTracking(trackingLevel) .UseCompilationRoots(compilationRoots) .UseOptimizationMode(_optimizationMode); compilation = builder.ToCompilation(); } compilation.Compile(_commandLineOptions.OutputFilePath.FullName); if (_commandLineOptions.DgmlLogFileName != null) { compilation.WriteDependencyLog(_commandLineOptions.DgmlLogFileName.FullName); } } 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; // // Initialize type system context // SharedGenericsMode genericsMode = _useSharedGenerics || !_isWasmCodegen ? SharedGenericsMode.CanonicalReferenceTypes : SharedGenericsMode.Disabled; // TODO: compiler switch for SIMD support? var simdVectorLength = (_isCppCodegen || _isWasmCodegen) ? SimdVectorLength.None : SimdVectorLength.Vector128Bit; var targetAbi = _isCppCodegen ? TargetAbi.CppCodegen : TargetAbi.CoreRT; var targetDetails = new TargetDetails(_targetArchitecture, _targetOS, targetAbi, simdVectorLength); CompilerTypeSystemContext typeSystemContext = (_isReadyToRunCodeGen ? new ReadyToRunCompilerContext(targetDetails, genericsMode) : new CompilerTypeSystemContext(targetDetails, genericsMode)); // // TODO: To support our pre-compiled test tree, allow input files that aren't managed assemblies since // some tests contain a mixture of both managed and native binaries. // // See: https://github.com/dotnet/corert/issues/2785 // // When we undo this this hack, replace this foreach with // typeSystemContext.InputFilePaths = _inputFilePaths; // Dictionary<string, string> inputFilePaths = new Dictionary<string, string>(); foreach (var inputFile in _inputFilePaths) { try { var module = typeSystemContext.GetModuleFromPath(inputFile.Value); inputFilePaths.Add(inputFile.Key, inputFile.Value); } catch (TypeSystemException.BadImageFormatException) { // Keep calm and carry on. } } typeSystemContext.InputFilePaths = inputFilePaths; typeSystemContext.ReferenceFilePaths = _referenceFilePaths; typeSystemContext.SetSystemModule(typeSystemContext.GetModuleForSimpleName(_systemModuleName)); if (typeSystemContext.InputFilePaths.Count == 0) throw new CommandLineException("No input files specified"); // // Initialize compilation group and compilation roots // // Single method mode? MethodDesc singleMethod = CheckAndParseSingleMethodModeArguments(typeSystemContext); CompilationModuleGroup compilationGroup; List<ICompilationRootProvider> compilationRoots = new List<ICompilationRootProvider>(); if (singleMethod != null) { // Compiling just a single method compilationGroup = new SingleMethodCompilationModuleGroup(singleMethod); compilationRoots.Add(new SingleMethodRootProvider(singleMethod)); } else { // Either single file, or multifile library, or multifile consumption. EcmaModule entrypointModule = null; bool systemModuleIsInputModule = false; foreach (var inputFile in typeSystemContext.InputFilePaths) { EcmaModule module = typeSystemContext.GetModuleFromPath(inputFile.Value); if (module.PEReader.PEHeaders.IsExe) { if (entrypointModule != null) throw new Exception("Multiple EXE modules"); entrypointModule = module; } if (module == typeSystemContext.SystemModule) systemModuleIsInputModule = true; if (!_isReadyToRunCodeGen) compilationRoots.Add(new ExportedMethodsRootProvider(module)); } if (entrypointModule != null && !_isReadyToRunCodeGen) { compilationRoots.Add(new MainMethodRootProvider(entrypointModule, CreateInitializerList(typeSystemContext))); compilationRoots.Add(new RuntimeConfigurationRootProvider(_runtimeOptions)); } if (_isReadyToRunCodeGen) { List<EcmaModule> inputModules = new List<EcmaModule>(); foreach (var inputFile in typeSystemContext.InputFilePaths) { EcmaModule module = typeSystemContext.GetModuleFromPath(inputFile.Value); compilationRoots.Add(new ReadyToRunRootProvider(module)); inputModules.Add(module); if (!_isInputVersionBubble) { break; } } List<ModuleDesc> versionBubbleModules = new List<ModuleDesc>(); if (_isInputVersionBubble) { // In large version bubble mode add reference paths to the compilation group foreach (string referenceFile in _referenceFilePaths.Values) { try { // Currently SimpleTest.targets has no easy way to filter out non-managed assemblies // from the reference list. EcmaModule module = typeSystemContext.GetModuleFromPath(referenceFile); versionBubbleModules.Add(module); } catch (TypeSystemException.BadImageFormatException ex) { Console.WriteLine("Warning: cannot open reference assembly '{0}': {1}", referenceFile, ex.Message); } } } compilationGroup = new ReadyToRunSingleAssemblyCompilationModuleGroup( typeSystemContext, inputModules, versionBubbleModules); } else if (_multiFile) { List<EcmaModule> inputModules = new List<EcmaModule>(); foreach (var inputFile in typeSystemContext.InputFilePaths) { EcmaModule module = typeSystemContext.GetModuleFromPath(inputFile.Value); if (entrypointModule == null) { // This is a multifile production build - we need to root all methods compilationRoots.Add(new LibraryRootProvider(module)); } inputModules.Add(module); } compilationGroup = new MultiFileSharedCompilationModuleGroup(typeSystemContext, inputModules); } else { if (entrypointModule == null && !_nativeLib) throw new Exception("No entrypoint module"); if (!systemModuleIsInputModule) compilationRoots.Add(new ExportedMethodsRootProvider((EcmaModule)typeSystemContext.SystemModule)); compilationGroup = new SingleFileCompilationModuleGroup(); if (_rootAllApplicationAssemblies) compilationRoots.Add(new ApplicationAssemblyRootProvider(typeSystemContext)); } if (_nativeLib) { // Set owning module of generated native library startup method to compiler generated module, // to ensure the startup method is included in the object file during multimodule mode build compilationRoots.Add(new NativeLibraryInitializerRootProvider(typeSystemContext.GeneratedAssembly, CreateInitializerList(typeSystemContext))); compilationRoots.Add(new RuntimeConfigurationRootProvider(_runtimeOptions)); } if (_rdXmlFilePaths.Count > 0) Console.WriteLine("Warning: RD.XML processing will change before release (https://github.com/dotnet/corert/issues/5001)"); foreach (var rdXmlFilePath in _rdXmlFilePaths) { compilationRoots.Add(new RdXmlRootProvider(typeSystemContext, rdXmlFilePath)); } } // // Compile // CompilationBuilder builder; if (_isWasmCodegen) builder = new WebAssemblyCodegenCompilationBuilder(typeSystemContext, compilationGroup); else if (_isReadyToRunCodeGen) { string inputFilePath = ""; foreach (var input in typeSystemContext.InputFilePaths) { inputFilePath = input.Value; break; } builder = new ReadyToRunCodegenCompilationBuilder(typeSystemContext, compilationGroup, inputFilePath); } else if (_isCppCodegen) builder = new CppCodegenCompilationBuilder(typeSystemContext, compilationGroup); else builder = new RyuJitCompilationBuilder(typeSystemContext, compilationGroup); string compilationUnitPrefix = _multiFile ? System.IO.Path.GetFileNameWithoutExtension(_outputFilePath) : ""; builder.UseCompilationUnitPrefix(compilationUnitPrefix); if (!_isCppCodegen && !_isWasmCodegen) builder.UsePInvokePolicy(new ConfigurablePInvokePolicy(typeSystemContext.Target)); RemovedFeature removedFeatures = 0; foreach (string feature in _removedFeatures) { if (feature == "EventSource") removedFeatures |= RemovedFeature.Etw; else if (feature == "FrameworkStrings") removedFeatures |= RemovedFeature.FrameworkResources; else if (feature == "Globalization") removedFeatures |= RemovedFeature.Globalization; else if (feature == "Comparers") removedFeatures |= RemovedFeature.Comparers; else if (feature == "CurlHandler") removedFeatures |= RemovedFeature.CurlHandler; } ILProvider ilProvider = _isReadyToRunCodeGen ? (ILProvider)new ReadyToRunILProvider() : new CoreRTILProvider(); if (removedFeatures != 0) ilProvider = new RemovingILProvider(ilProvider, removedFeatures); var stackTracePolicy = _emitStackTraceData ? (StackTraceEmissionPolicy)new EcmaMethodStackTraceEmissionPolicy() : new NoStackTraceEmissionPolicy(); MetadataBlockingPolicy mdBlockingPolicy = _noMetadataBlocking ? (MetadataBlockingPolicy)new NoMetadataBlockingPolicy() : new BlockedInternalsBlockingPolicy(typeSystemContext); ManifestResourceBlockingPolicy resBlockingPolicy = (removedFeatures & RemovedFeature.FrameworkResources) != 0 ? new FrameworkStringResourceBlockingPolicy() : (ManifestResourceBlockingPolicy)new NoManifestResourceBlockingPolicy(); UsageBasedMetadataGenerationOptions metadataGenerationOptions = UsageBasedMetadataGenerationOptions.AnonymousTypeHeuristic; if (_completeTypesMetadata) metadataGenerationOptions |= UsageBasedMetadataGenerationOptions.CompleteTypesOnly; if (_scanReflection) metadataGenerationOptions |= UsageBasedMetadataGenerationOptions.ILScanning; DynamicInvokeThunkGenerationPolicy invokeThunkGenerationPolicy = new DefaultDynamicInvokeThunkGenerationPolicy(); bool supportsReflection = !_disableReflection && !_isReadyToRunCodeGen && _systemModuleName == DefaultSystemModule; MetadataManager metadataManager; if (_isReadyToRunCodeGen) { metadataManager = new ReadyToRunTableManager(typeSystemContext); } else if (supportsReflection) { metadataManager = new UsageBasedMetadataManager( compilationGroup, typeSystemContext, mdBlockingPolicy, resBlockingPolicy, _metadataLogFileName, stackTracePolicy, invokeThunkGenerationPolicy, ilProvider, metadataGenerationOptions); } else { metadataManager = new EmptyMetadataManager(typeSystemContext); } // Unless explicitly opted in at the command line, we enable scanner for retail builds by default. // We don't do this for CppCodegen and Wasm, because those codegens are behind. // We also don't do this for multifile because scanner doesn't simulate inlining (this would be // fixable by using a CompilationGroup for the scanner that has a bigger worldview, but // let's cross that bridge when we get there). bool useScanner = _useScanner || (_optimizationMode != OptimizationMode.None && !_isCppCodegen && !_isWasmCodegen && !_isReadyToRunCodeGen && !_multiFile); useScanner &= !_noScanner; builder.UseILProvider(ilProvider); ILScanResults scanResults = null; if (useScanner) { ILScannerBuilder scannerBuilder = builder.GetILScannerBuilder() .UseCompilationRoots(compilationRoots) .UseMetadataManager(metadataManager); if (_scanDgmlLogFileName != null) scannerBuilder.UseDependencyTracking(_generateFullScanDgmlLog ? DependencyTrackingLevel.All : DependencyTrackingLevel.First); IILScanner scanner = scannerBuilder.ToILScanner(); scanResults = scanner.Scan(); if (metadataManager is UsageBasedMetadataManager usageBasedManager) metadataManager = usageBasedManager.ToAnalysisBasedMetadataManager(); } var logger = new Logger(Console.Out, _isVerbose); DebugInformationProvider debugInfoProvider = _enableDebugInfo ? (_ilDump == null ? new DebugInformationProvider() : new ILAssemblyGeneratingMethodDebugInfoProvider(_ilDump, new EcmaOnlyDebugInformationProvider())) : new NullDebugInformationProvider(); DependencyTrackingLevel trackingLevel = _dgmlLogFileName == null ? DependencyTrackingLevel.None : (_generateFullDgmlLog ? DependencyTrackingLevel.All : DependencyTrackingLevel.First); compilationRoots.Add(metadataManager); builder .UseBackendOptions(_codegenOptions) .UseMethodBodyFolding(_methodBodyFolding) .UseMetadataManager(metadataManager) .UseLogger(logger) .UseDependencyTracking(trackingLevel) .UseCompilationRoots(compilationRoots) .UseOptimizationMode(_optimizationMode) .UseDebugInfoProvider(debugInfoProvider); if (scanResults != null) { // If we have a scanner, feed the vtable analysis results to the compilation. // This could be a command line switch if we really wanted to. builder.UseVTableSliceProvider(scanResults.GetVTableLayoutInfo()); // If we have a scanner, feed the generic dictionary results to the compilation. // This could be a command line switch if we really wanted to. builder.UseGenericDictionaryLayoutProvider(scanResults.GetDictionaryLayoutInfo()); // If we feed any outputs of the scanner into the compilation, it's essential // we use scanner's devirtualization manager. It prevents optimizing codegens // from accidentally devirtualizing cases that can never happen at runtime // (e.g. devirtualizing a method on a type that never gets allocated). builder.UseDevirtualizationManager(scanResults.GetDevirtualizationManager()); } ICompilation compilation = builder.ToCompilation(); ObjectDumper dumper = _mapFileName != null ? new ObjectDumper(_mapFileName) : null; CompilationResults compilationResults = compilation.Compile(_outputFilePath, dumper); if (_exportsFile != null) { ExportsFileWriter defFileWriter = new ExportsFileWriter(typeSystemContext, _exportsFile); foreach (var compilationRoot in compilationRoots) { if (compilationRoot is ExportedMethodsRootProvider provider) defFileWriter.AddExportedMethods(provider.ExportedMethods); } defFileWriter.EmitExportedMethods(); } if (_dgmlLogFileName != null) compilationResults.WriteDependencyLog(_dgmlLogFileName); if (scanResults != null) { SimdHelper simdHelper = new SimdHelper(); if (_scanDgmlLogFileName != null) scanResults.WriteDependencyLog(_scanDgmlLogFileName); // If the scanner and compiler don't agree on what to compile, the outputs of the scanner might not actually be usable. // We are going to check this two ways: // 1. The methods and types generated during compilation are a subset of method and types scanned // 2. The methods and types scanned are a subset of methods and types compiled (this has a chance to hold for unoptimized builds only). // Check that methods and types generated during compilation are a subset of method and types scanned bool scanningFail = false; DiffCompilationResults(ref scanningFail, compilationResults.CompiledMethodBodies, scanResults.CompiledMethodBodies, "Methods", "compiled", "scanned", method => !(method.GetTypicalMethodDefinition() is EcmaMethod) || method.Name == "ThrowPlatformNotSupportedException"); DiffCompilationResults(ref scanningFail, compilationResults.ConstructedEETypes, scanResults.ConstructedEETypes, "EETypes", "compiled", "scanned", type => !(type.GetTypeDefinition() is EcmaType)); // If optimizations are enabled, the results will for sure not match in the other direction due to inlining, etc. // But there's at least some value in checking the scanner doesn't expand the universe too much in debug. if (_optimizationMode == OptimizationMode.None) { // Check that methods and types scanned are a subset of methods and types compiled // If we find diffs here, they're not critical, but still might be causing a Size on Disk regression. bool dummy = false; // We additionally skip methods in SIMD module because there's just too many intrisics to handle and IL scanner // doesn't expand them. They would show up as noisy diffs. DiffCompilationResults(ref dummy, scanResults.CompiledMethodBodies, compilationResults.CompiledMethodBodies, "Methods", "scanned", "compiled", method => !(method.GetTypicalMethodDefinition() is EcmaMethod) || simdHelper.IsSimdType(method.OwningType)); DiffCompilationResults(ref dummy, scanResults.ConstructedEETypes, compilationResults.ConstructedEETypes, "EETypes", "scanned", "compiled", type => !(type.GetTypeDefinition() is EcmaType)); } if (scanningFail) throw new Exception("Scanning failure"); } if (debugInfoProvider is IDisposable) ((IDisposable)debugInfoProvider).Dispose(); return 0; }
public TestTypeSystemContext(TargetArchitecture arch, TargetOS targetOS = TargetOS.Unknown) : base(new TargetDetails(arch, targetOS, TargetAbi.Unknown)) { _vectorFieldLayoutAlgorithm = new VectorFieldLayoutAlgorithm(_metadataFieldLayout, true); _int128FieldLayoutAlgorithm = new Int128FieldLayoutAlgorithm(_metadataFieldLayout); }
public void SavePerfMap(string perfMapPath, int perfMapFormatVersion, string dllFileName, TargetOS targetOS, TargetArchitecture targetArch) { string perfMapExtension; if (perfMapFormatVersion == PerfMapWriter.LegacyCrossgen1FormatVersion) { string mvidComponent = null; foreach (AssemblyInfo inputAssembly in _outputInfoBuilder.EnumerateInputAssemblies()) { if (mvidComponent == null) { mvidComponent = inputAssembly.Mvid.ToString(); } else { mvidComponent = "composite"; break; } } perfMapExtension = ".ni.{" + mvidComponent + "}.map"; } else { perfMapExtension = ".ni.r2rmap"; } string perfMapFileName = Path.Combine(perfMapPath, Path.GetFileNameWithoutExtension(dllFileName) + perfMapExtension); Console.WriteLine("Emitting PerfMap file: {0}", perfMapFileName); PerfMapWriter.Write(perfMapFileName, perfMapFormatVersion, _outputInfoBuilder.EnumerateMethods(), _outputInfoBuilder.EnumerateInputAssemblies(), targetOS, targetArch); }
public TargetDetails(TargetArchitecture architecture, TargetOS targetOS, TargetAbi abi) { Architecture = architecture; OperatingSystem = targetOS; Abi = abi; }
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; // TODO: compiler switch for SIMD support? var simdVectorLength = _isCppCodegen ? 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; } 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); }
/// <summary> /// Outputs specified headers, sections, methods or runtime functions for one ReadyToRun image /// </summary> /// <param name="r2r">The structure containing the info of the ReadyToRun image</param> public void Dump(ReadyToRunReader r2r) { _dumper.Begin(); bool standardDump = !(_options.EntryPoints || _options.CreatePDB || _options.CreatePerfmap); if (_options.Header && standardDump) { _dumper.WriteDivider("R2R Header"); _dumper.DumpHeader(true); } bool haveQuery = false; if (_options.Section != null) { haveQuery = true; QuerySection(r2r, _options.Section); } if (_options.RuntimeFunction != null) { haveQuery = true; QueryRuntimeFunction(r2r, _options.RuntimeFunction); } if (_options.Query != null) { haveQuery = true; QueryMethod(r2r, "R2R Methods by Query", _options.Query, true); } if (_options.Keyword != null) { haveQuery = true; QueryMethod(r2r, "R2R Methods by Keyword", _options.Keyword, false); } if (!haveQuery) { // Dump all sections and methods if no queries specified if (_options.EntryPoints) { _dumper.DumpEntryPoints(); } TargetArchitecture architecture = r2r.Machine switch { Machine.I386 => TargetArchitecture.X86, Machine.Amd64 => TargetArchitecture.X64, Machine.ArmThumb2 => TargetArchitecture.ARM, Machine.Arm64 => TargetArchitecture.ARM64, _ => throw new NotImplementedException(r2r.Machine.ToString()), }; TargetOS os = r2r.OperatingSystem switch { OperatingSystem.Windows => TargetOS.Windows, OperatingSystem.Linux => TargetOS.Linux, OperatingSystem.Apple => TargetOS.OSX, OperatingSystem.FreeBSD => TargetOS.FreeBSD, OperatingSystem.NetBSD => TargetOS.FreeBSD, _ => throw new NotImplementedException(r2r.OperatingSystem.ToString()), }; TargetDetails details = new TargetDetails(architecture, os, TargetAbi.CoreRT); if (_options.CreatePDB) { string pdbPath = _options.PdbPath; if (String.IsNullOrEmpty(pdbPath)) { pdbPath = Path.GetDirectoryName(r2r.Filename); } var pdbWriter = new PdbWriter(pdbPath, PDBExtraData.None, details); pdbWriter.WritePDBData(r2r.Filename, ProduceDebugInfoMethods(r2r)); } if (_options.CreatePerfmap) { string perfmapPath = _options.PerfmapPath; if (string.IsNullOrEmpty(perfmapPath)) { perfmapPath = Path.ChangeExtension(r2r.Filename, ".r2rmap"); } PerfMapWriter.Write(perfmapPath, _options.PerfmapFormatVersion, ProduceDebugInfoMethods(r2r), ProduceDebugInfoAssemblies(r2r), details); } if (standardDump) { _dumper.DumpAllMethods(); _dumper.DumpFixupStats(); } } _dumper.End(); }
public Recipe(string Name, TargetPlatform platform = TargetPlatform.UNKNOWN, TargetOS OS = TargetOS.UNKNOWN) { name = Name; config = new Config(platform, OS); scripts = new List <Script>(); }
public TimeZone(bool runningOnSaucelabs, TargetOS targetOS) { _runningOnSauceLabs = runningOnSaucelabs; _targetOS = targetOS; }
public Config(TargetPlatform targetPlatform = TargetPlatform.UNKNOWN, TargetOS targetOS = TargetOS.UNKNOWN, TargetArch targetArch = TargetArch.UNKNOWN) { }