Esempio n. 1
0
        // Writes a list of lines to stderr, writing only a limited number of lines if there are too many of them.
        protected void WriteLimitedOutput(string first, IEnumerable <string> lines, List <Exception> exceptions)
        {
            if ((first == null || first.Length == 0) && !lines.Any())
            {
                return;
            }

            if (Driver.Verbosity < 6 && lines.Count() > 1000)
            {
                lines = lines.Take(1000);                  // Limit the output so that we don't overload VSfM.
                exceptions.Add(ErrorHelper.CreateWarning(5108, "The compiler output is too long, it's been limited to 1000 lines."));
            }

            // Construct the entire message before writing anything, so that there's a better chance the message isn't
            // mixed up with output from other threads.
            var sb = new StringBuilder();

            if (first != null && first.Length > 0)
            {
                sb.AppendLine(first);
            }
            foreach (var line in lines)
            {
                sb.AppendLine(line);
            }
            sb.Length -= Environment.NewLine.Length;             // strip off the last newline, since we're adding it in the next line
            Console.Error.WriteLine(sb);
        }
Esempio n. 2
0
        public virtual AssemblyDefinition Load(string fileName)
        {
            if (!File.Exists(fileName))
            {
                return(null);
            }

            AssemblyDefinition assembly;
            var name = Path.GetFileNameWithoutExtension(fileName);

            if (cache.TryGetValue(name, out assembly))
            {
                return(assembly);
            }

            try {
                fileName = Target.GetRealPath(fileName);

                // Check the architecture-specific directory
                if (Path.GetDirectoryName(fileName) == FrameworkDirectory && !string.IsNullOrEmpty(ArchDirectory))
                {
                    var archName = Path.Combine(ArchDirectory, Path.GetFileName(fileName));
                    if (File.Exists(archName))
                    {
                        fileName = archName;
                    }
                }

                var parameters = CreateDefaultReaderParameters(fileName);
                try {
                    assembly = ModuleDefinition.ReadModule(fileName, parameters).Assembly;
                    params_cache [assembly.Name.ToString()] = parameters;
                    if (!assembly.MainModule.HasSymbols)
                    {
                        // We Cecil didn't load symbols, but there's a pdb, then something went wrong loading it (maybe an old-style pdb?).
                        // Warn about this.
                        var pdb = Path.ChangeExtension(fileName, "pdb");
                        if (File.Exists(pdb))
                        {
                            ErrorHelper.Show(ErrorHelper.CreateWarning(178, Errors.MX0178, fileName));
                        }
                    }
                }
                catch (SymbolsNotMatchingException) {
                    parameters.ReadSymbols          = false;
                    parameters.SymbolReaderProvider = null;
                    assembly = ModuleDefinition.ReadModule(fileName, parameters).Assembly;
                    // only report the warning (on symbols) if we can actually load the assembly itself (otherwise it's more confusing than helpful)
                    ErrorHelper.Show(ErrorHelper.CreateWarning(129, Errors.MX0129, fileName));
                }
            }
            catch (Exception e) {
                throw new ProductException(9, true, e, Errors.MX0009, fileName);
            }
            return(CacheAssembly(assembly));
        }
Esempio n. 3
0
        void ParseOption(ApplePlatform platform, string option, List <ProductException> messages)
        {
            bool   enabled;
            string opt;

            switch (option [0])
            {
            case '-':
                enabled = false;
                opt     = option.Substring(1);
                break;

            case '+':
                enabled = true;
                opt     = option.Substring(1);
                break;

            default:
                opt     = option;
                enabled = true;
                break;
            }

            if (opt == "all")
            {
                for (int i = 0; i < values.Length; i++)
                {
                    var valid = valid_platforms [i];
                    if (Array.IndexOf(valid, platform) < 0)
                    {
                        continue;                         // Don't apply 'all' to optimizations that aren't valid for the current platform
                    }
                    values [i] = enabled;
                }
            }
            else
            {
                var found = false;
                for (int i = 0; i < values.Length; i++)
                {
                    if (opt_names [i] != opt)
                    {
                        continue;
                    }
                    found      = true;
                    values [i] = enabled;
                }
                if (!found)
                {
                    messages.Add(ErrorHelper.CreateWarning(132, Errors.MX0132, opt, string.Join(", ", Enum.GetValues(typeof(Opt)).Cast <Opt> ().Where(o => Array.IndexOf(valid_platforms [(int)o], platform) >= 0).Select(o => opt_names [(int)o]))));
                }
            }
        }
