Beispiel #1
0
        public Compilation(CompilerTypeSystemContext typeSystemContext, CompilationOptions options)
        {
            _typeSystemContext = typeSystemContext;
            _options = options;

            _nameMangler = new NameMangler(this);
        }
Beispiel #2
0
        public Compilation(CompilationOptions options, CompilerTypeSystemContext context, CompilationModuleGroup compilationGroup)
        {
            _options = options;

            _nameMangler = new NameMangler(options.IsCppCodeGen);

            _typeSystemContext = context;
            _compilationModuleGroup = compilationGroup;
        }
Beispiel #3
0
        public Compilation(CompilationOptions options)
        {
            _options = options;

            _typeSystemContext = new CompilerTypeSystemContext(new TargetDetails(options.TargetArchitecture, options.TargetOS));
            _typeSystemContext.InputFilePaths = options.InputFilePaths;
            _typeSystemContext.ReferenceFilePaths = options.ReferenceFilePaths;

            _typeSystemContext.SetSystemModule(_typeSystemContext.GetModuleForSimpleName(options.SystemModuleName));

            _nameMangler = new NameMangler(this);
        }
Beispiel #4
0
        public Compilation(CompilationOptions options)
        {
            _options = options;

            _typeSystemContext = new CompilerTypeSystemContext(new TargetDetails(options.TargetArchitecture, options.TargetOS));
            _typeSystemContext.InputFilePaths = options.InputFilePaths;
            _typeSystemContext.ReferenceFilePaths = options.ReferenceFilePaths;

            _typeSystemContext.SetSystemModule(_typeSystemContext.GetModuleForSimpleName(options.SystemModuleName));

            _nameMangler = new NameMangler(this);

            _typeInitManager = new TypeInitialization();

            if (options.MultiFile)
            {
                _compilationModuleGroup = new MultiFileCompilationModuleGroup(_typeSystemContext, this);
            }
            else
            {
                _compilationModuleGroup = new SingleFileCompilationModuleGroup(_typeSystemContext, this);
            }
        }
        public AnalysisBasedMetadataManager(
            CompilerTypeSystemContext typeSystemContext,
            MetadataBlockingPolicy blockingPolicy,
            ManifestResourceBlockingPolicy resourceBlockingPolicy,
            string logFile,
            StackTraceEmissionPolicy stackTracePolicy,
            DynamicInvokeThunkGenerationPolicy invokeThunkGenerationPolicy,
            IEnumerable <ModuleDesc> modulesWithMetadata,
            IEnumerable <ReflectableEntity <TypeDesc> > reflectableTypes,
            IEnumerable <ReflectableEntity <MethodDesc> > reflectableMethods,
            IEnumerable <ReflectableEntity <FieldDesc> > reflectableFields)
            : base(typeSystemContext, blockingPolicy, resourceBlockingPolicy, logFile, stackTracePolicy, invokeThunkGenerationPolicy)
        {
            _modulesWithMetadata = new List <ModuleDesc>(modulesWithMetadata);

            foreach (var refType in reflectableTypes)
            {
                _reflectableTypes.Add(refType.Entity, refType.Category);
            }

            foreach (var refMethod in reflectableMethods)
            {
                // Asking for description or runtime mapping for a member without asking
                // for the owning type would mean we can't actually satisfy the request.
                Debug.Assert((refMethod.Category & MetadataCategory.Description) == 0 ||
                             (_reflectableTypes[refMethod.Entity.OwningType] & MetadataCategory.Description) != 0);
                Debug.Assert((refMethod.Category & MetadataCategory.RuntimeMapping) == 0 ||
                             (_reflectableTypes[refMethod.Entity.OwningType] & MetadataCategory.RuntimeMapping) != 0);
                _reflectableMethods.Add(refMethod.Entity, refMethod.Category);
            }

            foreach (var refField in reflectableFields)
            {
                // Asking for description or runtime mapping for a member without asking
                // for the owning type would mean we can't actually satisfy the request.
                Debug.Assert((refField.Category & MetadataCategory.Description) == 0 ||
                             (_reflectableTypes[refField.Entity.OwningType] & MetadataCategory.Description) != 0);
                Debug.Assert((refField.Category & MetadataCategory.RuntimeMapping) == 0 ||
                             (_reflectableTypes[refField.Entity.OwningType] & MetadataCategory.RuntimeMapping) != 0);
                _reflectableFields.Add(refField.Entity, refField.Category);
            }

#if DEBUG
            HashSet <ModuleDesc> moduleHash = new HashSet <ModuleDesc>(_modulesWithMetadata);
            foreach (var refType in reflectableTypes)
            {
                // The instantiated types need to agree on the Description bit with the definition.
                // GetMetadataCategory relies on that.
                Debug.Assert((GetMetadataCategory(refType.Entity.GetTypeDefinition()) & MetadataCategory.Description)
                             == (GetMetadataCategory(refType.Entity) & MetadataCategory.Description));

                Debug.Assert(!(refType.Entity is MetadataType) || moduleHash.Contains(((MetadataType)refType.Entity).Module));
            }

            foreach (var refMethod in reflectableMethods)
            {
                // The instantiated methods need to agree on the Description bit with the definition.
                // GetMetadataCategory relies on that.
                Debug.Assert((GetMetadataCategory(refMethod.Entity.GetTypicalMethodDefinition()) & MetadataCategory.Description)
                             == (GetMetadataCategory(refMethod.Entity) & MetadataCategory.Description));

                // Canonical form of the method needs to agree with the logical form
                Debug.Assert(GetMetadataCategory(refMethod.Entity) == GetMetadataCategory(refMethod.Entity.GetCanonMethodTarget(CanonicalFormKind.Specific)));
            }

            foreach (var refField in reflectableFields)
            {
                // The instantiated fields need to agree on the Description bit with the definition.
                // GetMetadataCategory relies on that.
                Debug.Assert((GetMetadataCategory(refField.Entity.GetTypicalFieldDefinition()) & MetadataCategory.Description)
                             == (GetMetadataCategory(refField.Entity) & MetadataCategory.Description));
            }
#endif
        }
