diff options
Diffstat (limited to 'src/ILCompiler/src/Program.cs')
-rw-r--r-- | src/ILCompiler/src/Program.cs | 125 |
1 files changed, 93 insertions, 32 deletions
diff --git a/src/ILCompiler/src/Program.cs b/src/ILCompiler/src/Program.cs index e869f7540..cd75a913e 100644 --- a/src/ILCompiler/src/Program.cs +++ b/src/ILCompiler/src/Program.cs @@ -17,6 +17,8 @@ namespace ILCompiler { internal class Program { + private const string DefaultSystemModule = "System.Private.CoreLib"; + private Dictionary<string, string> _inputFilePaths = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); private Dictionary<string, string> _referenceFilePaths = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); @@ -37,7 +39,7 @@ namespace ILCompiler private OptimizationMode _optimizationMode; private bool _enableDebugInfo; private string _ilDump; - private string _systemModuleName = "System.Private.CoreLib"; + private string _systemModuleName = DefaultSystemModule; private bool _multiFile; private bool _nativeLib; private string _exportsFile; @@ -47,6 +49,8 @@ namespace ILCompiler private bool _emitStackTraceData; private string _mapFileName; private string _metadataLogFileName; + private bool _noMetadataBlocking; + private bool _completeTypesMetadata; private string _singleMethodTypeName; private string _singleMethodName; @@ -56,6 +60,12 @@ namespace ILCompiler private IReadOnlyList<string> _rdXmlFilePaths = Array.Empty<string>(); + private IReadOnlyList<string> _initAssemblies = Array.Empty<string>(); + + private IReadOnlyList<string> _appContextSwitches = Array.Empty<string>(); + + private IReadOnlyList<string> _runtimeOptions = Array.Empty<string>(); + private bool _help; private Program() @@ -88,20 +98,20 @@ namespace ILCompiler 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(); + 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(); } // Workaround for https://github.com/dotnet/corefx/issues/25267 @@ -149,10 +159,15 @@ namespace ILCompiler syntax.DefineOptionList("rdxml", ref _rdXmlFilePaths, "RD.XML file(s) for compilation"); syntax.DefineOption("map", ref _mapFileName, "Generate a map file"); syntax.DefineOption("metadatalog", ref _metadataLogFileName, "Generate a metadata log file"); + syntax.DefineOption("nometadatablocking", ref _noMetadataBlocking, "Ignore metadata blocking for internal implementation details"); + syntax.DefineOption("completetypemetadata", ref _completeTypesMetadata, "Generate complete metadata for types"); syntax.DefineOption("scan", ref _useScanner, "Use IL scanner to generate optimized code (implied by -O)"); syntax.DefineOption("noscan", ref _noScanner, "Do not use IL scanner to generate optimized code"); syntax.DefineOption("ildump", ref _ilDump, "Dump IL assembly listing for compiler-generated IL"); syntax.DefineOption("stacktracedata", ref _emitStackTraceData, "Emit data to support generating stack trace strings at runtime"); + syntax.DefineOptionList("initassembly", ref _initAssemblies, "Assembly(ies) with a library initializer"); + syntax.DefineOptionList("appcontextswitch", ref _appContextSwitches, "System.AppContext switches to set"); + syntax.DefineOptionList("runtimeopt", ref _runtimeOptions, "Runtime options to set"); syntax.DefineOption("targetarch", ref _targetArchitectureStr, "Target architecture for cross compilation"); syntax.DefineOption("targetos", ref _targetOSStr, "Target OS for cross compilation"); @@ -180,6 +195,33 @@ namespace ILCompiler return argSyntax; } + private IReadOnlyCollection<MethodDesc> CreateInitializerList(TypeSystemContext context) + { + List<ModuleDesc> assembliesWithInitalizers = new List<ModuleDesc>(); + + // Build a list of assemblies that have an initializer that needs to run before + // any user code runs. + foreach (string initAssemblyName in _initAssemblies) + { + ModuleDesc assembly = context.ResolveAssembly(new AssemblyName(initAssemblyName)); + assembliesWithInitalizers.Add(assembly); + } + + var libraryInitializers = new LibraryInitializers(context, assembliesWithInitalizers); + + List<MethodDesc> initializerList = new List<MethodDesc>(libraryInitializers.LibraryInitializerMethods); + + // If there are any AppContext switches the user wishes to enable, generate code that sets them. + if (_appContextSwitches.Count > 0) + { + MethodDesc appContextInitMethod = new Internal.IL.Stubs.StartupCode.AppContextInitializerMethod( + context.GeneratedAssembly.GetGlobalModuleType(), _appContextSwitches); + initializerList.Add(appContextInitMethod); + } + + return initializerList; + } + private int Run(string[] args) { InitializeDefaultOptions(); @@ -190,7 +232,7 @@ namespace ILCompiler Help(syntax.GetHelpText()); return 1; } - + if (_outputFilePath == null) throw new CommandLineException("Output filename must be specified (/out <file>)"); @@ -231,6 +273,7 @@ namespace ILCompiler if (_isWasmCodegen) _targetArchitecture = TargetArchitecture.Wasm32; + // // Initialize type system context // @@ -239,8 +282,9 @@ namespace ILCompiler 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 simdVectorLength = (_isCppCodegen || _isWasmCodegen) ? SimdVectorLength.None : SimdVectorLength.Vector128Bit; + var targetAbi = _isCppCodegen ? TargetAbi.CppCodegen : TargetAbi.CoreRT; + var targetDetails = new TargetDetails(_targetArchitecture, _targetOS, targetAbi, simdVectorLength); var typeSystemContext = new CompilerTypeSystemContext(targetDetails, genericsMode); // @@ -309,15 +353,8 @@ namespace ILCompiler if (entrypointModule != null) { - LibraryInitializers libraryInitializers = - new LibraryInitializers(typeSystemContext, _isCppCodegen); - compilationRoots.Add(new MainMethodRootProvider(entrypointModule, libraryInitializers.LibraryInitializerMethods)); - } - else if (_nativeLib) - { - EcmaModule module = (EcmaModule)typeSystemContext.SystemModule; - LibraryInitializers libraryInitializers = new LibraryInitializers(typeSystemContext, _isCppCodegen); - compilationRoots.Add(new NativeLibraryInitializerRootProvider(module, libraryInitializers.LibraryInitializerMethods)); + compilationRoots.Add(new MainMethodRootProvider(entrypointModule, CreateInitializerList(typeSystemContext))); + compilationRoots.Add(new RuntimeConfigurationRootProvider(_runtimeOptions)); } if (_multiFile) @@ -344,8 +381,15 @@ namespace ILCompiler throw new Exception("No entrypoint module"); compilationRoots.Add(new ExportedMethodsRootProvider((EcmaModule)typeSystemContext.SystemModule)); + compilationGroup = new SingleFileCompilationModuleGroup(); + } - compilationGroup = new SingleFileCompilationModuleGroup(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) @@ -371,12 +415,27 @@ namespace ILCompiler var stackTracePolicy = _emitStackTraceData ? (StackTraceEmissionPolicy)new EcmaMethodStackTraceEmissionPolicy() : new NoStackTraceEmissionPolicy(); + MetadataBlockingPolicy mdBlockingPolicy = _noMetadataBlocking ? + (MetadataBlockingPolicy)new NoMetadataBlockingPolicy() : new BlockedInternalsBlockingPolicy(); + + ManifestResourceBlockingPolicy resBlockingPolicy = new NoManifestResourceBlockingPolicy(); + + UsageBasedMetadataGenerationOptions metadataGenerationOptions = UsageBasedMetadataGenerationOptions.None; + if (_completeTypesMetadata) + metadataGenerationOptions |= UsageBasedMetadataGenerationOptions.CompleteTypesOnly; + + DynamicInvokeThunkGenerationPolicy invokeThunkGenerationPolicy = new DefaultDynamicInvokeThunkGenerationPolicy(); + UsageBasedMetadataManager metadataManager = new UsageBasedMetadataManager( compilationGroup, typeSystemContext, - new BlockedInternalsBlockingPolicy(), + mdBlockingPolicy, + resBlockingPolicy, _metadataLogFileName, - stackTracePolicy); + stackTracePolicy, + invokeThunkGenerationPolicy, + metadataGenerationOptions + ); // 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. @@ -388,7 +447,9 @@ namespace ILCompiler useScanner &= !_noScanner; - MetadataManager compilationMetadataManager = _isWasmCodegen ? (MetadataManager)new EmptyMetadataManager(typeSystemContext) : metadataManager; + bool supportsReflection = !_isWasmCodegen && !_isCppCodegen && _systemModuleName == DefaultSystemModule; + + MetadataManager compilationMetadataManager = supportsReflection ? metadataManager : (MetadataManager)new EmptyMetadataManager(typeSystemContext); ILScanResults scanResults = null; if (useScanner) { @@ -494,7 +555,7 @@ namespace ILCompiler // 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)); + "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)); } |