Esempio n. 4
0
        public virtual AssemblyDefinition Load(string fileName)
        {
            if (!File.Exists(fileName))
            {
                return(null);
            }

            AssemblyDefinition assembly;
            var name = Path.GetFileNameWithoutExtension(fileName);

            if (cache.TryGetValue(name, out assembly))
            {
                return(assembly);
            }

            try {
                fileName = Target.GetRealPath(fileName);

                // Check the architecture-specific directory
                if (Path.GetDirectoryName(fileName) == FrameworkDirectory && !string.IsNullOrEmpty(ArchDirectory))
                {
                    var archName = Path.Combine(ArchDirectory, Path.GetFileName(fileName));
                    if (File.Exists(archName))
                    {
                        fileName = archName;
                    }
                }

                var parameters = CreateDefaultReaderParameters(fileName);
                try {
                    assembly = ModuleDefinition.ReadModule(fileName, parameters).Assembly;
                    params_cache [assembly.Name.ToString()] = parameters;
                }
                catch (InvalidOperationException e) {
                    // cecil use the default message so it's not very helpful to detect the root cause
                    if (!e.TargetSite.ToString().Contains("Void ReadSymbols(Mono.Cecil.Cil.ISymbolReader)"))
                    {
                        throw;
                    }
                    parameters.ReadSymbols          = false;
                    parameters.SymbolReaderProvider = null;
                    assembly = ModuleDefinition.ReadModule(fileName, parameters).Assembly;
                    // only report the warning (on symbols) if we can actually load the assembly itself (otherwise it's more confusing than helpful)
                    ErrorHelper.Show(ErrorHelper.CreateWarning(129, $"Debugging symbol file for '{fileName}' does not match the assembly and is ignored."));
                }
            }
            catch (Exception e) {
                throw new ProductException(9, true, e, "Error while loading assemblies: {0}", fileName);
            }
            cache.Add(name, assembly);
            return(assembly);
        }
        public virtual AssemblyDefinition Load(string fileName)
        {
            if (!File.Exists(fileName))
            {
                return(null);
            }

            AssemblyDefinition assembly;
            var name = Path.GetFileNameWithoutExtension(fileName);

            if (cache.TryGetValue(name, out assembly))
            {
                return(assembly);
            }

            try {
                fileName = Target.GetRealPath(fileName);

                // Check the architecture-specific directory
                if (Path.GetDirectoryName(fileName) == FrameworkDirectory && !string.IsNullOrEmpty(ArchDirectory))
                {
                    var archName = Path.Combine(ArchDirectory, Path.GetFileName(fileName));
                    if (File.Exists(archName))
                    {
                        fileName = archName;
                    }
                }

                var parameters = CreateDefaultReaderParameters(fileName);
                try {
                    assembly = ModuleDefinition.ReadModule(fileName, parameters).Assembly;
                    params_cache [assembly.Name.ToString()] = parameters;
                }
                catch (SymbolsNotMatchingException) {
                    parameters.ReadSymbols          = false;
                    parameters.SymbolReaderProvider = null;
                    assembly = ModuleDefinition.ReadModule(fileName, parameters).Assembly;
                    // only report the warning (on symbols) if we can actually load the assembly itself (otherwise it's more confusing than helpful)
                    ErrorHelper.Show(ErrorHelper.CreateWarning(129, Errors.MX0129, fileName));
                }
            }
            catch (Exception e) {
                throw new ProductException(9, true, e, Errors.MX0009, fileName);
            }
            cache.Add(name, assembly);
            return(assembly);
        }