Beispiel #6
0
        private int Run(string[] args)
        {
            InitializeDefaultOptions();

            ArgumentSyntax syntax = ParseCommandLine(args);

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

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

            //
            // Set target Architecture and OS
            //
            if (_targetArchitectureStr != null)
            {
                if (_targetArchitectureStr.Equals("x86", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.X86;
                }
                else if (_targetArchitectureStr.Equals("x64", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.X64;
                }
                else if (_targetArchitectureStr.Equals("arm", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.ARM;
                }
                else if (_targetArchitectureStr.Equals("armel", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.ARMEL;
                }
                else if (_targetArchitectureStr.Equals("arm64", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.ARM64;
                }
                else
                {
                    throw new CommandLineException("Target architecture is not supported");
                }
            }
            if (_targetOSStr != null)
            {
                if (_targetOSStr.Equals("windows", StringComparison.OrdinalIgnoreCase))
                {
                    _targetOS = TargetOS.Windows;
                }
                else if (_targetOSStr.Equals("linux", StringComparison.OrdinalIgnoreCase))
                {
                    _targetOS = TargetOS.Linux;
                }
                else if (_targetOSStr.Equals("osx", StringComparison.OrdinalIgnoreCase))
                {
                    _targetOS = TargetOS.OSX;
                }
                else
                {
                    throw new CommandLineException("Target OS is not supported");
                }
            }

            //
            // Initialize type system context
            //

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

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

            ILScanResults scanResults = null;

            if (_useScanner && !_isCppCodegen)
            {
                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 = _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);

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

            if (scanResults != null)
            {
                // If we have a scanner, feed the vtable analysis results to the compilation.
                // This could be a command line switch if we really wanted to.
                builder.UseVTableSliceProvider(scanResults.GetVTableLayoutInfo());

                // If we have a scanner, feed the generic dictionary results to the compilation.
                // This could be a command line switch if we really wanted to.
                builder.UseGenericDictionaryLayoutProvider(scanResults.GetDictionaryLayoutInfo());
            }

            ICompilation compilation = builder.ToCompilation();

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

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

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

            if (scanResults != null)
            {
                SimdHelper simdHelper = new SimdHelper();

                if (_scanDgmlLogFileName != null)
                {
                    scanResults.WriteDependencyLog(_scanDgmlLogFileName);
                }

                // If the scanner and compiler don't agree on what to compile, the outputs of the scanner might not actually be usable.
                // We are going to check this two ways:
                // 1. The methods and types generated during compilation are a subset of method and types scanned
                // 2. The methods and types scanned are a subset of methods and types compiled (this has a chance to hold for unoptimized builds only).

                // Check that methods and types generated during compilation are a subset of method and types scanned
                bool scanningFail = false;
                DiffCompilationResults(ref scanningFail, compilationResults.CompiledMethodBodies, scanResults.CompiledMethodBodies,
                                       "Methods", "compiled", "scanned", method => !(method.GetTypicalMethodDefinition() is EcmaMethod));
                DiffCompilationResults(ref scanningFail, compilationResults.ConstructedEETypes, scanResults.ConstructedEETypes,
                                       "EETypes", "compiled", "scanned", type => !(type.GetTypeDefinition() is EcmaType));

                // If optimizations are enabled, the results will for sure not match in the other direction due to inlining, etc.
                // But there's at least some value in checking the scanner doesn't expand the universe too much in debug.
                if (_optimizationMode == OptimizationMode.None)
                {
                    // Check that methods and types scanned are a subset of methods and types compiled

                    // If we find diffs here, they're not critical, but still might be causing a Size on Disk regression.
                    bool dummy = false;

                    // We additionally skip methods in SIMD module because there's just too many intrisics to handle and IL scanner
                    // doesn't expand them. They would show up as noisy diffs.
                    DiffCompilationResults(ref dummy, scanResults.CompiledMethodBodies, compilationResults.CompiledMethodBodies,
                                           "Methods", "scanned", "compiled", method => !(method.GetTypicalMethodDefinition() is EcmaMethod) || simdHelper.IsInSimdModule(method.OwningType));
                    DiffCompilationResults(ref dummy, scanResults.ConstructedEETypes, compilationResults.ConstructedEETypes,
                                           "EETypes", "scanned", "compiled", type => !(type.GetTypeDefinition() is EcmaType));
                }

                if (scanningFail)
                {
                    throw new Exception("Scanning failure");
                }
            }

            return(0);
        }
 public RyuJitCompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup group)
     : base(context, group,
            new CoreRTNameMangler(context.Target.IsWindows ? (NodeMangler) new WindowsNodeMangler() : (NodeMangler) new UnixNodeMangler(), false))
 {
 }
Beispiel #8
0
        private void RunSingleCompilation(Dictionary <string, string> inFilePaths, InstructionSetSupport instructionSetSupport, string compositeRootPath, Dictionary <string, string> unrootedInputFilePaths, HashSet <ModuleDesc> versionBubbleModulesHash, CompilerTypeSystemContext typeSystemContext)
        {
            //
            // Initialize output filename
            //
            var outFile = _commandLineOptions.OutNearInput ? inFilePaths.First().Value.Replace(".dll", ".ni.dll") : _commandLineOptions.OutputFilePath;

            using (PerfEventSource.StartStopEvents.CompilationEvents())
            {
                ICompilation compilation;
                using (PerfEventSource.StartStopEvents.LoadingEvents())
                {
                    List <EcmaModule> inputModules   = new List <EcmaModule>();
                    List <EcmaModule> rootingModules = new List <EcmaModule>();
                    Guid?inputModuleMvid             = null;

                    foreach (var inputFile in inFilePaths)
                    {
                        EcmaModule module = typeSystemContext.GetModuleFromPath(inputFile.Value);
                        inputModules.Add(module);
                        rootingModules.Add(module);
                        versionBubbleModulesHash.Add(module);

                        if (!_commandLineOptions.Composite && !inputModuleMvid.HasValue)
                        {
                            inputModuleMvid = module.MetadataReader.GetGuid(module.MetadataReader.GetModuleDefinition().Mvid);
                        }

                        if (!_commandLineOptions.CompositeOrInputBubble)
                        {
                            break;
                        }
                    }

                    foreach (var unrootedInputFile in unrootedInputFilePaths)
                    {
                        EcmaModule module = typeSystemContext.GetModuleFromPath(unrootedInputFile.Value);
                        inputModules.Add(module);
                        versionBubbleModulesHash.Add(module);
                    }

                    //
                    // 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>();
                    foreach (var file in _commandLineOptions.MibcFilePaths)
                    {
                        mibcFiles.Add(file);
                    }

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

                    // Load any profiles generated by method call chain analyis
                    CallChainProfile jsonProfile = null;

                    if (!string.IsNullOrEmpty(_commandLineOptions.CallChainProfileFile))
                    {
                        jsonProfile = new CallChainProfile(_commandLineOptions.CallChainProfileFile, typeSystemContext, _referenceableModules);
                    }

                    // Examine profile guided information as appropriate
                    ProfileDataManager profileDataManager =
                        new ProfileDataManager(logger,
                                               _referenceableModules,
                                               inputModules,
                                               versionBubbleModules,
                                               _commandLineOptions.CompileBubbleGenerics ? inputModules[0] : null,
                                               mibcFiles,
                                               jsonProfile,
                                               typeSystemContext,
                                               compilationGroup,
                                               _commandLineOptions.EmbedPgoData);

                    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;
                            }
                        }
                    }
                    // In single-file compilation mode, use the assembly's DebuggableAttribute to determine whether to optimize
                    // or produce debuggable code if an explicit optimization level was not specified on the command line
                    OptimizationMode optimizationMode = _optimizationMode;
                    if (optimizationMode == OptimizationMode.None && !_commandLineOptions.OptimizeDisabled && !_commandLineOptions.Composite)
                    {
                        System.Diagnostics.Debug.Assert(inputModules.Count == 1);
                        optimizationMode = ((EcmaAssembly)inputModules[0].Assembly).HasOptimizationsDisabled() ? OptimizationMode.None : OptimizationMode.Blended;
                    }

                    CompositeImageSettings compositeImageSettings = new CompositeImageSettings();

                    if (_commandLineOptions.CompositeKeyFile != null)
                    {
                        ImmutableArray <byte> compositeStrongNameKey = File.ReadAllBytes(_commandLineOptions.CompositeKeyFile).ToImmutableArray();
                        if (!IsValidPublicKey(compositeStrongNameKey))
                        {
                            throw new Exception(string.Format(SR.ErrorCompositeKeyFileNotPublicKey));
                        }

                        compositeImageSettings.PublicKey = compositeStrongNameKey;
                    }

                    //
                    // Compile
                    //

                    ReadyToRunCodegenCompilationBuilder builder = new ReadyToRunCodegenCompilationBuilder(
                        typeSystemContext, compilationGroup, _allInputFilePaths.Values, compositeRootPath);
                    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)
                    .UseMapCsvFile(_commandLineOptions.MapCsv)
                    .UsePdbFile(_commandLineOptions.Pdb, _commandLineOptions.PdbPath)
                    .UsePerfMapFile(_commandLineOptions.PerfMap, _commandLineOptions.PerfMapPath, inputModuleMvid)
                    .UseProfileFile(jsonProfile != null)
                    .UseParallelism(_commandLineOptions.Parallelism)
                    .UseProfileData(profileDataManager)
                    .FileLayoutAlgorithms(_methodLayout, _fileLayout)
                    .UseCompositeImageSettings(compositeImageSettings)
                    .UseJitPath(_commandLineOptions.JitPath)
                    .UseInstructionSetSupport(instructionSetSupport)
                    .UseCustomPESectionAlignment(_commandLineOptions.CustomPESectionAlignment)
                    .UseVerifyTypeAndFieldLayout(_commandLineOptions.VerifyTypeAndFieldLayout)
                    .GenerateOutputFile(outFile)
                    .UseILProvider(ilProvider)
                    .UseBackendOptions(_commandLineOptions.CodegenOptions)
                    .UseLogger(logger)
                    .UseDependencyTracking(trackingLevel)
                    .UseCompilationRoots(compilationRoots)
                    .UseOptimizationMode(optimizationMode);

                    if (_commandLineOptions.PrintReproInstructions)
                    {
                        builder.UsePrintReproInstructions(CreateReproArgumentString);
                    }

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

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

                compilation.Dispose();
            }
        }
Beispiel #9
0
        private int Run()
        {
            using (PerfEventSource.StartStopEvents.CompilationEvents())
            {
                ICompilation compilation;
                using (PerfEventSource.StartStopEvents.LoadingEvents())
                {
                    InitializeDefaultOptions();

                    ProcessCommandLine();

                    if (_commandLineOptions.OutputFilePath == null)
                    {
                        throw new CommandLineException(SR.MissingOutputFile);
                    }

                    CheckCustomPESectionAlignment();
                    ConfigureTarget();
                    InstructionSetSupport instructionSetSupport = ConfigureInstructionSetSupport();

                    //
                    // Initialize type system context
                    //

                    SharedGenericsMode genericsMode = SharedGenericsMode.CanonicalReferenceTypes;

                    var targetDetails = new TargetDetails(_targetArchitecture, _targetOS, TargetAbi.CoreRT, instructionSetSupport.GetVectorTSimdVector());
                    _typeSystemContext = new ReadyToRunCompilerContext(targetDetails, genericsMode);

                    string compositeRootPath = _commandLineOptions.CompositeRootPath?.FullName;

                    //
                    // 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);
                            if (compositeRootPath == null)
                            {
                                compositeRootPath = Path.GetDirectoryName(inputFile.Value);
                            }
                        }
                        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);
                                if (compositeRootPath == null)
                                {
                                    compositeRootPath = Path.GetDirectoryName(unrootedInputFile.Value);
                                }
                            }
                        }
                        catch (TypeSystemException.BadImageFormatException)
                        {
                            // Keep calm and carry on.
                        }
                    }

                    CheckManagedCppInputFiles(allInputFilePaths.Values);

                    _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)
                    {
                        if (_commandLineOptions.InputFilePaths.Count() > 0)
                        {
                            Console.WriteLine(SR.InputWasNotLoadable);
                            return(2);
                        }
                        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, compositeRootPath);
                    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)
                    .UseProfileData(profileDataManager)
                    .FileLayoutAlgorithms(_commandLineOptions.MethodLayout, _commandLineOptions.FileLayout)
                    .UseJitPath(_commandLineOptions.JitPath)
                    .UseInstructionSetSupport(instructionSetSupport)
                    .UseCustomPESectionAlignment(_commandLineOptions.CustomPESectionAlignment)
                    .UseVerifyTypeAndFieldLayout(_commandLineOptions.VerifyTypeAndFieldLayout)
                    .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);
        }
 public CppCodegenCompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup group)
     : base(new CppCodegenNodeFactory(context, group))
 {
 }
 public WebAssemblyCodegenCompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup group)
     : base(context, group, new CoreRTNameMangler(new WebAssemblyNodeMangler(), false))
 {
 }
 public MultiFileCompilationModuleGroup(CompilerTypeSystemContext typeSystemContext) : base(typeSystemContext)
 { }
 public MultiFileSharedCompilationModuleGroup(CompilerTypeSystemContext context, IEnumerable <ModuleDesc> compilationModuleSet)
     : base(context, compilationModuleSet)
 {
 }
 public CompilerGeneratedInteropStubManager(CompilationModuleGroup compilationModuleGroup, CompilerTypeSystemContext typeSystemContext, InteropStateManager interopStateManager) :
     base(compilationModuleGroup, typeSystemContext, interopStateManager)
 {
 }
Beispiel #15
0
 public EmptyMetadataManager(CompilerTypeSystemContext typeSystemContext)
     : base(typeSystemContext, new FullyBlockedMetadataPolicy(), new FullyBlockedManifestResourcePolicy())
 {
 }
Beispiel #16
0
 public InteropStubManager(CompilationModuleGroup compilationModuleGroup, CompilerTypeSystemContext typeSystemContext, InteropStateManager interopStateManager)
 {
     _compilationModuleGroup = compilationModuleGroup;
     _typeSystemContext      = typeSystemContext;
     InteropStateManager     = interopStateManager;
 }
Beispiel #17
0
 public SingleFileCompilationModuleGroup(CompilerTypeSystemContext typeSystemContext) : base(typeSystemContext)
 {
 }
Beispiel #18
0
        public ProfileDataManager(Logger logger,
                                  IEnumerable <ModuleDesc> possibleReferenceModules,
                                  IEnumerable <ModuleDesc> inputModules,
                                  IEnumerable <ModuleDesc> versionBubbleModules,
                                  ModuleDesc nonLocalGenericsHome,
                                  IReadOnlyList <string> mibcFiles,
                                  CompilerTypeSystemContext context,
                                  ReadyToRunCompilationModuleGroupBase compilationGroup)
        {
            _ibcParser        = new IBCProfileParser(logger, possibleReferenceModules);
            _compilationGroup = compilationGroup;
            HashSet <ModuleDesc> versionBubble = new HashSet <ModuleDesc>(versionBubbleModules);

            {
                // Parse MIbc Data

                string onlyParseItemsDefinedInAssembly = nonLocalGenericsHome == null?inputModules.First().Assembly.GetName().Name : null;

                HashSet <string> versionBubbleModuleStrings = new HashSet <string>();
                foreach (ModuleDesc versionBubbleModule in versionBubble)
                {
                    versionBubbleModuleStrings.Add(versionBubbleModule.Assembly.GetName().Name);
                }

                foreach (string file in mibcFiles)
                {
                    _inputData.Add(MIbcProfileParser.ParseMIbcFile(context, file, versionBubbleModuleStrings, onlyParseItemsDefinedInAssembly));
                }
            }

            {
                // Parse Ibc data
                foreach (var module in inputModules)
                {
                    _inputData.Add(_ibcParser.ParseIBCDataFromModule((EcmaModule)module));
                    _placedProfileMethods.Add(module, new HashSet <MethodDesc>());
                }
            }

            // Merge all data together
            foreach (ProfileData profileData in _inputData)
            {
                MergeProfileData(ref _partialNGen, _mergedProfileData, profileData);
            }

            // With the merged data find the set of methods to be placed within this module
            foreach (var profileData in _mergedProfileData)
            {
                // If the method is not excluded from processing
                if (!profileData.Value.Flags.HasFlag(MethodProfilingDataFlags.ExcludeHotMethodCode) &&
                    !profileData.Value.Flags.HasFlag(MethodProfilingDataFlags.ExcludeColdMethodCode))
                {
                    // Check for methods which are defined within the version bubble, and only rely on other modules within the bubble
                    if (!_compilationGroup.VersionsWithMethodBody(profileData.Key))
                    {
                        continue; // Method not contained within version bubble
                    }
                    if (_compilationGroup.ContainsType(profileData.Key.OwningType) &&
                        (profileData.Key.OwningType is MetadataType declaringType))
                    {
                        // In this case the method is placed in its natural home (which is the defining module of the method)
                        _placedProfileMethods[declaringType.Module].Add(profileData.Key);
                        _placedProfileMethodsAll.Add(profileData.Key);
                    }
                    else
                    {
                        // If the defining module is not within the input set, if the nonLocalGenericsHome is provided, place it there
                        if ((nonLocalGenericsHome != null) && (profileData.Key.GetTypicalMethodDefinition() != profileData.Key))
                        {
                            _placedProfileMethods[nonLocalGenericsHome].Add(profileData.Key);
                            _placedProfileMethodsAll.Add(profileData.Key);
                        }
                    }
                }
            }
        }