Esempio n. 6
0
        public void RunRegistrar()
        {
            // The static registrar.
            if (Registrar != RegistrarMode.Static)
            {
                throw new PlatformException(67, "Invalid registrar: {0}", Registrar);                  // this is only called during our own build
            }
            if (RootAssemblies.Count < 1)
            {
                throw ErrorHelper.CreateError(130, "No root assemblies found. You should provide at least one root assembly.");
            }

            var registrar_m        = RegistrarOutputLibrary;
            var RootAssembly       = RootAssemblies [0];
            var resolvedAssemblies = new Dictionary <string, AssemblyDefinition> ();
            var resolver           = new PlatformResolver()
            {
                FrameworkDirectory = Driver.GetPlatformFrameworkDirectory(this),
                RootDirectory      = Path.GetDirectoryName(RootAssembly),
#if MMP
                CommandLineAssemblies = RootAssemblies,
#endif
            };

            if (Platform == ApplePlatform.iOS || Platform == ApplePlatform.MacOSX)
            {
                if (Is32Build)
                {
                    resolver.ArchDirectory = Driver.GetArch32Directory(this);
                }
                else
                {
                    resolver.ArchDirectory = Driver.GetArch64Directory(this);
                }
            }

            var ps = new ReaderParameters();

            ps.AssemblyResolver = resolver;
            resolvedAssemblies.Add("mscorlib", ps.AssemblyResolver.Resolve(AssemblyNameReference.Parse("mscorlib"), new ReaderParameters()));

            var  productAssembly      = Driver.GetProductAssembly(this);
            bool foundProductAssembly = false;

            foreach (var asm in RootAssemblies)
            {
                var rootName = Path.GetFileNameWithoutExtension(asm);
                if (rootName == productAssembly)
                {
                    foundProductAssembly = true;
                }

                try {
                    AssemblyDefinition lastAssembly = ps.AssemblyResolver.Resolve(AssemblyNameReference.Parse(rootName), new ReaderParameters());
                    if (lastAssembly == null)
                    {
                        ErrorHelper.CreateWarning(7, "The root assembly '{0}' does not exist", rootName);
                        continue;
                    }

                    if (resolvedAssemblies.TryGetValue(rootName, out var previousAssembly))
                    {
                        if (lastAssembly.MainModule.RuntimeVersion != previousAssembly.MainModule.RuntimeVersion)
                        {
                            Driver.Log(2, "Attemping to load an assembly another time {0} (previous {1})", lastAssembly.FullName, previousAssembly.FullName);
                        }
                        continue;
                    }

                    resolvedAssemblies.Add(rootName, lastAssembly);
                    Driver.Log(3, "Loaded {0}", lastAssembly.MainModule.FileName);
                } catch (Exception ex) {
                    ErrorHelper.Warning(9, ex, "Error while loading assemblies: {0}: {1}", rootName, ex.Message);
                    continue;
                }
            }

            if (!foundProductAssembly)
            {
                throw ErrorHelper.CreateError(131, "Product assembly '{0}' not found in assembly list: '{1}'", productAssembly, string.Join("', '", RootAssemblies.ToArray()));
            }

#if MONOTOUCH
            BuildTarget = BuildTarget.Simulator;
#endif
            var registrar = new Registrar.StaticRegistrar(this);
            if (RootAssemblies.Count == 1)
            {
                registrar.GenerateSingleAssembly(resolvedAssemblies.Values, Path.ChangeExtension(registrar_m, "h"), registrar_m, Path.GetFileNameWithoutExtension(RootAssembly));
            }
            else
            {
                registrar.Generate(resolvedAssemblies.Values, Path.ChangeExtension(registrar_m, "h"), registrar_m);
            }
        }