Beispiel #19
0
        private int Run(string[] args)
        {
            InitializeDefaultOptions();

            ArgumentSyntax syntax = ParseCommandLine(args);

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

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

            //
            // Set target Architecture and OS
            //
            if (_targetArchitectureStr != null)
            {
                if (_targetArchitectureStr.Equals("x86", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.X86;
                }
                else if (_targetArchitectureStr.Equals("x64", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.X64;
                }
                else if (_targetArchitectureStr.Equals("arm", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.ARM;
                }
                else if (_targetArchitectureStr.Equals("armel", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.ARM;
                }
                else if (_targetArchitectureStr.Equals("arm64", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.ARM64;
                }
                else if (_targetArchitectureStr.Equals("wasm", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.Wasm32;
                    _isWasmCodegen      = true;
                }
                else
                {
                    throw new CommandLineException("Target architecture is not supported");
                }
            }
            if (_targetOSStr != null)
            {
                if (_targetOSStr.Equals("windows", StringComparison.OrdinalIgnoreCase))
                {
                    _targetOS = TargetOS.Windows;
                }
                else if (_targetOSStr.Equals("linux", StringComparison.OrdinalIgnoreCase))
                {
                    _targetOS = TargetOS.Linux;
                }
                else if (_targetOSStr.Equals("osx", StringComparison.OrdinalIgnoreCase))
                {
                    _targetOS = TargetOS.OSX;
                }
                else
                {
                    throw new CommandLineException("Target OS is not supported");
                }
            }

            if (_isWasmCodegen)
            {
                _targetArchitecture = TargetArchitecture.Wasm32;
            }

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

            //
            // Initialize type system context
            //

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

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

            //
            // TODO: To support our pre-compiled test tree, allow input files that aren't managed assemblies since
            // some tests contain a mixture of both managed and native binaries.
            //
            // See: https://github.com/dotnet/corert/issues/2785
            //
            // When we undo this this hack, replace this foreach with
            //  typeSystemContext.InputFilePaths = _inputFilePaths;
            //
            Dictionary <string, string> inputFilePaths = new Dictionary <string, string>();

            foreach (var inputFile in _inputFilePaths)
            {
                try
                {
                    var module = typeSystemContext.GetModuleFromPath(inputFile.Value);
                    inputFilePaths.Add(inputFile.Key, inputFile.Value);
                }
                catch (TypeSystemException.BadImageFormatException)
                {
                    // Keep calm and carry on.
                }
            }

            typeSystemContext.InputFilePaths     = inputFilePaths;
            typeSystemContext.ReferenceFilePaths = _referenceFilePaths;

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

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

            //
            // Initialize compilation group and compilation roots
            //

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

            CompilationModuleGroup          compilationGroup;
            List <ICompilationRootProvider> compilationRoots = new List <ICompilationRootProvider>();

            if (singleMethod != null)
            {
                // Compiling just a single method
                compilationGroup = new SingleMethodCompilationModuleGroup(singleMethod);
                compilationRoots.Add(new SingleMethodRootProvider(singleMethod));
            }
            else
            {
                // Either single file, or multifile library, or multifile consumption.
                EcmaModule entrypointModule          = null;
                bool       systemModuleIsInputModule = false;
                foreach (var inputFile in typeSystemContext.InputFilePaths)
                {
                    EcmaModule module = typeSystemContext.GetModuleFromPath(inputFile.Value);

                    if (module.PEReader.PEHeaders.IsExe)
                    {
                        if (entrypointModule != null)
                        {
                            throw new Exception("Multiple EXE modules");
                        }
                        entrypointModule = module;
                    }

                    if (module == typeSystemContext.SystemModule)
                    {
                        systemModuleIsInputModule = true;
                    }

                    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 (_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;
            }
            if (_rootAllApplicationAssemblies)
            {
                metadataGenerationOptions |= UsageBasedMetadataGenerationOptions.FullUserAssemblyRooting;
            }

            DynamicInvokeThunkGenerationPolicy invokeThunkGenerationPolicy = new DefaultDynamicInvokeThunkGenerationPolicy();

            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);
        }
Beispiel #20
0
 public ReadyToRunTableManager(CompilerTypeSystemContext typeSystemContext)
     : base(typeSystemContext)
 {
 }
Beispiel #21
0
 public EmptyMetadataManager(CompilationModuleGroup group, CompilerTypeSystemContext typeSystemContext) : base(group, typeSystemContext)
 {
 }
 public MultiFileCompilationModuleGroup(CompilerTypeSystemContext typeSystemContext, ICompilationRootProvider rootProvider) : base(typeSystemContext, rootProvider)
 { }
 protected CompilationModuleGroup(CompilerTypeSystemContext typeSystemContext, ICompilationRootProvider rootProvider)
 {
     _typeSystemContext = typeSystemContext;
     _rootProvider = rootProvider;
 }
 public CompilerGeneratedMetadataManager(CompilationModuleGroup group, CompilerTypeSystemContext typeSystemContext) : base(group, typeSystemContext)
 {
     _metadataPolicy = new GeneratedTypesAndCodeMetadataPolicy(this);
 }
Beispiel #25
0
 protected CompilationModuleGroup(CompilerTypeSystemContext typeSystemContext, ICompilationRootProvider rootProvider)
 {
     _typeSystemContext = typeSystemContext;
     _rootProvider      = rootProvider;
 }
 public SingleFileCompilationModuleGroup(CompilerTypeSystemContext typeSystemContext, ICompilationRootProvider rootProvider) : base(typeSystemContext, rootProvider)
 {
 }
Beispiel #27
0
        /// <summary>
        /// Constructs a new instance of <see cref="DelegateCreationInfo"/> set up to construct a delegate of type
        /// '<paramref name="delegateType"/>' pointing to '<paramref name="targetMethod"/>'.
        /// </summary>
        public static DelegateCreationInfo Create(TypeDesc delegateType, MethodDesc targetMethod, TypeDesc constrainedType, NodeFactory factory, bool followVirtualDispatch)
        {
            CompilerTypeSystemContext context = factory.TypeSystemContext;
            DefType systemDelegate            = context.GetWellKnownType(WellKnownType.MulticastDelegate).BaseType;

            int paramCountTargetMethod = targetMethod.Signature.Length;

            if (!targetMethod.Signature.IsStatic)
            {
                paramCountTargetMethod++;
            }

            DelegateInfo delegateInfo             = context.GetDelegateInfo(delegateType.GetTypeDefinition());
            int          paramCountDelegateClosed = delegateInfo.Signature.Length + 1;
            bool         closed = false;

            if (paramCountDelegateClosed == paramCountTargetMethod)
            {
                closed = true;
            }
            else
            {
                Debug.Assert(paramCountDelegateClosed == paramCountTargetMethod + 1);
            }

            if (targetMethod.Signature.IsStatic)
            {
                MethodDesc invokeThunk;
                MethodDesc initMethod;

                if (!closed)
                {
                    initMethod  = systemDelegate.GetKnownMethod("InitializeOpenStaticThunk", null);
                    invokeThunk = delegateInfo.Thunks[DelegateThunkKind.OpenStaticThunk];
                }
                else
                {
                    // Closed delegate to a static method (i.e. delegate to an extension method that locks the first parameter)
                    invokeThunk = delegateInfo.Thunks[DelegateThunkKind.ClosedStaticThunk];
                    initMethod  = systemDelegate.GetKnownMethod("InitializeClosedStaticThunk", null);
                }

                var instantiatedDelegateType = delegateType as InstantiatedType;
                if (instantiatedDelegateType != null)
                {
                    invokeThunk = context.GetMethodForInstantiatedType(invokeThunk, instantiatedDelegateType);
                }

                return(new DelegateCreationInfo(
                           factory.MethodEntrypoint(initMethod),
                           targetMethod,
                           constrainedType,
                           constrainedType == null ? TargetKind.ExactCallableAddress : TargetKind.ConstrainedMethod,
                           factory.MethodEntrypoint(invokeThunk)));
            }
            else
            {
                if (!closed)
                {
                    throw new NotImplementedException("Open instance delegates");
                }

                string     initializeMethodName = "InitializeClosedInstance";
                MethodDesc targetCanonMethod    = targetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
                TargetKind kind;
                if (targetMethod.HasInstantiation)
                {
                    if (followVirtualDispatch && targetMethod.IsVirtual)
                    {
                        initializeMethodName = "InitializeClosedInstanceWithGVMResolution";
                        kind = TargetKind.MethodHandle;
                    }
                    else
                    {
                        if (targetMethod != targetCanonMethod)
                        {
                            // Closed delegates to generic instance methods need to be constructed through a slow helper that
                            // checks for the fat function pointer case (function pointer + instantiation argument in a single
                            // pointer) and injects an invocation thunk to unwrap the fat function pointer as part of
                            // the invocation if necessary.
                            initializeMethodName = "InitializeClosedInstanceSlow";
                        }

                        kind = TargetKind.ExactCallableAddress;
                    }
                }
                else
                {
                    if (followVirtualDispatch && targetMethod.IsVirtual)
                    {
                        if (targetMethod.OwningType.IsInterface)
                        {
                            kind = TargetKind.InterfaceDispatch;
                            initializeMethodName = "InitializeClosedInstanceToInterface";
                        }
                        else
                        {
                            kind         = TargetKind.VTableLookup;
                            targetMethod = targetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
                        }
                    }
                    else
                    {
                        kind         = TargetKind.CanonicalEntrypoint;
                        targetMethod = targetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
                    }
                }

                Debug.Assert(constrainedType == null);
                return(new DelegateCreationInfo(
                           factory.MethodEntrypoint(systemDelegate.GetKnownMethod(initializeMethodName, null)),
                           targetMethod,
                           constrainedType,
                           kind));
            }
        }
Beispiel #28
0
        private int Run(string[] args)
        {
            InitializeDefaultOptions();

            ProcessCommandLine(args);

            if (_commandLineOptions.Help)
            {
                Console.WriteLine(_commandLineOptions.HelpText);
                return(1);
            }

            if (_commandLineOptions.OutputFilePath == null && !_commandLineOptions.OutNearInput)
            {
                throw new CommandLineException(SR.MissingOutputFile);
            }

            ConfigureTarget();
            InstructionSetSupport instructionSetSupport = ConfigureInstructionSetSupport();

            SharedGenericsMode genericsMode = SharedGenericsMode.CanonicalReferenceTypes;

            var targetDetails = new TargetDetails(_targetArchitecture, _targetOS, _armelAbi ? TargetAbi.CoreRTArmel : TargetAbi.CoreRT, instructionSetSupport.GetVectorTSimdVector());

            bool versionBubbleIncludesCoreLib = false;

            if (_commandLineOptions.InputBubble)
            {
                versionBubbleIncludesCoreLib = true;
            }
            else
            {
                if (!_commandLineOptions.SingleFileCompilation)
                {
                    foreach (var inputFile in _inputFilePaths)
                    {
                        if (String.Compare(inputFile.Key, "System.Private.CoreLib", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            versionBubbleIncludesCoreLib = true;
                            break;
                        }
                    }
                }
                if (!versionBubbleIncludesCoreLib)
                {
                    foreach (var inputFile in _unrootedInputFilePaths)
                    {
                        if (String.Compare(inputFile.Key, "System.Private.CoreLib", StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            versionBubbleIncludesCoreLib = true;
                            break;
                        }
                    }
                }
            }

            //
            // Initialize type system context
            //
            _typeSystemContext = new ReadyToRunCompilerContext(targetDetails, genericsMode, versionBubbleIncludesCoreLib);

            string compositeRootPath = _commandLineOptions.CompositeRootPath;

            // Collections for already loaded modules
            Dictionary <string, string> inputFilePaths           = new Dictionary <string, string>();
            Dictionary <string, string> unrootedInputFilePaths   = new Dictionary <string, string>();
            HashSet <ModuleDesc>        versionBubbleModulesHash = new HashSet <ModuleDesc>();

            using (PerfEventSource.StartStopEvents.LoadingEvents())
            {
                //
                // 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 = inFilePaths;
                //

                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);
                        if (compositeRootPath == null)
                        {
                            compositeRootPath = Path.GetDirectoryName(inputFile.Value);
                        }
                    }
                    catch (TypeSystemException.BadImageFormatException)
                    {
                        // Keep calm and carry on.
                    }
                }

                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);
                            if (compositeRootPath == null)
                            {
                                compositeRootPath = Path.GetDirectoryName(unrootedInputFile.Value);
                            }
                        }
                    }
                    catch (TypeSystemException.BadImageFormatException)
                    {
                        // Keep calm and carry on.
                    }
                }

                CheckManagedCppInputFiles(_allInputFilePaths.Values);

                _typeSystemContext.InputFilePaths     = _allInputFilePaths;
                _typeSystemContext.ReferenceFilePaths = _referenceFilePaths;

                if (_typeSystemContext.InputFilePaths.Count == 0)
                {
                    if (_commandLineOptions.InputFilePaths.Count > 0)
                    {
                        Console.WriteLine(SR.InputWasNotLoadable);
                        return(2);
                    }
                    throw new CommandLineException(SR.NoInputFiles);
                }

                foreach (var referenceFile in _referenceFilePaths.Values)
                {
                    try
                    {
                        EcmaModule module = _typeSystemContext.GetModuleFromPath(referenceFile);
                        _referenceableModules.Add(module);
                        if (_commandLineOptions.InputBubble && _inputbubblereferenceFilePaths.Count == 0)
                        {
                            // In large version bubble mode add reference paths to the compilation group
                            // Consider bubble as large if no explicit bubble references were passed
                            versionBubbleModulesHash.Add(module);
                        }
                    }
                    catch { } // Ignore non-managed pe files
                }

                if (_commandLineOptions.InputBubble)
                {
                    foreach (var referenceFile in _inputbubblereferenceFilePaths.Values)
                    {
                        try
                        {
                            EcmaModule module = _typeSystemContext.GetModuleFromPath(referenceFile);
                            versionBubbleModulesHash.Add(module);
                        }
                        catch { } // Ignore non-managed pe files
                    }
                }
            }

            string systemModuleName = _commandLineOptions.SystemModule ?? DefaultSystemModule;

            _typeSystemContext.SetSystemModule((EcmaModule)_typeSystemContext.GetModuleForSimpleName(systemModuleName));
            CompilerTypeSystemContext typeSystemContext = _typeSystemContext;

            if (_commandLineOptions.SingleFileCompilation)
            {
                var singleCompilationInputFilePaths = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase);

                foreach (var inputFile in inputFilePaths)
                {
                    var singleCompilationVersionBubbleModulesHash = new HashSet <ModuleDesc>(versionBubbleModulesHash);

                    singleCompilationInputFilePaths.Clear();
                    singleCompilationInputFilePaths.Add(inputFile.Key, inputFile.Value);
                    typeSystemContext.InputFilePaths = singleCompilationInputFilePaths;

                    if (!_commandLineOptions.InputBubble)
                    {
                        bool singleCompilationVersionBubbleIncludesCoreLib = versionBubbleIncludesCoreLib || (String.Compare(inputFile.Key, "System.Private.CoreLib", StringComparison.OrdinalIgnoreCase) == 0);

                        typeSystemContext = new ReadyToRunCompilerContext(targetDetails, genericsMode, singleCompilationVersionBubbleIncludesCoreLib, _typeSystemContext);
                        typeSystemContext.SetSystemModule((EcmaModule)typeSystemContext.GetModuleForSimpleName(systemModuleName));
                    }

                    RunSingleCompilation(singleCompilationInputFilePaths, instructionSetSupport, compositeRootPath, unrootedInputFilePaths, singleCompilationVersionBubbleModulesHash, typeSystemContext);
                }
            }
            else
            {
                RunSingleCompilation(inputFilePaths, instructionSetSupport, compositeRootPath, unrootedInputFilePaths, versionBubbleModulesHash, typeSystemContext);
            }

            return(0);
        }
 public RyuJitCompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup group)
     : base(new RyuJitNodeFactory(context, group))
 {
 }
Beispiel #30
0
        private MethodDesc CheckAndParseSingleMethodModeArguments(CompilerTypeSystemContext context)
        {
            if (_commandLineOptions.SingleMethodName == null && _commandLineOptions.SingleMethodTypeName == null && _commandLineOptions.SingleMethodGenericArg == null)
            {
                return(null);
            }

            if (_commandLineOptions.SingleMethodName == null || _commandLineOptions.SingleMethodTypeName == null)
            {
                throw new CommandLineException(SR.TypeAndMethodNameNeeded);
            }

            TypeDesc owningType = FindType(context, _commandLineOptions.SingleMethodTypeName);

            // TODO: allow specifying signature to distinguish overloads
            MethodDesc method          = null;
            bool       printMethodList = false;
            int        curIndex        = 0;

            foreach (var searchMethod in owningType.GetMethods())
            {
                if (searchMethod.Name != _commandLineOptions.SingleMethodName)
                {
                    continue;
                }

                curIndex++;
                if (_commandLineOptions.SingleMethodIndex != 0)
                {
                    if (curIndex == _commandLineOptions.SingleMethodIndex)
                    {
                        method = searchMethod;
                        break;
                    }
                }
                else
                {
                    if (method == null)
                    {
                        method = searchMethod;
                    }
                    else
                    {
                        printMethodList = true;
                    }
                }
            }

            if (printMethodList)
            {
                curIndex = 0;
                foreach (var searchMethod in owningType.GetMethods())
                {
                    if (searchMethod.Name != _commandLineOptions.SingleMethodName)
                    {
                        continue;
                    }

                    curIndex++;
                    Console.WriteLine($"{curIndex} - {searchMethod}");
                }
                throw new CommandLineException(SR.SingleMethodIndexNeeded);
            }

            if (method == null)
            {
                throw new CommandLineException(string.Format(SR.MethodNotFoundOnType, _commandLineOptions.SingleMethodName, _commandLineOptions.SingleMethodTypeName));
            }

            if (method.HasInstantiation != (_commandLineOptions.SingleMethodGenericArg != null) ||
                (method.HasInstantiation && (method.Instantiation.Length != _commandLineOptions.SingleMethodGenericArg.Count)))
            {
                throw new CommandLineException(
                          string.Format(SR.GenericArgCountMismatch, method.Instantiation.Length, _commandLineOptions.SingleMethodName, _commandLineOptions.SingleMethodTypeName));
            }

            if (method.HasInstantiation)
            {
                List <TypeDesc> genericArguments = new List <TypeDesc>();
                foreach (var argString in _commandLineOptions.SingleMethodGenericArg)
                {
                    genericArguments.Add(FindType(context, argString));
                }
                method = method.MakeInstantiatedMethod(genericArguments.ToArray());
            }

            return(method);
        }
 protected CompilationModuleGroup(CompilerTypeSystemContext typeSystemContext)
 {
     _typeSystemContext = typeSystemContext;
 }
 public MetadataManager(CompilerTypeSystemContext context)
 {
     _typeSystemContext = context;
 }