Esempio n. 7
0
        protected override async Task ExecuteAsync()
        {
            // always show the native linker warnings since many of them turn out to be very important
            // and very hard to diagnose otherwise when hidden from the build output. Ref: bug #2430
            var linker_errors = new List <Exception> ();
            var output        = new StringBuilder();
            var code          = await Driver.RunCommandAsync(Target.App.CompilerPath, CompilerFlags.ToString(), null, output);

            Application.ProcessNativeLinkerOutput(Target, output.ToString(), CompilerFlags.AllLibraries, linker_errors, code != 0);

            if (code != 0)
            {
                // if the build failed - it could be because of missing frameworks / libraries we identified earlier
                foreach (var assembly in Target.Assemblies)
                {
                    if (assembly.UnresolvedModuleReferences == null)
                    {
                        continue;
                    }

                    foreach (var mr in assembly.UnresolvedModuleReferences)
                    {
                        // TODO: add more diagnose information on the warnings
                        var name = Path.GetFileNameWithoutExtension(mr.Name);
                        linker_errors.Add(new MonoTouchException(5215, false, "References to '{0}' might require additional -framework=XXX or -lXXX instructions to the native linker", name));
                    }
                }
                // mtouch does not validate extra parameters given to GCC when linking (--gcc_flags)
                if (!String.IsNullOrEmpty(Target.App.UserGccFlags))
                {
                    linker_errors.Add(new MonoTouchException(5201, true, "Native linking failed. Please review the build log and the user flags provided to gcc: {0}", Target.App.UserGccFlags));
                }
                linker_errors.Add(new MonoTouchException(5202, true, "Native linking failed. Please review the build log.", Target.App.UserGccFlags));

                if (code == 255)
                {
                    // check command length
                    // getconf ARG_MAX
                    StringBuilder getconf_output = new StringBuilder();
                    if (Driver.RunCommand("getconf", "ARG_MAX", output: getconf_output, suppressPrintOnErrors: true) == 0)
                    {
                        int arg_max;
                        if (int.TryParse(getconf_output.ToString().Trim(' ', '\t', '\n', '\r'), out arg_max))
                        {
                            var cmd_length = Target.App.CompilerPath.Length + 1 + CompilerFlags.ToString().Length;
                            if (cmd_length > arg_max)
                            {
                                linker_errors.Add(ErrorHelper.CreateWarning(5217, $"Native linking possibly failed because the linker command line was too long ({cmd_length} characters)."));
                            }
                            else
                            {
                                Driver.Log(3, $"Linker failure is probably not due to command-line length (actual: {cmd_length} limit: {arg_max}");
                            }
                        }
                        else
                        {
                            Driver.Log(3, "Failed to parse 'getconf ARG_MAX' output: {0}", getconf_output);
                        }
                    }
                    else
                    {
                        Driver.Log(3, "Failed to execute 'getconf ARG_MAX'\n{0}", getconf_output);
                    }
                }
            }
            ErrorHelper.Show(linker_errors);

            // the native linker can prefer private (and existing) over public (but non-existing) framework when weak_framework are used
            // on an iOS target version where the framework does not exists, e.g. targeting iOS6 for JavaScriptCore added in iOS7 results in
            // /System/Library/PrivateFrameworks/JavaScriptCore.framework/JavaScriptCore instead of
            // /System/Library/Frameworks/JavaScriptCore.framework/JavaScriptCore
            // more details in https://bugzilla.xamarin.com/show_bug.cgi?id=31036
            if (CompilerFlags.WeakFrameworks.Count > 0)
            {
                Target.AdjustDylibs(OutputFile);
            }
            Driver.Watch("Native Link", 1);
        }
Esempio n. 8
0
        public void RunRegistrar()
        {
            // The static registrar.
            if (Registrar != RegistrarMode.Static)
            {
                throw new ProductException(67, Errors.MT0067, Registrar);                  // this is only called during our own build
            }
            if (RootAssemblies.Count < 1)
            {
                throw ErrorHelper.CreateError(130, Errors.MX0130);
            }

            var registrar_m        = RegistrarOutputLibrary;
            var RootAssembly       = RootAssemblies [0];
            var resolvedAssemblies = new Dictionary <string, AssemblyDefinition> ();
            var resolver           = new PlatformResolver()
            {
                RootDirectory = Path.GetDirectoryName(RootAssembly),
#if MMP
                CommandLineAssemblies = RootAssemblies,
#endif
            };

            if (Platform == ApplePlatform.iOS && !Driver.IsDotNet)
            {
                if (Is32Build)
                {
                    resolver.ArchDirectory = Driver.GetArch32Directory(this);
                }
                else
                {
                    resolver.ArchDirectory = Driver.GetArch64Directory(this);
                }
            }

            var ps = new ReaderParameters();

            ps.AssemblyResolver = resolver;
            foreach (var reference in References)
            {
                var r = resolver.Load(reference);
                if (r == null)
                {
                    throw ErrorHelper.CreateError(2002, Errors.MT2002, reference);
                }
            }

            var  productAssembly      = Driver.GetProductAssembly(this);
            bool foundProductAssembly = false;

            foreach (var asm in RootAssemblies)
            {
                var rootName = Path.GetFileNameWithoutExtension(asm);
                if (rootName == productAssembly)
                {
                    foundProductAssembly = true;
                }

                try {
                    AssemblyDefinition lastAssembly = ps.AssemblyResolver.Resolve(AssemblyNameReference.Parse(rootName), new ReaderParameters());
                    if (lastAssembly == null)
                    {
                        ErrorHelper.CreateWarning(7, Errors.MX0007, rootName);
                        continue;
                    }

                    if (resolvedAssemblies.TryGetValue(rootName, out var previousAssembly))
                    {
                        if (lastAssembly.MainModule.RuntimeVersion != previousAssembly.MainModule.RuntimeVersion)
                        {
                            Driver.Log(2, "Attemping to load an assembly another time {0} (previous {1})", lastAssembly.FullName, previousAssembly.FullName);
                        }
                        continue;
                    }

                    resolvedAssemblies.Add(rootName, lastAssembly);
                    Driver.Log(3, "Loaded {0}", lastAssembly.MainModule.FileName);
                } catch (Exception ex) {
                    ErrorHelper.Warning(9, ex, Errors.MX0009, $"{rootName}: {ex.Message}");
                    continue;
                }
            }

            if (!foundProductAssembly)
            {
                throw ErrorHelper.CreateError(131, Errors.MX0131, productAssembly, string.Join("', '", RootAssemblies.ToArray()));
            }

#if MONOTOUCH
            if (SelectAbis(Abis, Abi.SimulatorArchMask).Count > 0)
            {
                BuildTarget = BuildTarget.Simulator;
            }
            else if (SelectAbis(Abis, Abi.DeviceArchMask).Count > 0)
            {
                BuildTarget = BuildTarget.Device;
            }
            else
            {
                throw ErrorHelper.CreateError(99, Errors.MX0099, "No valid ABI");
            }
#endif
            var registrar = new Registrar.StaticRegistrar(this);
            if (RootAssemblies.Count == 1)
            {
                registrar.GenerateSingleAssembly(resolver, resolvedAssemblies.Values, Path.ChangeExtension(registrar_m, "h"), registrar_m, Path.GetFileNameWithoutExtension(RootAssembly));
            }
            else
            {
                registrar.Generate(resolvedAssemblies.Values, Path.ChangeExtension(registrar_m, "h"), registrar_m);
            }
        }