Beispiel #33
0
        private TypeDesc FindType(CompilerTypeSystemContext context, string typeName)
        {
            ModuleDesc systemModule = context.SystemModule;

            TypeDesc foundType = systemModule.GetTypeByCustomAttributeTypeName(typeName);
            if (foundType == null)
                throw new CommandLineException($"Type '{typeName}' not found");

            TypeDesc classLibCanon = systemModule.GetType("System", "__Canon", false);
            TypeDesc classLibUniCanon = systemModule.GetType("System", "__UniversalCanon", false);

            return foundType.ReplaceTypesInConstructionOfType(
                new TypeDesc[] { classLibCanon, classLibUniCanon },
                new TypeDesc[] { context.CanonType, context.UniversalCanonType });
        }
Beispiel #34
0
 public ApplicationAssemblyRootProvider(CompilerTypeSystemContext context)
 {
     _context = context;
 }
Beispiel #35
0
 public MetadataManager(CompilationModuleGroup compilationModuleGroup, CompilerTypeSystemContext typeSystemContext)
 {
     _compilationModuleGroup = compilationModuleGroup;
     _typeSystemContext      = typeSystemContext;
 }
Beispiel #36
0
        private int Run(string[] args)
        {
            InitializeDefaultOptions();

            ArgumentSyntax syntax = ParseCommandLine(args);
            if (_help)
            {
                Help(syntax.GetHelpText());
                return 1;
            }

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

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

            //
            // Initialize type system context
            //

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

            var typeSystemContext = new CompilerTypeSystemContext(new TargetDetails(_targetArchitecture, _targetOS), genericsMode);
            typeSystemContext.InputFilePaths = _inputFilePaths;
            typeSystemContext.ReferenceFilePaths = _referenceFilePaths;

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

            //
            // Initialize compilation group and compilation roots
            //

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

            CompilationModuleGroup compilationGroup;
            List<ICompilationRootProvider> compilationRoots = new List<ICompilationRootProvider>();
            if (singleMethod != null)
            {
                // Compiling just a single method
                compilationGroup = new SingleMethodCompilationModuleGroup(singleMethod);
                compilationRoots.Add(new SingleMethodRootProvider(singleMethod));
            }
            else
            {
                // Either single file, or multifile library, or multifile consumption.
                EcmaModule entrypointModule = null;
                foreach (var inputFile in typeSystemContext.InputFilePaths)
                {
                    EcmaModule module = typeSystemContext.GetModuleFromPath(inputFile.Value);

                    if (module.PEReader.PEHeaders.IsExe)
                    {
                        if (entrypointModule != null)
                            throw new Exception("Multiple EXE modules");
                        entrypointModule = module;
                    }

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

                if (entrypointModule != null)
                {
                    compilationRoots.Add(new MainMethodRootProvider(entrypointModule));
                }

                if (_multiFile)
                {
                    List<EcmaModule> inputModules = new List<EcmaModule>();

                    foreach (var inputFile in typeSystemContext.InputFilePaths)
                    {
                        EcmaModule module = typeSystemContext.GetModuleFromPath(inputFile.Value);

                        if (entrypointModule == null)
                        {
                            // This is a multifile production build - we need to root all methods
                            compilationRoots.Add(new LibraryRootProvider(module));
                        }
                        inputModules.Add(module);
                    }

                    compilationGroup = new MultiFileCompilationModuleGroup(inputModules);
                }
                else
                {
                    if (entrypointModule == null)
                        throw new Exception("No entrypoint module");

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

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

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

                    compilationGroup = new SingleFileCompilationModuleGroup();
                }

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

            //
            // Compile
            //

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

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

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

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

            compilation.Compile(_outputFilePath);

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

            return 0;
        }
 public SingleMethodCompilationModuleGroup(CompilerTypeSystemContext typeSystemContext, MethodDesc method)
     : base(typeSystemContext)
 {
     _method = method;
 }
Beispiel #38
0
        private int Run(string[] args)
        {
            InitializeDefaultOptions();

            ArgumentSyntax syntax = ParseCommandLine(args);
            if (_help)
            {
                Help(syntax.GetHelpText());
                return 1;
            }

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

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

            //
            // Initialize type system context
            //

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

            var typeSystemContext = new CompilerTypeSystemContext(new TargetDetails(_targetArchitecture, _targetOS), genericsMode);
            typeSystemContext.InputFilePaths = _inputFilePaths;
            typeSystemContext.ReferenceFilePaths = _referenceFilePaths;

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

            //
            // Initialize compilation group
            //

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

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

            //
            // Compile
            //

            Compilation compilation = new Compilation(_options, typeSystemContext, compilationGroup);
            compilation.Log = _options.Verbose ? Console.Out : TextWriter.Null;
            compilation.Compile();

            return 0;
        }
Beispiel #39
0
        public ReadyToRunCompilerContext(TargetDetails details, SharedGenericsMode genericsMode, bool bubbleIncludesCorelib, CompilerTypeSystemContext oldTypeSystemContext = null)
            : base(details, genericsMode)
        {
            _r2rFieldLayoutAlgorithm          = new ReadyToRunMetadataFieldLayoutAlgorithm();
            _systemObjectFieldLayoutAlgorithm = new SystemObjectFieldLayoutAlgorithm(_r2rFieldLayoutAlgorithm);

            // Only the Arm64 JIT respects the OS rules for vector type abi currently
            _vectorFieldLayoutAlgorithm = new VectorFieldLayoutAlgorithm(_r2rFieldLayoutAlgorithm, (details.Architecture == TargetArchitecture.ARM64) ? true : bubbleIncludesCorelib);

            string matchingVectorType = "Unknown";

            if (details.MaximumSimdVectorLength == SimdVectorLength.Vector128Bit)
            {
                matchingVectorType = "Vector128`1";
            }
            else if (details.MaximumSimdVectorLength == SimdVectorLength.Vector256Bit)
            {
                matchingVectorType = "Vector256`1";
            }

            // No architecture has completely stable handling of Vector<T> in the abi (Arm64 may change to SVE)
            _vectorOfTFieldLayoutAlgorithm = new VectorOfTFieldLayoutAlgorithm(_r2rFieldLayoutAlgorithm, _vectorFieldLayoutAlgorithm, matchingVectorType, bubbleIncludesCorelib);

            // Int128 and UInt128 should be ABI stable on all currently supported platforms
            _int128FieldLayoutAlgorithm = new Int128FieldLayoutAlgorithm(_r2rFieldLayoutAlgorithm);

            if (oldTypeSystemContext != null)
            {
                InheritOpenModules(oldTypeSystemContext);
            }
        }
Beispiel #40
0
        private MethodDesc CheckAndParseSingleMethodModeArguments(CompilerTypeSystemContext context)
        {
            if (_singleMethodName == null && _singleMethodTypeName == null && _singleMethodGenericArgs == null)
                return null;

            if (_singleMethodName == null || _singleMethodTypeName == null)
                throw new CommandLineException("Both method name and type name are required parameters for single method mode");

            TypeDesc owningType = FindType(context, _singleMethodTypeName);

            // TODO: allow specifying signature to distinguish overloads
            MethodDesc method = owningType.GetMethod(_singleMethodName, null);
            if (method == null)
                throw new CommandLineException($"Method '{_singleMethodName}' not found in '{_singleMethodTypeName}'");

            if (method.HasInstantiation != (_singleMethodGenericArgs != null) ||
                (method.HasInstantiation && (method.Instantiation.Length != _singleMethodGenericArgs.Count)))
            {
                throw new CommandLineException(
                    $"Expected {method.Instantiation.Length} generic arguments for method '{_singleMethodName}' on type '{_singleMethodTypeName}'");
            }

            if (method.HasInstantiation)
            {
                List<TypeDesc> genericArguments = new List<TypeDesc>();
                foreach (var argString in _singleMethodGenericArgs)
                    genericArguments.Add(FindType(context, argString));
                method = method.MakeInstantiatedMethod(genericArguments.ToArray());
            }

            return method;
        }
 private static InteropStubManager NewEmptyInteropStubManager(CompilerTypeSystemContext context, CompilationModuleGroup compilationModuleGroup)
 {
     // On Project N, the compiler doesn't generate the interop code on the fly
     return(new EmptyInteropStubManager(compilationModuleGroup, context, null));
 }
Beispiel #42
0
        private int Run(string[] args)
        {
            ParseCommandLine(args);

            if (_help)
            {
                Help();
                return 1;
            }

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

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

            TargetOS targetOS;
#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
                throw new NotImplementedException();
#else
            targetOS = TargetOS.Windows;
#endif

            _compilerTypeSystemContext = new CompilerTypeSystemContext(new TargetDetails(TargetArchitecture.X64, targetOS));
            _compilerTypeSystemContext.InputFilePaths = _inputFilePaths;
            _compilerTypeSystemContext.ReferenceFilePaths = _referenceFilePaths;

            _compilerTypeSystemContext.SetSystemModule(_compilerTypeSystemContext.GetModuleForSimpleName(_systemModuleName));

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

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

            ArgumentSyntax syntax = ParseCommandLine(args);

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

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

            //
            // Set target Architecture and OS
            //
            if (_targetArchitectureStr != null)
            {
                if (_targetArchitectureStr.Equals("x86", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.X86;
                }
                else if (_targetArchitectureStr.Equals("x64", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.X64;
                }
                else if (_targetArchitectureStr.Equals("arm", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.ARM;
                }
                else if (_targetArchitectureStr.Equals("armel", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.ARM;
                }
                else if (_targetArchitectureStr.Equals("arm64", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.ARM64;
                }
                else if (_targetArchitectureStr.Equals("wasm", StringComparison.OrdinalIgnoreCase))
                {
                    _targetArchitecture = TargetArchitecture.Wasm32;
                    _isWasmCodegen      = true;
                }
                else
                {
                    throw new CommandLineException("Target architecture is not supported");
                }
            }
            if (_targetOSStr != null)
            {
                if (_targetOSStr.Equals("windows", StringComparison.OrdinalIgnoreCase))
                {
                    _targetOS = TargetOS.Windows;
                }
                else if (_targetOSStr.Equals("linux", StringComparison.OrdinalIgnoreCase))
                {
                    _targetOS = TargetOS.Linux;
                }
                else if (_targetOSStr.Equals("osx", StringComparison.OrdinalIgnoreCase))
                {
                    _targetOS = TargetOS.OSX;
                }
                else
                {
                    throw new CommandLineException("Target OS is not supported");
                }
            }

            if (_isWasmCodegen)
            {
                _targetArchitecture = TargetArchitecture.Wasm32;
            }

            InstructionSetSupportBuilder instructionSetSupportBuilder = new InstructionSetSupportBuilder(_targetArchitecture);

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

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

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

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

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

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

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

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

            InstructionSetSupportBuilder optimisticInstructionSetSupportBuilder = new InstructionSetSupportBuilder(_targetArchitecture);

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

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

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

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

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

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

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

            //
            // Initialize type system context
            //

            SharedGenericsMode genericsMode = SharedGenericsMode.CanonicalReferenceTypes;

            var simdVectorLength = (_isCppCodegen || _isWasmCodegen) ? SimdVectorLength.None : instructionSetSupport.GetVectorTSimdVector();
            var targetAbi        = _isCppCodegen ? TargetAbi.CppCodegen : TargetAbi.CoreRT;
            var targetDetails    = new TargetDetails(_targetArchitecture, _targetOS, targetAbi, simdVectorLength);
            CompilerTypeSystemContext typeSystemContext =
                new CompilerTypeSystemContext(targetDetails, genericsMode, supportsReflection ? DelegateFeature.All : 0);

            //
            // TODO: To support our pre-compiled test tree, allow input files that aren't managed assemblies since
            // some tests contain a mixture of both managed and native binaries.
            //
            // See: https://github.com/dotnet/corert/issues/2785
            //
            // When we undo this this hack, replace this foreach with
            //  typeSystemContext.InputFilePaths = _inputFilePaths;
            //
            Dictionary <string, string> inputFilePaths = new Dictionary <string, string>();

            foreach (var inputFile in _inputFilePaths)
            {
                try
                {
                    var module = typeSystemContext.GetModuleFromPath(inputFile.Value);
                    inputFilePaths.Add(inputFile.Key, inputFile.Value);
                }
                catch (TypeSystemException.BadImageFormatException)
                {
                    // Keep calm and carry on.
                }
            }

            typeSystemContext.InputFilePaths     = inputFilePaths;
            typeSystemContext.ReferenceFilePaths = _referenceFilePaths;
            if (!typeSystemContext.InputFilePaths.ContainsKey(_systemModuleName) &&
                !typeSystemContext.ReferenceFilePaths.ContainsKey(_systemModuleName))
            {
                throw new CommandLineException($"System module {_systemModuleName} does not exists. Make sure that you specify --systemmodule");
            }

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

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

            //
            // Initialize compilation group and compilation roots
            //

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

            CompilationModuleGroup          compilationGroup;
            List <ICompilationRootProvider> compilationRoots = new List <ICompilationRootProvider>();

            if (singleMethod != null)
            {
                // Compiling just a single method
                compilationGroup = new SingleMethodCompilationModuleGroup(singleMethod);
                compilationRoots.Add(new SingleMethodRootProvider(singleMethod));
            }
            else
            {
                // Either single file, or multifile library, or multifile consumption.
                EcmaModule entrypointModule          = null;
                bool       systemModuleIsInputModule = false;
                foreach (var inputFile in typeSystemContext.InputFilePaths)
                {
                    EcmaModule module = typeSystemContext.GetModuleFromPath(inputFile.Value);

                    if (module.PEReader.PEHeaders.IsExe)
                    {
                        if (entrypointModule != null)
                        {
                            throw new Exception("Multiple EXE modules");
                        }
                        entrypointModule = module;
                    }

                    if (module == typeSystemContext.SystemModule)
                    {
                        systemModuleIsInputModule = true;
                    }

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

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

                if (_multiFile)
                {
                    List <EcmaModule> inputModules = new List <EcmaModule>();

                    foreach (var inputFile in typeSystemContext.InputFilePaths)
                    {
                        EcmaModule module = typeSystemContext.GetModuleFromPath(inputFile.Value);

                        if (entrypointModule == null)
                        {
                            // This is a multifile production build - we need to root all methods
                            compilationRoots.Add(new LibraryRootProvider(module));
                        }
                        inputModules.Add(module);
                    }

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

                    if (!systemModuleIsInputModule)
                    {
                        compilationRoots.Add(new ExportedMethodsRootProvider((EcmaModule)typeSystemContext.SystemModule));
                    }
                    compilationGroup = new SingleFileCompilationModuleGroup();
                }

                if (_nativeLib)
                {
                    // Set owning module of generated native library startup method to compiler generated module,
                    // to ensure the startup method is included in the object file during multimodule mode build
                    compilationRoots.Add(new NativeLibraryInitializerRootProvider(typeSystemContext.GeneratedAssembly, CreateInitializerList(typeSystemContext)));
                    compilationRoots.Add(new RuntimeConfigurationRootProvider(_runtimeOptions));
                    compilationRoots.Add(new ExpectedIsaFeaturesRootProvider(instructionSetSupport));
                }

                if (_rdXmlFilePaths.Count > 0)
                {
                    Console.WriteLine("Warning: RD.XML processing will change before release (https://github.com/dotnet/corert/issues/5001)");
                }
                foreach (var rdXmlFilePath in _rdXmlFilePaths)
                {
                    compilationRoots.Add(new RdXmlRootProvider(typeSystemContext, rdXmlFilePath));
                }
            }

            //
            // Compile
            //

            CompilationBuilder builder;

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

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

            builder.UseCompilationUnitPrefix(compilationUnitPrefix);

            PInvokeILEmitterConfiguration pinvokePolicy;

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

            RemovedFeature removedFeatures = 0;

            foreach (string feature in _removedFeatures)
            {
                if (feature == "EventSource")
                {
                    removedFeatures |= RemovedFeature.Etw;
                }
                else if (feature == "FrameworkStrings")
                {
                    removedFeatures |= RemovedFeature.FrameworkResources;
                }
                else if (feature == "Globalization")
                {
                    removedFeatures |= RemovedFeature.Globalization;
                }
                else if (feature == "Comparers")
                {
                    removedFeatures |= RemovedFeature.Comparers;
                }
                else if (feature == "SerializationGuard")
                {
                    removedFeatures |= RemovedFeature.SerializationGuard;
                }
                else if (feature == "XmlNonFileStream")
                {
                    removedFeatures |= RemovedFeature.XmlDownloadNonFileStream;
                }
            }

            ILProvider ilProvider = new CoreRTILProvider();

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

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

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

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

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

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

            DynamicInvokeThunkGenerationPolicy invokeThunkGenerationPolicy = new DefaultDynamicInvokeThunkGenerationPolicy();

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

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

            // Unless explicitly opted in at the command line, we enable scanner for retail builds by default.
            // We don't do this for CppCodegen and Wasm, because those codegens are behind.
            // We also don't do this for multifile because scanner doesn't simulate inlining (this would be
            // fixable by using a CompilationGroup for the scanner that has a bigger worldview, but
            // let's cross that bridge when we get there).
            bool useScanner = _useScanner ||
                              (_optimizationMode != OptimizationMode.None && !_isCppCodegen && !_isWasmCodegen && !_multiFile);

            useScanner &= !_noScanner;

            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" || method.Name == "ThrowArgumentOutOfRangeException");
                DiffCompilationResults(ref scanningFail, compilationResults.ConstructedEETypes, scanResults.ConstructedEETypes,
                                       "EETypes", "compiled", "scanned", type => !(type.GetTypeDefinition() is EcmaType));

                // If optimizations are enabled, the results will for sure not match in the other direction due to inlining, etc.
                // But there's at least some value in checking the scanner doesn't expand the universe too much in debug.
                if (_optimizationMode == OptimizationMode.None)
                {
                    // Check that methods and types scanned are a subset of methods and types compiled

                    // If we find diffs here, they're not critical, but still might be causing a Size on Disk regression.
                    bool dummy = false;

                    // We additionally skip methods in SIMD module because there's just too many intrisics to handle and IL scanner
                    // doesn't expand them. They would show up as noisy diffs.
                    DiffCompilationResults(ref dummy, scanResults.CompiledMethodBodies, compilationResults.CompiledMethodBodies,
                                           "Methods", "scanned", "compiled", method => !(method.GetTypicalMethodDefinition() is EcmaMethod) || method.OwningType.IsIntrinsic);
                    DiffCompilationResults(ref dummy, scanResults.ConstructedEETypes, compilationResults.ConstructedEETypes,
                                           "EETypes", "scanned", "compiled", type => !(type.GetTypeDefinition() is EcmaType));
                }

                if (scanningFail)
                {
                    throw new Exception("Scanning failure");
                }
            }

            if (debugInfoProvider is IDisposable)
            {
                ((IDisposable)debugInfoProvider).Dispose();
            }

            return(0);
        }
Beispiel #44
0
 public CppCodegenCompilationBuilder(CompilerTypeSystemContext context, CompilationModuleGroup group)
     : base(context, group, new CoreRTNameMangler(new CppNodeMangler(), true))
 {
 }
Beispiel #45
0
 public MetadataManager(CompilerTypeSystemContext typeSystemContext, MetadataBlockingPolicy blockingPolicy)
 {
     _typeSystemContext = typeSystemContext;
     _blockingPolicy    = blockingPolicy;
 }
 public SingleMethodCompilationModuleGroup(CompilerTypeSystemContext typeSystemContext, MethodDesc method)
     : base(typeSystemContext)
 {
     _method = method;
 }
Beispiel #47
0
        private TypeDesc FindType(CompilerTypeSystemContext context, string typeName)
        {
            TypeDesc foundType = context.SystemModule.GetTypeByCustomAttributeTypeName(typeName);
            if (foundType == null)
                throw new CommandLineException($"Type '{typeName}' not found");

            return foundType;
        }