Esempio n. 9
0
        public void Initialize(Application app, out List <ProductException> messages)
        {
            messages = new List <ProductException> ();
            // warn if the user asked to optimize something when the optimization can't be applied
            for (int i = 0; i < values.Length; i++)
            {
                if (!values [i].HasValue)
                {
                    continue;
                }

                // check if the optimization is valid for the current platform
                var valid = valid_platforms [i];
                if (Array.IndexOf(valid, app.Platform) < 0)
                {
                    messages.Add(ErrorHelper.CreateWarning(2003, Errors.MT2003_C, opt_names [i], string.Join(", ", valid.Select(v => v.AsString()))));
                    values [i] = false;
                    continue;
                }

                switch ((Opt)i)
                {
                case Opt.StaticBlockToDelegateLookup:
                    if (app.Registrar != RegistrarMode.Static)
                    {
                        messages.Add(ErrorHelper.CreateWarning(2003, Errors.MT2003, (values [i].Value ? "" : "-"), opt_names [i]));
                        values [i] = false;
                        continue;
                    }
                    break;                     // does not require the linker

                case Opt.TrimArchitectures:
                    break;                     // Does not require linker

                case Opt.RegisterProtocols:
                case Opt.RemoveDynamicRegistrar:
                    if (app.Registrar != RegistrarMode.Static)
                    {
                        messages.Add(ErrorHelper.CreateWarning(2003, Errors.MT2003, (values[i].Value ? "" : "-"), opt_names[i]));
                        values [i] = false;
                        continue;
                    }
                    goto default;                     // also requires the linker

                default:
                    if (app.LinkMode == LinkMode.None)
                    {
                        messages.Add(ErrorHelper.CreateWarning(2003, Errors.MT2003_B, (values [i].Value ? "" : "-"), opt_names [i]));
                        values [i] = false;
                    }
                    break;
                }
            }

            // by default we keep the code to ensure we're executing on the UI thread (for UI code) for debug builds
            // but this can be overridden to either (a) remove it from debug builds or (b) keep it in release builds
            if (!RemoveUIThreadChecks.HasValue)
            {
                RemoveUIThreadChecks = !app.EnableDebug;
            }

            // By default we always eliminate dead code.
            if (!DeadCodeElimination.HasValue)
            {
                DeadCodeElimination = true;
            }

            if (!InlineIsDirectBinding.HasValue)
            {
                if (app.Platform != ApplePlatform.MacOSX)
                {
                    // By default we always inline calls to NSObject.IsDirectBinding
                    // unless the interpreter is enabled (we can't predict if code will be subclassed)
                    InlineIsDirectBinding = !app.UseInterpreter;
                }
                else
                {
                    // NSObject.IsDirectBinding is not a safe optimization to apply to XM apps,
                    // because there may be additional code/assemblies we don't know about at build time.
                    InlineIsDirectBinding = false;
                }
            }

            // The default behavior for InlineIntPtrSize depends on the assembly being linked,
            // which means we can't set it to a global constant. It's handled in the OptimizeGeneratedCodeSubStep directly.

            if (app.Platform != ApplePlatform.MacOSX)
            {
                // By default we always inline calls to Runtime.Arch
                if (!InlineRuntimeArch.HasValue)
                {
                    InlineRuntimeArch = true;
                }
            }

            // We try to optimize calls to BlockLiteral.SetupBlock if the static registrar is enabled
            if (!OptimizeBlockLiteralSetupBlock.HasValue)
            {
                OptimizeBlockLiteralSetupBlock = app.Registrar == RegistrarMode.Static;
            }

            // We will register protocols if the static registrar is enabled and loading assemblies is not possible
            if (!RegisterProtocols.HasValue)
            {
                if (app.Platform != ApplePlatform.MacOSX)
                {
                    RegisterProtocols = (app.Registrar == RegistrarMode.Static) && !app.UseInterpreter;
                }
                else
                {
                    RegisterProtocols = false;
                }
            }
            else if (app.Registrar != RegistrarMode.Static && RegisterProtocols == true)
            {
                RegisterProtocols = false;                 // we've already shown a warning for this.
            }

            // By default we always inline calls to Runtime.DynamicRegistrationSupported
            if (!InlineDynamicRegistrationSupported.HasValue)
            {
                InlineDynamicRegistrationSupported = true;
            }

            // By default always enable static block-to-delegate lookup (it won't make a difference unless the static registrar is used though)
            if (!StaticBlockToDelegateLookup.HasValue)
            {
                StaticBlockToDelegateLookup = true;
            }

            if (!RemoveDynamicRegistrar.HasValue)
            {
                if (InlineDynamicRegistrationSupported != true)
                {
                    // Can't remove the dynamic registrar unless also inlining Runtime.DynamicRegistrationSupported
                    RemoveDynamicRegistrar = false;
                }
                else if (StaticBlockToDelegateLookup != true)
                {
                    // Can't remove the dynamic registrar unless also generating static lookup of block-to-delegates in the static registrar.
                    RemoveDynamicRegistrar = false;
                }
                else if (app.Registrar != RegistrarMode.Static || app.LinkMode == LinkMode.None)
                {
                    // Both the linker and the static registrar are also required
                    RemoveDynamicRegistrar = false;
                }
                else
                {
                    if (app.Platform != ApplePlatform.MacOSX)
                    {
                        // we can't predict is unknown (at build time) code will require registration (at runtime)
                        if (app.UseInterpreter)
                        {
                            RemoveDynamicRegistrar = false;
                        }
                        // We don't have enough information yet to determine if we can remove the dynamic
                        // registrar or not, so let the value stay unset until we do know (when running the linker).
                    }
                    else
                    {
                        // By default disabled for XM apps
                        RemoveDynamicRegistrar = false;
                    }
                }
            }

            if (app.Platform == ApplePlatform.MacOSX)
            {
                // By default on macOS trim-architectures for Release and not for debug
                if (!TrimArchitectures.HasValue)
                {
                    TrimArchitectures = !app.EnableDebug;
                }
            }

            if (app.Platform != ApplePlatform.MacOSX)
            {
                if (!RemoveUnsupportedILForBitcode.HasValue)
                {
                    // By default enabled for watchOS device builds.
                    RemoveUnsupportedILForBitcode = app.Platform == ApplePlatform.WatchOS && app.IsDeviceBuild;
                }

                if (!SealAndDevirtualize.HasValue)
                {
                    // by default run the linker SealerSubStep unless the interpreter is enabled
                    SealAndDevirtualize = !app.UseInterpreter;
                }
            }

            // By default Runtime.IsARM64CallingConvention inlining is always enabled.
            if (!InlineIsARM64CallingConvention.HasValue)
            {
                InlineIsARM64CallingConvention = true;
            }

            // by default we try to eliminate any .cctor we can
            if (!StaticConstructorBeforeFieldInit.HasValue)
            {
                StaticConstructorBeforeFieldInit = true;
            }

            // by default we remove rarely used custom attributes
            if (!CustomAttributesRemoval.HasValue)
            {
                CustomAttributesRemoval = true;
            }
        }