// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.utils;

import static com.android.tools.r8.utils.AndroidApiLevel.B;
import static com.android.tools.r8.utils.SystemPropertyUtils.parseSystemPropertyForDevelopmentOrDefault;

import com.android.tools.r8.ClassFileConsumer;
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.DataResourceConsumer;
import com.android.tools.r8.DesugarGraphConsumer;
import com.android.tools.r8.DexFilePerClassFileConsumer;
import com.android.tools.r8.DexIndexedConsumer;
import com.android.tools.r8.FeatureSplit;
import com.android.tools.r8.GlobalSyntheticsConsumer;
import com.android.tools.r8.MapIdProvider;
import com.android.tools.r8.ProgramConsumer;
import com.android.tools.r8.SourceFileProvider;
import com.android.tools.r8.StringConsumer;
import com.android.tools.r8.Version;
import com.android.tools.r8.androidapi.ComputedApiLevel;
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.debuginfo.DebugRepresentation;
import com.android.tools.r8.dex.ApplicationReader.ProgramClassConflictResolver;
import com.android.tools.r8.dex.Marker;
import com.android.tools.r8.dex.Marker.Backend;
import com.android.tools.r8.dex.Marker.Tool;
import com.android.tools.r8.dex.MixedSectionLayoutStrategy;
import com.android.tools.r8.dex.VirtualFile;
import com.android.tools.r8.dump.DumpOptions;
import com.android.tools.r8.errors.CompilationError;
import com.android.tools.r8.errors.IncompleteNestNestDesugarDiagnosic;
import com.android.tools.r8.errors.InterfaceDesugarMissingTypeDiagnostic;
import com.android.tools.r8.errors.InvalidDebugInfoException;
import com.android.tools.r8.errors.InvalidLibrarySuperclassDiagnostic;
import com.android.tools.r8.errors.MissingNestHostNestDesugarDiagnostic;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.experimental.graphinfo.GraphConsumer;
import com.android.tools.r8.experimental.startup.StartupOptions;
import com.android.tools.r8.experimental.startup.instrumentation.StartupInstrumentationOptions;
import com.android.tools.r8.features.FeatureSplitConfiguration;
import com.android.tools.r8.graph.AppInfoWithClassHierarchy;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexApplication;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexClasspathClass;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItem;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexLibraryClass;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.classmerging.VerticallyMergedClasses;
import com.android.tools.r8.horizontalclassmerging.HorizontalClassMerger;
import com.android.tools.r8.horizontalclassmerging.HorizontallyMergedClasses;
import com.android.tools.r8.horizontalclassmerging.Policy;
import com.android.tools.r8.inspector.internal.InspectorImpl;
import com.android.tools.r8.ir.analysis.proto.ProtoReferences;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.desugar.TypeRewriter;
import com.android.tools.r8.ir.desugar.TypeRewriter.MachineDesugarPrefixRewritingMapper;
import com.android.tools.r8.ir.desugar.desugaredlibrary.DesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.desugaredlibrary.machinespecification.MachineDesugaredLibrarySpecification;
import com.android.tools.r8.ir.desugar.nest.Nest;
import com.android.tools.r8.ir.optimize.Inliner;
import com.android.tools.r8.ir.optimize.enums.EnumDataMap;
import com.android.tools.r8.naming.ClassNameMapper;
import com.android.tools.r8.naming.MapVersion;
import com.android.tools.r8.optimize.argumentpropagation.ArgumentPropagatorEventConsumer;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.position.Position;
import com.android.tools.r8.profile.art.ArtProfileOptions;
import com.android.tools.r8.references.ClassReference;
import com.android.tools.r8.references.FieldReference;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.references.Reference;
import com.android.tools.r8.repackaging.Repackaging.DefaultRepackagingConfiguration;
import com.android.tools.r8.repackaging.Repackaging.RepackagingConfiguration;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.android.tools.r8.shaking.Enqueuer;
import com.android.tools.r8.shaking.GlobalKeepInfoConfiguration;
import com.android.tools.r8.shaking.ProguardConfiguration;
import com.android.tools.r8.shaking.ProguardConfigurationRule;
import com.android.tools.r8.utils.IROrdering.IdentityIROrdering;
import com.android.tools.r8.utils.IROrdering.NondeterministicIROrdering;
import com.android.tools.r8.utils.collections.ProgramMethodSet;
import com.android.tools.r8.utils.structural.Ordered;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Deque;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.objectweb.asm.Opcodes;

public class InternalOptions implements GlobalKeepInfoConfiguration {

  // Set to true to run compilation in a single thread and without randomly shuffling the input.
  // This makes life easier when running R8 in a debugger.
  public static final boolean DETERMINISTIC_DEBUGGING =
      System.getProperty("com.android.tools.r8.deterministicdebugging") != null;

  // Use a MethodCollection where most interleavings between reading and mutating is caught.
  public static final boolean USE_METHOD_COLLECTION_CONCURRENCY_CHECKED = false;

  public enum LineNumberOptimization {
    OFF,
    ON
  }

  public enum DesugarState {
    OFF,
    ON;

    public boolean isOff() {
      return this == OFF;
    }

    public boolean isOn() {
      return this == ON;
    }
  }

  public static final CfVersion SUPPORTED_CF_VERSION = CfVersion.V20;

  public static final int SUPPORTED_DEX_VERSION =
      AndroidApiLevel.LATEST.getDexVersion().getIntValue();
  public static final int EXPERIMENTAL_DEX_VERSION = DexVersion.V40.getIntValue();

  public static final int ASM_VERSION = Opcodes.ASM9;

  public final DexItemFactory itemFactory;

  public DexItemFactory dexItemFactory() {
    return itemFactory;
  }

  public boolean hasProguardConfiguration() {
    return proguardConfiguration != null;
  }

  public ProguardConfiguration getProguardConfiguration() {
    return proguardConfiguration;
  }

  private final ProguardConfiguration proguardConfiguration;
  public final Reporter reporter;

  // TODO(zerny): Make this private-final once we have full program-consumer support.
  public ProgramConsumer programConsumer = null;

  public ProgramClassConflictResolver programClassConflictResolver = null;

  private GlobalSyntheticsConsumer globalSyntheticsConsumer = null;

  public DataResourceConsumer dataResourceConsumer;
  public FeatureSplitConfiguration featureSplitConfiguration;

  public List<Consumer<InspectorImpl>> outputInspections = Collections.emptyList();

  // Constructor for testing and/or other utilities.
  public InternalOptions() {
    reporter = new Reporter();
    itemFactory = new DexItemFactory();
    proguardConfiguration = null;
    enableTreeShaking = false;
    enableMinification = false;
  }

  // Constructor for D8, L8, Lint and other non-shrinkers.
  public InternalOptions(DexItemFactory factory, Reporter reporter) {
    assert reporter != null;
    assert factory != null;
    this.reporter = reporter;
    itemFactory = factory;
    proguardConfiguration = null;
    enableTreeShaking = false;
    enableMinification = false;
    disableGlobalOptimizations();
  }

  // Constructor for R8.
  public InternalOptions(
      CompilationMode mode, ProguardConfiguration proguardConfiguration, Reporter reporter) {
    assert reporter != null;
    assert proguardConfiguration != null;
    this.debug = mode == CompilationMode.DEBUG;
    this.reporter = reporter;
    this.proguardConfiguration = proguardConfiguration;
    itemFactory = proguardConfiguration.getDexItemFactory();
    enableTreeShaking = proguardConfiguration.isShrinking();
    enableMinification = proguardConfiguration.isObfuscating();
    if (!proguardConfiguration.isOptimizing()) {
      // TODO(b/171457102): Avoid the need for this.
      // -dontoptimize disables optimizations by flipping related flags.
      disableAllOptimizations();
    }
    if (debug) {
      assert !isMinifying();
      assert !isOptimizing();
      keepDebugRelatedInformation();
    }
    configurationDebugging = proguardConfiguration.isConfigurationDebugging();
    if (proguardConfiguration.isProtoShrinkingEnabled()) {
      enableProtoShrinking();
    }
  }

  private void keepDebugRelatedInformation() {
    assert !proguardConfiguration.isObfuscating();
    getProguardConfiguration().getKeepAttributes().sourceFile = true;
    getProguardConfiguration().getKeepAttributes().sourceDebugExtension = true;
    getProguardConfiguration().getKeepAttributes().lineNumberTable = true;
    getProguardConfiguration().getKeepAttributes().localVariableTable = true;
    getProguardConfiguration().getKeepAttributes().localVariableTypeTable = true;
  }

  void enableProtoShrinking() {
    enableFieldBitAccessAnalysis = true;
    protoShrinking.enableGeneratedMessageLiteShrinking = true;
    protoShrinking.enableGeneratedMessageLiteBuilderShrinking = true;
    protoShrinking.enableGeneratedExtensionRegistryShrinking = true;
    protoShrinking.enableEnumLiteProtoShrinking = true;
  }

  void disableAllOptimizations() {
    disableGlobalOptimizations();
    enableNameReflectionOptimization = false;
    enableStringConcatenationOptimization = false;
  }

  public void disableGlobalOptimizations() {
    inlinerOptions.enableInlining = false;
    enableClassInlining = false;
    enableDevirtualization = false;
    enableVerticalClassMerging = false;
    enableEnumUnboxing = false;
    outline.enabled = false;
    enableEnumValueOptimization = false;
    enableSideEffectAnalysis = false;
    enableTreeShakingOfLibraryMethodOverrides = false;
    enableInitializedClassesAnalysis = false;
    callSiteOptimizationOptions.disableOptimization();
    horizontalClassMergerOptions.setRestrictToSynthetics();
  }

  // Configure options according to platform build assumptions.
  // See go/r8platformflag and b/232073181.
  public void configureAndroidPlatformBuild(boolean isAndroidPlatformBuild) {
    assert !addAndroidPlatformBuildToMarker;
    if (isAndroidPlatformBuild || minApiLevel.isPlatform()) {
      apiModelingOptions().disableApiModeling();
      // TODO(b/232073181): This should also enable throwing errors on triggered backports.
      disableBackports = true;
      addAndroidPlatformBuildToMarker = isAndroidPlatformBuild;
    }
  }

  public boolean printTimes = System.getProperty("com.android.tools.r8.printtimes") != null;
  // To print memory one also have to enable printtimes.
  public boolean printMemory = System.getProperty("com.android.tools.r8.printmemory") != null;

  // Flag to toggle if DEX code objects should pass-through without IR processing.
  public boolean passthroughDexCode = false;

  public static class NeverMergeGroup<T> {
    private final List<T> prefixes;
    private final List<T> exceptionPrefixes;

    NeverMergeGroup(List<T> prefixes, List<T> exceptionPrefixes) {
      this.prefixes = prefixes;
      this.exceptionPrefixes = exceptionPrefixes;
    }

    public List<T> getPrefixes() {
      return prefixes;
    }

    public List<T> getExceptionPrefixes() {
      return exceptionPrefixes;
    }

    public <R> NeverMergeGroup<R> map(Function<T, R> fn) {
      return new NeverMergeGroup<>(
          prefixes.stream().map(fn).collect(Collectors.toList()),
          exceptionPrefixes.stream().map(fn).collect(Collectors.toList()));
    }
  }

  // Flag to toggle if the prefix based merge restriction should be enforced.
  public boolean enableNeverMergePrefixes = true;
  public NeverMergeGroup<String> neverMerge =
      new NeverMergeGroup<>(ImmutableList.of("j$."), ImmutableList.of("java."));

  public boolean classpathInterfacesMayHaveStaticInitialization = false;
  public boolean libraryInterfacesMayHaveStaticInitialization = false;

  // Optimization-related flags. These should conform to -dontoptimize and disableAllOptimizations.
  public boolean enableFieldBitAccessAnalysis =
      System.getProperty("com.android.tools.r8.fieldBitAccessAnalysis") != null;
  public boolean enableVerticalClassMerging = true;
  public boolean enableUnusedInterfaceRemoval = true;
  public boolean enableDevirtualization = true;
  public boolean enableEnumUnboxing = true;
  public boolean enableSimpleInliningConstraints = true;
  public final int simpleInliningConstraintThreshold = 0;
  public boolean enableClassInlining = true;
  public boolean enableClassStaticizer = true;
  public boolean enableInitializedClassesAnalysis = true;
  public boolean enableSideEffectAnalysis = true;
  public boolean enableDeterminismAnalysis = true;
  public boolean enableServiceLoaderRewriting = true;
  public boolean enableNameReflectionOptimization = true;
  public boolean enableStringConcatenationOptimization = true;
  public boolean enableTreeShakingOfLibraryMethodOverrides = false;
  public boolean encodeChecksums = false;
  public BiPredicate<String, Long> dexClassChecksumFilter = (name, checksum) -> true;
  public boolean forceAnnotateSynthetics = false;
  public boolean readDebugSetFileEvent = false;
  public boolean disableL8AnnotationRemoval =
      System.getProperty("com.android.tools.r8.disableL8AnnotationRemoval") != null;

  public int callGraphLikelySpuriousCallEdgeThreshold = 50;

  public int verificationSizeLimitInBytes() {
    if (testing.verificationSizeLimitInBytesOverride > -1) {
      return testing.verificationSizeLimitInBytesOverride;
    }
    // For CF we use the defined limit in the spec. For DEX we use the limit of the static verifier
    // https://android.googlesource.com/platform/art/+/android10-release/compiler/compiler.cc#48
    return isGeneratingClassFiles() ? 65534 : 16383;
  }

  public int minimumVerificationSizeLimitInBytes() {
    if (testing.verificationSizeLimitInBytesOverride > -1) {
      return testing.verificationSizeLimitInBytesOverride;
    }
    return 16383;
  }

  // We assume options will always be created on the main thread.
  public Thread mainThread = Thread.currentThread();

  public boolean enableSwitchRewriting = true;
  public boolean enableStringSwitchConversion = true;
  public int minimumStringSwitchSize = 3;
  public boolean enableEnumValueOptimization = true;
  public boolean enableEnumSwitchMapRemoval = true;
  public final OutlineOptions outline = new OutlineOptions();
  public boolean enableInitializedClassesInInstanceMethodsAnalysis = true;
  public boolean enableRedundantFieldLoadElimination = true;
  // TODO(b/138917494): Disable until we have numbers on potential performance penalties.
  public boolean enableRedundantConstNumberOptimization = false;
  public boolean enableLoopUnrolling = true;

  // TODO(b/237567012): Remove when resolved.
  public boolean enableCheckAllInstructionsDuringStackMapVerification = false;

  public String synthesizedClassPrefix = "";

  // Number of threads to use while processing the dex files.
  public int threadCount = DETERMINISTIC_DEBUGGING ? 1 : ThreadUtils.NOT_SPECIFIED;
  // Print smali disassembly.
  public boolean useSmaliSyntax = false;
  // Verbose output.
  public boolean verbose = false;
  // Silencing output.
  public boolean quiet = false;
  // Throw exception if there is a warning about invalid debug info.
  public boolean invalidDebugInfoFatal = false;
  // Don't gracefully recover from invalid debug info.
  public boolean invalidDebugInfoStrict =
      System.getProperty("com.android.tools.r8.strictdebuginfo") != null;

  public boolean ignoreJavaLibraryOverride = false;

  // When dexsplitting we ignore main dex classes missing in the application. These will be
  // fused together by play store when shipped for pre-L devices.
  public boolean ignoreMainDexMissingClasses = false;

  // Boolean value indicating that byte code pass through may be enabled.
  public boolean enableCfByteCodePassThrough = false;

  // Flag to control the representation of stateless lambdas.
  // See b/222081665 for context.
  public boolean createSingletonsForStatelessLambdas =
      System.getProperty("com.android.tools.r8.createSingletonsForStatelessLambdas") != null;

  // Flag to allow record annotations in DEX. See b/231930852 for context.
  public boolean emitRecordAnnotationsInDex =
      System.getProperty("com.android.tools.r8.emitRecordAnnotationsInDex") != null;

  // Flag to allow nest annotations in DEX. See b/231930852 for context.
  public boolean emitNestAnnotationsInDex =
      System.getProperty("com.android.tools.r8.emitNestAnnotationsInDex") != null;

  // Flag to allow permitted subclasses annotations in DEX. See b/231930852 for context.
  public boolean emitPermittedSubclassesAnnotationsInDex =
      System.getProperty("com.android.tools.r8.emitPermittedSubclassesAnnotationsInDex") != null;

  private DumpInputFlags dumpInputFlags = DumpInputFlags.getDefault();

  // Contain the contents of the build properties file from the compiler command.
  public DumpOptions dumpOptions;

  // Hidden marker for classes.dex
  private boolean hasMarker = false;
  private Marker marker;

  public void setMarker(Marker marker) {
    this.hasMarker = true;
    this.marker = marker;
  }

  public Marker getMarker(Tool tool) {
    if (hasMarker) {
      return marker;
    }
    return createMarker(tool);
  }

  // Compute the marker to be placed in the main dex file.
  private Marker createMarker(Tool tool) {
    Marker marker =
        new Marker(tool)
            .setVersion(Version.LABEL)
            .setCompilationMode(debug ? CompilationMode.DEBUG : CompilationMode.RELEASE)
            .setBackend(isGeneratingClassFiles() ? Backend.CF : Backend.DEX)
            .setHasChecksums(encodeChecksums);
    // The marker records the min API if any desugaring happens or if the compiler generates dex
    // since the output depends on the min API in this case. There is basically no min API entry
    // in R8 cf to cf.
    if (isGeneratingDex() || desugarState == DesugarState.ON) {
      marker.setMinApi(getMinApiLevel().getLevel());
    }
    if (machineDesugaredLibrarySpecification.getIdentifier() != null) {
      marker.setDesugaredLibraryIdentifiers(machineDesugaredLibrarySpecification.getIdentifier());
    }
    if (Version.isDevelopmentVersion()) {
      marker.setSha1(VersionProperties.INSTANCE.getSha());
    }
    if (tool == Tool.R8) {
      marker.setR8Mode(forceProguardCompatibility ? "compatibility" : "full");
    }
    if (addAndroidPlatformBuildToMarker) {
      marker.setAndroidPlatformBuild();
    }
    return marker;
  }

  public void setDumpInputFlags(DumpInputFlags dumpInputFlags) {
    this.dumpInputFlags = dumpInputFlags;
  }

  public boolean hasConsumer() {
    return programConsumer != null;
  }

  public InternalOutputMode getInternalOutputMode() {
    assert hasConsumer();
    if (isGeneratingDexIndexed()) {
      return InternalOutputMode.DexIndexed;
    } else if (isGeneratingDexFilePerClassFile()) {
      return InternalOutputMode.DexFilePerClassFile;
    } else if (isGeneratingClassFiles()) {
      return InternalOutputMode.ClassFile;
    }
    throw new UnsupportedOperationException("Cannot find internal output mode.");
  }

  public boolean hasGlobalSyntheticsConsumer() {
    return globalSyntheticsConsumer != null;
  }

  public GlobalSyntheticsConsumer getGlobalSyntheticsConsumer() {
    return globalSyntheticsConsumer;
  }

  public void setGlobalSyntheticsConsumer(GlobalSyntheticsConsumer globalSyntheticsConsumer) {
    this.globalSyntheticsConsumer = globalSyntheticsConsumer;
  }

  public boolean isDesugaredLibraryCompilation() {
    return machineDesugaredLibrarySpecification.isLibraryCompilation();
  }

  public boolean isRelocatorCompilation() {
    return relocatorCompilation;
  }

  public boolean shouldKeepStackMapTable() {
    assert isRelocatorCompilation() || getProguardConfiguration() != null;
    return isRelocatorCompilation() || getProguardConfiguration().getKeepAttributes().stackMapTable;
  }

  public boolean shouldRerunEnqueuer() {
    return isShrinking() || isMinifying() || getProguardConfiguration().hasApplyMappingFile();
  }

  public boolean isGeneratingDex() {
    return isGeneratingDexIndexed() || isGeneratingDexFilePerClassFile();
  }

  public boolean isGeneratingDexIndexed() {
    return programConsumer instanceof DexIndexedConsumer;
  }

  public boolean isGeneratingDexFilePerClassFile() {
    return programConsumer instanceof DexFilePerClassFileConsumer;
  }

  public boolean isGeneratingClassFiles() {
    return programConsumer instanceof ClassFileConsumer;
  }

  public boolean isDesugaring() {
    return desugarState.isOn();
  }

  public boolean isCfDesugaring() {
    return isGeneratingClassFiles() && desugarState.isOn();
  }

  public DexIndexedConsumer getDexIndexedConsumer() {
    return (DexIndexedConsumer) programConsumer;
  }

  public DexFilePerClassFileConsumer getDexFilePerClassFileConsumer() {
    return (DexFilePerClassFileConsumer) programConsumer;
  }

  public ClassFileConsumer getClassFileConsumer() {
    return (ClassFileConsumer) programConsumer;
  }

  public void signalFinishedToConsumers() {
    if (programConsumer != null) {
      programConsumer.finished(reporter);
      if (dataResourceConsumer != null) {
        dataResourceConsumer.finished(reporter);
      }
    }
    if (featureSplitConfiguration != null) {
      for (FeatureSplit featureSplit : featureSplitConfiguration.getFeatureSplits()) {
        ProgramConsumer programConsumer = featureSplit.getProgramConsumer();
        programConsumer.finished(reporter);
        DataResourceConsumer dataResourceConsumer = programConsumer.getDataResourceConsumer();
        if (dataResourceConsumer != null) {
          dataResourceConsumer.finished(reporter);
        }
      }
    }
    if (desugarGraphConsumer != null) {
      desugarGraphConsumer.finished();
    }
  }

  public boolean shouldDesugarNests() {
    return !canUseNestBasedAccess();
  }

  public boolean shouldDesugarRecords() {
    return desugarState.isOn() && !canUseRecords();
  }

  public boolean shouldDesugarVarHandle() {
    return desugarState.isOn() && !canUseVarHandle() && enableVarHandleDesugaring;
  }

  public Set<String> extensiveLoggingFilter = getExtensiveLoggingFilter();
  public Set<String> extensiveInterfaceMethodMinifierLoggingFilter =
      getExtensiveInterfaceMethodMinifierLoggingFilter();

  public List<String> methodsFilter = ImmutableList.of();
  private AndroidApiLevel minApiLevel = AndroidApiLevel.getDefault();
  // Skipping min_api check and compiling an intermediate result intended for later merging.
  // Intermediate builds also emits or update synthesized classes mapping.
  public boolean intermediate = false;
  private boolean addAndroidPlatformBuildToMarker = false;
  public boolean retainCompileTimeAnnotations = true;
  public boolean ignoreBootClasspathEnumsForMaindexTracing =
      System.getProperty("com.android.tools.r8.ignoreBootClasspathEnumsForMaindexTracing") != null;
  public boolean pruneNonVissibleAnnotationClasses =
      System.getProperty("com.android.tools.r8.pruneNonVissibleAnnotationClasses") != null;
  public List<String> logArgumentsFilter = ImmutableList.of();

  // Flag to turn on/offLoad/store optimization in the Cf back-end.
  public boolean enableLoadStoreOptimization = true;
  // Flag to turn on/off desugaring in D8/R8.
  public DesugarState desugarState = DesugarState.ON;
  // Flag to turn on/off partial VarHandle desugaring.
  public boolean enableVarHandleDesugaring = false;
  // Flag to turn off backport methods (and report errors if triggered).
  public boolean disableBackports = false;
  public boolean disableBackportsWithErrorDiagnostics =
      System.getProperty("com.android.tools.r8.throwErrorOnBackport") != null;
  // Flag to turn on/off reduction of nest to improve class merging optimizations.
  public boolean enableNestReduction = true;
  // Defines interface method rewriter behavior.
  public OffOrAuto interfaceMethodDesugaring = OffOrAuto.Auto;
  // Defines try-with-resources rewriter behavior.
  public OffOrAuto tryWithResourcesDesugaring = OffOrAuto.Auto;
  // Flag to turn on/off processing of @dalvik.annotation.codegen.CovariantReturnType and
  // @dalvik.annotation.codegen.CovariantReturnType$CovariantReturnTypes.
  public boolean processCovariantReturnTypeAnnotations = true;
  // Flag to control library/program class lookup order.
  // TODO(120884788): Enable this flag as the default.
  public boolean lookupLibraryBeforeProgram = false;
  // TODO(120884788): Leave this system property as a stop-gap for some time.
  // public boolean lookupLibraryBeforeProgram =
  //     System.getProperty("com.android.tools.r8.lookupProgramBeforeLibrary") == null;

  public boolean enableEnqueuerDeferredTracing =
      System.getProperty("com.android.tools.r8.disableEnqueuerDeferredTracing") == null;

  public boolean loadAllClassDefinitions = false;

  // Whether or not to check for valid multi-dex builds.
  //
  // For min-api levels that did not support native multi-dex the user should provide a main dex
  // list. However, DX, didn't check that this was the case. Therefore, for CompatDX we have a flag
  // to disable the check that the build makes sense for multi-dexing.
  public boolean enableMainDexListCheck = true;

  private final boolean enableTreeShaking;
  private final boolean enableMinification;

  public AndroidApiLevel getMinApiLevel() {
    // If compiling to CF with no desugaring then we should not inspect the min-api.
    // For now we assert the API level for non-desugared CF is B, but it would be better to never
    // access the min-api in those cases.
    assert desugarState.isOn() || isGeneratingDex() || minApiLevel.equals(AndroidApiLevel.B);
    return minApiLevel;
  }

  public void setMinApiLevel(AndroidApiLevel minApiLevel) {
    assert minApiLevel != null;
    this.minApiLevel = minApiLevel;
  }

  public boolean isOptimizing() {
    return hasProguardConfiguration() && getProguardConfiguration().isOptimizing();
  }

  public boolean isRelease() {
    return !debug;
  }

  public boolean isShrinking() {
    assert proguardConfiguration == null
        || enableTreeShaking == proguardConfiguration.isShrinking();
    return enableTreeShaking;
  }

  public boolean isMinifying() {
    assert proguardConfiguration == null
        || enableMinification == proguardConfiguration.isObfuscating();
    return enableMinification;
  }

  @Override
  public boolean isAnnotationRemovalEnabled() {
    return !isForceProguardCompatibilityEnabled();
  }

  @Override
  public boolean isTreeShakingEnabled() {
    return isShrinking();
  }

  @Override
  public boolean isMinificationEnabled() {
    return isMinifying();
  }

  @Override
  public boolean isOptimizationEnabled() {
    return isOptimizing();
  }

  @Override
  public boolean isRepackagingEnabled() {
    return !debug
        && proguardConfiguration != null
        && proguardConfiguration.getPackageObfuscationMode().isSome()
        && (isMinifying() || !isForceProguardCompatibilityEnabled());
  }

  @Override
  public boolean isForceProguardCompatibilityEnabled() {
    return forceProguardCompatibility;
  }

  public boolean parseSignatureAttribute() {
    return isKeepAttributesSignatureEnabled();
  }

  @Override
  public boolean isKeepAttributesSignatureEnabled() {
    return proguardConfiguration == null || proguardConfiguration.getKeepAttributes().signature;
  }

  @Override
  public boolean isKeepEnclosingMethodAttributeEnabled() {
    return proguardConfiguration.getKeepAttributes().enclosingMethod;
  }

  @Override
  public boolean isKeepInnerClassesAttributeEnabled() {
    return proguardConfiguration.getKeepAttributes().innerClasses;
  }

  @Override
  public boolean isKeepRuntimeInvisibleAnnotationsEnabled() {
    return proguardConfiguration.getKeepAttributes().runtimeInvisibleAnnotations;
  }

  @Override
  public boolean isKeepRuntimeInvisibleParameterAnnotationsEnabled() {
    return proguardConfiguration.getKeepAttributes().runtimeInvisibleParameterAnnotations;
  }

  @Override
  public boolean isKeepRuntimeVisibleAnnotationsEnabled() {
    return proguardConfiguration.getKeepAttributes().runtimeVisibleAnnotations;
  }

  @Override
  public boolean isKeepRuntimeVisibleParameterAnnotationsEnabled() {
    return proguardConfiguration.getKeepAttributes().runtimeVisibleParameterAnnotations;
  }

  /**
   * If any non-static class merging is enabled, information about types referred to by instanceOf
   * and check cast instructions needs to be collected.
   */
  public boolean isClassMergingExtensionRequired(Enqueuer.Mode mode) {
    if (mode.isInitialTreeShaking()) {
      return (horizontalClassMergerOptions.isEnabled(HorizontalClassMerger.Mode.INITIAL)
              && !horizontalClassMergerOptions.isRestrictedToSynthetics())
          || enableVerticalClassMerging;
    }
    if (mode.isFinalTreeShaking()) {
      return horizontalClassMergerOptions.isEnabled(HorizontalClassMerger.Mode.FINAL)
          && !horizontalClassMergerOptions.isRestrictedToSynthetics();
    }
    assert false;
    return false;
  }

  @Override
  public boolean isAccessModificationEnabled() {
    return getProguardConfiguration() != null
        && getProguardConfiguration().isAccessModificationAllowed();
  }

  @Override
  public boolean isMethodStaticizingEnabled() {
    return callSiteOptimizationOptions().isMethodStaticizingEnabled();
  }

  public boolean keepInnerClassStructure() {
    return getProguardConfiguration().getKeepAttributes().signature
        || getProguardConfiguration().getKeepAttributes().innerClasses;
  }

  public boolean canUseInputStackMaps() {
    return testing.readInputStackMaps ? testing.readInputStackMaps : isGeneratingClassFiles();
  }

  public boolean printCfg = false;
  public String printCfgFile;
  public boolean ignoreMissingClasses = false;
  public boolean reportMissingClassesInEnclosingMethodAttribute = false;
  public boolean reportMissingClassesInInnerClassAttributes = false;
  public boolean disableGenericSignatureValidation = false;
  public boolean disableInnerClassSeparatorValidationWhenRepackaging = false;

  // EXPERIMENTAL flag to get behaviour as close to Proguard as possible.
  public boolean forceProguardCompatibility = false;
  public AssertionConfigurationWithDefault assertionsConfiguration = null;
  public boolean configurationDebugging = false;

  // Don't convert Code objects to IRCode.
  public boolean skipIR = false;

  public boolean debug = false;

  private final RewriteArrayOptions rewriteArrayOptions = new RewriteArrayOptions();
  private final CallSiteOptimizationOptions callSiteOptimizationOptions =
      new CallSiteOptimizationOptions();
  private final CfCodeAnalysisOptions cfCodeAnalysisOptions = new CfCodeAnalysisOptions();
  private final ClassInlinerOptions classInlinerOptions = new ClassInlinerOptions();
  private final InlinerOptions inlinerOptions = new InlinerOptions();
  private final HorizontalClassMergerOptions horizontalClassMergerOptions =
      new HorizontalClassMergerOptions();
  private final OpenClosedInterfacesOptions openClosedInterfacesOptions =
      new OpenClosedInterfacesOptions();
  private final ProtoShrinkingOptions protoShrinking = new ProtoShrinkingOptions();
  private final KotlinOptimizationOptions kotlinOptimizationOptions =
      new KotlinOptimizationOptions();
  private final ApiModelTestingOptions apiModelTestingOptions = new ApiModelTestingOptions();
  private final DesugarSpecificOptions desugarSpecificOptions = new DesugarSpecificOptions();
  private final MappingComposeOptions mappingComposeOptions = new MappingComposeOptions();
  private final ArtProfileOptions artProfileOptions = new ArtProfileOptions();
  private final StartupOptions startupOptions = new StartupOptions();
  private final StartupInstrumentationOptions startupInstrumentationOptions =
      new StartupInstrumentationOptions();
  public final TestingOptions testing = new TestingOptions();

  public List<ProguardConfigurationRule> mainDexKeepRules = ImmutableList.of();
  public boolean minimalMainDex;
  /**
   * Enable usage of InheritanceClassInDexDistributor for multidex legacy builds. This allows
   * distribution of classes to minimize DexOpt LinearAlloc usage by minimizing linking errors
   * during DexOpt and controlling the load of classes with linking issues. This has the consequence
   * of making minimal main dex not absolutely minimal regarding runtime execution constraints
   * because it's adding classes in the main dex to satisfy also DexOpt constraints.
   */
  public boolean enableInheritanceClassInDexDistributor = true;

  public LineNumberOptimization lineNumberOptimization = LineNumberOptimization.ON;

  public RewriteArrayOptions rewriteArrayOptions() {
    return rewriteArrayOptions;
  }

  public CallSiteOptimizationOptions callSiteOptimizationOptions() {
    return callSiteOptimizationOptions;
  }

  public ClassInlinerOptions classInlinerOptions() {
    return classInlinerOptions;
  }

  public InlinerOptions inlinerOptions() {
    return inlinerOptions;
  }

  public HorizontalClassMergerOptions horizontalClassMergerOptions() {
    return horizontalClassMergerOptions;
  }

  public ProtoShrinkingOptions protoShrinking() {
    return protoShrinking;
  }

  public KotlinOptimizationOptions kotlinOptimizationOptions() {
    return kotlinOptimizationOptions;
  }

  public ApiModelTestingOptions apiModelingOptions() {
    return apiModelTestingOptions;
  }

  public MappingComposeOptions mappingComposeOptions() {
    return mappingComposeOptions;
  }

  public DesugarSpecificOptions desugarSpecificOptions() {
    return desugarSpecificOptions;
  }

  public CfCodeAnalysisOptions getCfCodeAnalysisOptions() {
    return cfCodeAnalysisOptions;
  }

  public DumpInputFlags getDumpInputFlags() {
    return dumpInputFlags;
  }

  public OpenClosedInterfacesOptions getOpenClosedInterfacesOptions() {
    return openClosedInterfacesOptions;
  }

  public ArtProfileOptions getArtProfileOptions() {
    return artProfileOptions;
  }

  public StartupOptions getStartupOptions() {
    return startupOptions;
  }

  public StartupInstrumentationOptions getStartupInstrumentationOptions() {
    return startupInstrumentationOptions;
  }

  public TestingOptions getTestingOptions() {
    return testing;
  }

  private static Set<String> getExtensiveLoggingFilter() {
    String property = System.getProperty("com.android.tools.r8.extensiveLoggingFilter");
    if (property != null) {
      ImmutableSet.Builder<String> builder = ImmutableSet.builder();
      for (String method : property.split(";")) {
        builder.add(method);
      }
      return builder.build();
    }
    return ImmutableSet.of();
  }

  private static Set<String> getExtensiveInterfaceMethodMinifierLoggingFilter() {
    String property =
        System.getProperty("com.android.tools.r8.extensiveInterfaceMethodMinifierLoggingFilter");
    if (property != null) {
      ImmutableSet.Builder<String> builder = ImmutableSet.builder();
      for (String method : property.split(";")) {
        builder.add(method);
      }
      return builder.build();
    }
    return ImmutableSet.of();
  }

  public static class InvalidParameterAnnotationInfo {

    final DexMethod method;
    final int expectedParameterCount;
    final int actualParameterCount;

    public InvalidParameterAnnotationInfo(
        DexMethod method, int expectedParameterCount, int actualParameterCount) {
      this.method = method;
      this.expectedParameterCount = expectedParameterCount;
      this.actualParameterCount = actualParameterCount;
    }
  }

  private static class TypeVersionPair {

    final CfVersion version;
    final DexType type;

    public TypeVersionPair(CfVersion version, DexType type) {
      this.version = version;
      this.type = type;
    }
  }

  private final Map<Origin, List<TypeVersionPair>> missingEnclosingMembers = new HashMap<>();

  private final Map<Origin, List<InvalidParameterAnnotationInfo>> warningInvalidParameterAnnotations
      = new HashMap<>();

  private final Map<Origin, List<Pair<ProgramMethod, String>>> warningInvalidDebugInfo =
      new HashMap<>();

  // Don't read code from dex files. Used to extract non-code information from vdex files where
  // the code contains unsupported byte codes.
  public boolean skipReadingDexCode = false;

  // If null, no main-dex list needs to be computed.
  // If non null it must be and passed to the consumer.
  public StringConsumer mainDexListConsumer = null;

  // If null, no proguard map needs to be computed.
  // If non null it must be and passed to the consumer.
  public StringConsumer proguardMapConsumer = null;

  // If null, no usage information needs to be computed.
  // If non-null, it must be and is passed to the consumer.
  public StringConsumer usageInformationConsumer = null;

  public boolean hasUsageInformationConsumer() {
    return usageInformationConsumer != null;
  }

  // If null, no proguard seeds info needs to be computed.
  // If non null it must be and passed to the consumer.
  public StringConsumer proguardSeedsConsumer = null;

  // If null, no configuration information needs to be printed.
  // If non-null, configuration must be passed to the consumer.
  public StringConsumer configurationConsumer = null;

  public void setDesugaredLibrarySpecification(DesugaredLibrarySpecification specification) {
    if (specification.isEmpty()) {
      return;
    }
    loadMachineDesugaredLibrarySpecification =
        (timing, app) ->
            machineDesugaredLibrarySpecification =
                specification.toMachineSpecification(app, timing);
  }

  private ThrowingBiConsumer<Timing, DexApplication, IOException>
      loadMachineDesugaredLibrarySpecification = null;

  public void loadMachineDesugaredLibrarySpecification(Timing timing, DexApplication app)
      throws IOException {
    if (loadMachineDesugaredLibrarySpecification == null) {
      return;
    }
    timing.begin("Load machine specification");
    loadMachineDesugaredLibrarySpecification.accept(timing, app);
    timing.end();
  }

  // Contains flags describing library desugaring.
  public MachineDesugaredLibrarySpecification machineDesugaredLibrarySpecification =
      MachineDesugaredLibrarySpecification.empty();

  public TypeRewriter getTypeRewriter() {
    return machineDesugaredLibrarySpecification.requiresTypeRewriting()
        ? new MachineDesugarPrefixRewritingMapper(machineDesugaredLibrarySpecification)
        : TypeRewriter.empty();
  }

  public boolean relocatorCompilation = false;

  // If null, no keep rules are recorded.
  // If non null it records desugared library APIs used by the program.
  public StringConsumer desugaredLibraryKeepRuleConsumer = null;

  // If null, no graph information needs to be provided for the keep/inclusion of classes
  // in the output. If non-null, each edge pertaining to kept parts of the resulting program
  // must be reported to the consumer.
  public GraphConsumer keptGraphConsumer = null;

  // If null, no graph information needs to be provided for the keep/inclusion of classes
  // in the main-dex output. If non-null, each edge pertaining to kept parts in the main-dex output
  // of the resulting program must be reported to the consumer.
  public GraphConsumer mainDexKeptGraphConsumer = null;

  // If null, no desugaring dependencies need to be provided. If non-null, each dependency between
  // code objects needed for correct desugaring needs to be provided to the consumer.
  public DesugarGraphConsumer desugarGraphConsumer = null;

  public Consumer<List<ProguardConfigurationRule>> syntheticProguardRulesConsumer = null;

  public MapIdProvider mapIdProvider = null;
  public SourceFileProvider sourceFileProvider = null;

  public static boolean assertionsEnabled() {
    boolean assertionsEnabled = false;
    assert assertionsEnabled = true; // Intentional side-effect.
    return assertionsEnabled;
  }

  public static void checkAssertionsEnabled() {
    if (!assertionsEnabled()) {
      throw new Unreachable();
    }
  }

  /** A set of dexitems we have reported missing to dedupe warnings. */
  private final Set<DexItem> reportedMissingForDesugaring = Sets.newConcurrentHashSet();

  private final AtomicBoolean reportedErrorReadingKotlinMetadataReflectively =
      new AtomicBoolean(false);
  private final Set<DexItem> invalidLibraryClasses = Sets.newConcurrentHashSet();

  public RuntimeException errorMissingNestHost(DexClass clazz) {
    throw reporter.fatalError(
        new MissingNestHostNestDesugarDiagnostic(
            clazz.getOrigin(), Position.UNKNOWN, messageErrorMissingNestHost(clazz)));
  }

  private static String messageErrorMissingNestHost(DexClass compiledClass) {
    String nestHostName = compiledClass.getNestHost().getName();
    return "Class "
        + compiledClass.type.getName()
        + " requires its nest host "
        + nestHostName
        + " to be on program or class path.";
  }

  public RuntimeException errorMissingNestMember(Nest nest) {
    throw reporter.fatalError(
        new IncompleteNestNestDesugarDiagnosic(
            nest.getHostClass().getOrigin(), Position.UNKNOWN, messageErrorIncompleteNest(nest)));
  }

  private static String messageErrorIncompleteNest(Nest nest) {
    List<DexProgramClass> programClassesFromNest = new ArrayList<>();
    List<DexClasspathClass> classpathClassesFromNest = new ArrayList<>();
    List<DexLibraryClass> libraryClassesFromNest = new ArrayList<>();
    nest.getHostClass()
        .accept(
            programClassesFromNest::add,
            classpathClassesFromNest::add,
            libraryClassesFromNest::add);
    for (DexClass memberClass : nest.getMembers()) {
      memberClass.accept(
          programClassesFromNest::add, classpathClassesFromNest::add, libraryClassesFromNest::add);
    }
    StringBuilder stringBuilder =
        new StringBuilder("Compilation of classes ")
            .append(StringUtils.join(", ", programClassesFromNest, DexClass::getTypeName))
            .append(" requires its nest mates ");
    if (nest.hasMissingMembers()) {
      stringBuilder
          .append(StringUtils.join(", ", nest.getMissingMembers(), DexType::getTypeName))
          .append(" (unavailable) ");
    }
    if (!libraryClassesFromNest.isEmpty()) {
      stringBuilder
          .append(StringUtils.join(", ", libraryClassesFromNest, DexClass::getTypeName))
          .append(" (on library path) ");
    }
    stringBuilder.append("to be on program or class path.");
    if (!classpathClassesFromNest.isEmpty()) {
      stringBuilder
          .append("(Classes ")
          .append(StringUtils.join(", ", classpathClassesFromNest, DexClass::getTypeName))
          .append(" from the same nest are on class path).");
    }
    return stringBuilder.toString();
  }

  public void warningMissingTypeForDesugar(
      Origin origin, Position position, DexType missingType, DexMethod context) {
    if (reportedMissingForDesugaring.add(missingType)) {
      reporter.warning(
          new InterfaceDesugarMissingTypeDiagnostic(
              origin,
              position,
              Reference.classFromDescriptor(missingType.toDescriptorString()),
              Reference.classFromDescriptor(context.holder.toDescriptorString()),
              null));
    }
  }

  public void warningMissingInterfaceForDesugar(
      DexClass classToDesugar, DexClass implementing, DexType missing) {
    if (reportedMissingForDesugaring.add(missing)) {
      reporter.warning(
          new InterfaceDesugarMissingTypeDiagnostic(
              classToDesugar.getOrigin(),
              Position.UNKNOWN,
              Reference.classFromDescriptor(missing.toDescriptorString()),
              Reference.classFromDescriptor(classToDesugar.getType().toDescriptorString()),
              classToDesugar == implementing
                  ? null
                  : Reference.classFromDescriptor(implementing.getType().toDescriptorString())));
    }
  }

  public void warningReadingKotlinMetadataReflective() {
    if (reportedErrorReadingKotlinMetadataReflectively.compareAndSet(false, true)) {
      reporter.warning(
          new StringDiagnostic(
              "Could not read the kotlin metadata message reflectively which indicates the"
                  + " compiler running in the context of a Security Manager. Not being able to"
                  + " read the kotlin metadata will have a negative effect oncode size"));
    }
  }

  public void warningInvalidLibrarySuperclassForDesugar(
      Origin origin,
      DexType libraryType,
      DexType invalidSuperType,
      String message,
      Set<DexMethod> retarget) {
    if (invalidLibraryClasses.add(invalidSuperType)) {
      reporter.warning(
          new InvalidLibrarySuperclassDiagnostic(
              origin,
              Reference.classFromDescriptor(libraryType.toDescriptorString()),
              Reference.classFromDescriptor(invalidSuperType.toDescriptorString()),
              message,
              Lists.newArrayList(
                  Iterables.transform(retarget, method -> method.asMethodReference()))));
    }
  }

  public void warningMissingEnclosingMember(DexType clazz, Origin origin, CfVersion version) {
    TypeVersionPair pair = new TypeVersionPair(version, clazz);
    synchronized (missingEnclosingMembers) {
      missingEnclosingMembers.computeIfAbsent(origin, k -> new ArrayList<>()).add(pair);
    }
  }

  public void warningInvalidParameterAnnotations(
      DexMethod method, Origin origin, int expected, int actual) {
    InvalidParameterAnnotationInfo info =
        new InvalidParameterAnnotationInfo(method, expected, actual);
    synchronized (warningInvalidParameterAnnotations) {
      warningInvalidParameterAnnotations.computeIfAbsent(origin, k -> new ArrayList<>()).add(info);
    }
  }

  public void warningInvalidDebugInfo(
      ProgramMethod method, Origin origin, InvalidDebugInfoException e) {
    if (invalidDebugInfoFatal) {
      throw new CompilationError("Fatal warning: Invalid debug info", e);
    }
    synchronized (warningInvalidDebugInfo) {
      warningInvalidDebugInfo.computeIfAbsent(
          origin, k -> new ArrayList<>()).add(new Pair<>(method, e.getMessage()));
    }
  }

  public boolean printWarnings() {
    boolean printed = false;
    boolean printOutdatedToolchain = false;
    if (warningInvalidParameterAnnotations.size() > 0) {
      // TODO(b/67626202): Add a regression test with a program that hits this issue.
      reporter.info(
          new StringDiagnostic(
              "Invalid parameter counts in MethodParameter attributes. "
                  + "This is likely due to Proguard having removed a parameter."));
      for (Origin origin : new TreeSet<>(warningInvalidParameterAnnotations.keySet())) {
        StringBuilder builder =
            new StringBuilder("Methods with invalid MethodParameter attributes:");
        for (InvalidParameterAnnotationInfo info : warningInvalidParameterAnnotations.get(origin)) {
          builder
              .append("\n  ")
              .append(info.method)
              .append(" expected count: ")
              .append(info.expectedParameterCount)
              .append(" actual count: ")
              .append(info.actualParameterCount);
        }
        reporter.info(new StringDiagnostic(builder.toString(), origin));
      }
      printed = true;
    }
    if (warningInvalidDebugInfo.size() > 0) {
      int count = 0;
      for (List<Pair<ProgramMethod, String>> methods : warningInvalidDebugInfo.values()) {
        count += methods.size();
      }
      reporter.info(
          new StringDiagnostic(
              "Stripped invalid locals information from "
                  + count
                  + (count == 1 ? " method." : " methods.")));
      for (Origin origin : new TreeSet<>(warningInvalidDebugInfo.keySet())) {
        StringBuilder builder = new StringBuilder("Methods with invalid locals information:");
        for (Pair<ProgramMethod, String> method : warningInvalidDebugInfo.get(origin)) {
          builder.append("\n  ").append(method.getFirst().toSourceString());
          builder.append("\n  ").append(method.getSecond());
        }
        reporter.info(new StringDiagnostic(builder.toString(), origin));
      }
      printed = true;
      printOutdatedToolchain = true;
    }
    if (missingEnclosingMembers.size() > 0) {
      reporter.info(
          new StringDiagnostic(
              "InnerClasses attribute has entries missing a corresponding "
                  + "EnclosingMethod attribute. "
                  + "Such InnerClasses attribute entries are ignored."));
      for (Origin origin : new TreeSet<>(missingEnclosingMembers.keySet())) {
        StringBuilder builder = new StringBuilder("Classes with missing EnclosingMethod: ");
        boolean first = true;
        for (TypeVersionPair pair : missingEnclosingMembers.get(origin)) {
          if (first) {
            first = false;
          } else {
            builder.append(", ");
          }
          builder.append(pair.type);
          printOutdatedToolchain |= pair.version.isLessThan(CfVersion.V1_5);
        }
        reporter.info(new StringDiagnostic(builder.toString(), origin));
      }
      printed = true;
    }
    if (printOutdatedToolchain) {
      reporter.info(
          new StringDiagnostic(
              "Some warnings are typically a sign of using an outdated Java toolchain."
                  + " To fix, recompile the source with an updated toolchain."));
    }
    return printed;
  }

  public boolean hasMethodsFilter() {
    return methodsFilter.size() > 0;
  }

  public boolean methodMatchesFilter(DexEncodedMethod method) {
    // Not specifying a filter matches all methods.
    if (!hasMethodsFilter()) {
      return true;
    }
    // Currently the filter is simple string equality on the qualified name.
    String qualifiedName = method.qualifiedName();
    return methodsFilter.contains(qualifiedName);
  }

  public boolean methodMatchesLogArgumentsFilter(DexEncodedMethod method) {
    // Not specifying a filter matches no methods.
    if (logArgumentsFilter.size() == 0) {
      return false;
    }
    // Currently the filter is simple string equality on the qualified name.
    String qualifiedName = method.qualifiedName();
    return logArgumentsFilter.contains(qualifiedName);
  }

  public enum PackageObfuscationMode {
    // No package obfuscation.
    NONE,
    // Strategy based on ordinary package obfuscation when no package-obfuscation mode is specified
    // by the users. In practice this falls back to FLATTEN but with keeping package-names.
    MINIFICATION,
    // Repackaging all classes into the single user-given (or top-level) package.
    REPACKAGE,
    // Repackaging all packages into the single user-given (or top-level) package.
    FLATTEN;

    public boolean isNone() {
      return this == NONE;
    }

    public boolean isFlattenPackageHierarchy() {
      return this == FLATTEN;
    }

    public boolean isRepackageClasses() {
      return this == REPACKAGE;
    }

    public boolean isMinification() {
      return this == MINIFICATION;
    }

    public boolean isSome() {
      return !isNone();
    }
  }

  public static class OutlineOptions {
    public boolean enabled = true;
    public int minSize = 3;
    public int maxSize = 99;
    public int threshold = 20;
    public int maxNumberOfInstructionsToBeConsidered = 100;
  }

  public static class KotlinOptimizationOptions {
    public boolean disableKotlinSpecificOptimizations =
        System.getProperty("com.android.tools.r8.disableKotlinSpecificOptimizations") != null;
  }

  // Temporary desugar specific options to make progress on b/147485959
  // All options should be including bugs to either fix the underlying issue or extend the api.
  public static class DesugarSpecificOptions {
    // b/172508621
    public boolean sortMethodsOnCfOutput =
        System.getProperty("com.android.tools.r8.sortMethodsOnCfWriting") != null;
    // Desugaring is not fully idempotent. With this option turned on all desugared input is
    // allowed, and if it is detected that the desugared input cannot be reprocessed, that input
    // will be passed-through without the problematic rewritings applied.
    public boolean allowAllDesugaredInput =
        System.getProperty("com.android.tools.r8.allowAllDesugaredInput") != null;
    // See b/191469661 for why this is here.
    public boolean noCfMarkerForDesugaredCode =
        System.getProperty("com.android.tools.r8.noCfMarkerForDesugaredCode") != null;
    // See b/182065081 for why this is here.
    public boolean lambdaClassFieldsFinal =
        System.getProperty("com.android.tools.r8.lambdaClassFieldsNotFinal") == null;
  }

  public class RewriteArrayOptions {
    // Arbitrary limit of number of inputs to new-filled-array/range.
    // The technical limit is 255 (Constants.U8BIT_MAX).
    public int minSizeForFilledNewArray = 1;
    public int maxSizeForFilledNewArrayOfReferences = 200;
    public int maxSizeForFilledNewArrayOfInts = 5;

    // Arbitrary limits of number of inputs to fill-array-data.
    public int minSizeForFilledArrayData = 2;
    public int maxSizeForFilledArrayData = 8 * 1024;

    // Check the most relaxed size range allowed.
    public boolean isPotentialSize(int size) {
      return minSizeForFilledNewArray <= size && size <= maxSizeForFilledArrayData;
    }

    // Dalvik x86-atom backend had a bug that made it crash on filled-new-array instructions for
    // arrays of objects. This is unfortunate, since this never hits arm devices, but we have
    // to disallow filled-new-array of objects for dalvik until kitkat. The buggy code was
    // removed during the jelly-bean release cycle and is not there from kitkat.
    //
    // Buggy code that accidentally call code that only works on primitives arrays.
    //
    // https://android.googlesource.com/platform/dalvik/+/ics-mr0/vm/mterp/out/InterpAsm-x86-atom.S#25106
    public boolean canUseFilledNewArrayOfStrings() {
      assert isGeneratingDex();
      return hasFeaturePresentFrom(AndroidApiLevel.K);
    }

    // When adding support for emitting new-filled-array for non-String types, ART 6.0.1 had issues.
    // https://ci.chromium.org/ui/p/r8/builders/ci/linux-android-6.0.1/6507/overview
    // It somehow had a new-array-filled return null.
    public boolean canUseFilledNewArrayOfNonStringObjects() {
      assert isGeneratingDex();
      return hasFeaturePresentFrom(AndroidApiLevel.N);
    }

    // Dalvik doesn't handle new-filled-array with arrays as values. It fails with:
    // W(629880) VFY: [Ljava/lang/Integer; is not instance of Ljava/lang/Integer;  (dalvikvm)
    public boolean canUseFilledNewArrayOfArrays() {
      assert isGeneratingDex();
      return hasFeaturePresentFrom(AndroidApiLevel.L);
    }
  }

  public class CallSiteOptimizationOptions {

    private boolean enabled = true;
    private boolean enableMethodStaticizing = true;

    private boolean forceSyntheticsForInstanceInitializers = false;

    public void disableOptimization() {
      enabled = false;
    }

    public int getMaxNumberOfInParameters() {
      return 10;
    }

    public boolean isEnabled() {
      if (!isOptimizing() || !isShrinking()) {
        return false;
      }
      return enabled;
    }

    public boolean isForceSyntheticsForInstanceInitializersEnabled() {
      return forceSyntheticsForInstanceInitializers;
    }

    public boolean isMethodStaticizingEnabled() {
      return enableMethodStaticizing;
    }

    public CallSiteOptimizationOptions setEnabled(boolean enabled) {
      if (enabled) {
        assert isEnabled();
      } else {
        disableOptimization();
      }
      return this;
    }

    public CallSiteOptimizationOptions setForceSyntheticsForInstanceInitializers(
        boolean forceSyntheticsForInstanceInitializers) {
      this.forceSyntheticsForInstanceInitializers = forceSyntheticsForInstanceInitializers;
      return this;
    }

    public CallSiteOptimizationOptions setEnableMethodStaticizing(boolean enableMethodStaticizing) {
      this.enableMethodStaticizing = enableMethodStaticizing;
      return this;
    }
  }

  public static class CfCodeAnalysisOptions {

    private boolean allowUnreachableCfBlocks = true;
    private boolean enableUnverifiableCodeReporting = false;

    public boolean isUnverifiableCodeReportingEnabled() {
      return enableUnverifiableCodeReporting;
    }

    public boolean isUnreachableCfBlocksAllowed() {
      return allowUnreachableCfBlocks;
    }

    public CfCodeAnalysisOptions setAllowUnreachableCfBlocks(boolean allowUnreachableCfBlocks) {
      this.allowUnreachableCfBlocks = allowUnreachableCfBlocks;
      return this;
    }

    public CfCodeAnalysisOptions setEnableUnverifiableCodeReporting(
        boolean enableUnverifiableCodeReporting) {
      this.enableUnverifiableCodeReporting = enableUnverifiableCodeReporting;
      return this;
    }
  }

  public class ClassInlinerOptions {

    public int classInliningInstructionAllowance = -1;

    public int getClassInliningInstructionAllowance() {
      if (classInliningInstructionAllowance >= 0) {
        return classInliningInstructionAllowance;
      }
      if (isGeneratingClassFiles()) {
        return 50;
      }
      assert isGeneratingDex();
      return 65;
    }
  }

  public interface ApplyInliningToInlineePredicate {

    boolean test(AppView<?> appView, ProgramMethod method, int inliningDepth);
  }

  public class InlinerOptions {

    public boolean enableInlining =
        !parseSystemPropertyForDevelopmentOrDefault("com.android.tools.r8.disableinlining", false);

    // This defines the limit of instructions in the inlinee
    public int simpleInliningInstructionLimit =
        parseSystemPropertyForDevelopmentOrDefault(
            "com.android.tools.r8.inliningInstructionLimit", -1);

    public int[] multiCallerInliningInstructionLimits =
        new int[] {Integer.MAX_VALUE, 28, 16, 12, 10};

    // This defines how many instructions of inlinees we can inlinee overall.
    public int inliningInstructionAllowance = 1500;

    // Maximum number of distinct values in a method that may be used in a monitor-enter
    // instruction.
    public int inliningMonitorEnterValuesAllowance = 4;

    // Maximum number of control flow resolution blocks that setup the register state before
    // the actual catch handler allowed when inlining. Threshold found empirically by testing on
    // GMS Core.
    public int inliningControlFlowResolutionBlocksThreshold = 15;

    public boolean enableInliningOfInvokesWithClassInitializationSideEffects = true;
    public boolean enableInliningOfInvokesWithNullableReceivers = true;
    public boolean disableInliningOfLibraryMethodOverrides = true;

    public ApplyInliningToInlineePredicate applyInliningToInlineePredicateForTesting = null;

    public int getSimpleInliningInstructionLimit() {
      // If a custom simple inlining instruction limit is set, then use that.
      if (simpleInliningInstructionLimit >= 0) {
        return simpleInliningInstructionLimit;
      }
      // Allow 3 instructions when generating to class files.
      if (isGeneratingClassFiles()) {
        return 3;
      }
      // Allow the size of the dex code to be up to 5 bytes.
      assert isGeneratingDex();
      return 5;
    }

    public boolean shouldApplyInliningToInlinee(
        AppView<?> appView, ProgramMethod inlinee, int inliningDepth) {
      if (applyInliningToInlineePredicateForTesting != null) {
        return applyInliningToInlineePredicateForTesting.test(appView, inlinee, inliningDepth);
      }
      if (protoShrinking.shouldApplyInliningToInlinee(appView, inlinee, inliningDepth)) {
        return true;
      }
      return false;
    }
  }

  public class HorizontalClassMergerOptions {

    // TODO(b/138781768): Set enable to true when this bug is resolved.
    private boolean enable =
        !Version.isDevelopmentVersion()
            || System.getProperty("com.android.tools.r8.disableHorizontalClassMerging") == null;
    // TODO(b/205611444): Enable by default.
    private boolean enableClassInitializerDeadlockDetection = true;
    private boolean enableInterfaceMerging =
        System.getProperty("com.android.tools.r8.enableHorizontalInterfaceMerging") != null;
    private boolean enableInterfaceMergingInInitial = false;
    private boolean enableSameFilePolicy =
        System.getProperty("com.android.tools.r8.enableSameFilePolicy") != null;
    private boolean enableSyntheticMerging = true;
    private boolean ignoreRuntimeTypeChecksForTesting = false;
    private boolean restrictToSynthetics = false;

    public void disable() {
      enable = false;
    }

    public void disableSyntheticMerging() {
      enableSyntheticMerging = false;
    }

    public void enable() {
      enable = true;
    }

    public void enableIf(boolean enable) {
      this.enable = enable;
    }

    public int getMaxClassGroupSizeInR8() {
      return 30;
    }

    public int getMaxClassGroupSizeInD8() {
      return 100;
    }

    public int getMaxInterfaceGroupSize() {
      return 100;
    }

    public boolean isConstructorMergingEnabled() {
      return true;
    }

    public boolean isClassInitializerDeadlockDetectionEnabled() {
      return enableClassInitializerDeadlockDetection;
    }

    public boolean isEnabled(HorizontalClassMerger.Mode mode) {
      if (!enable || debug || intermediate) {
        return false;
      }
      if (mode.isInitial()) {
        return inlinerOptions.enableInlining && isShrinking();
      }
      assert mode.isFinal();
      return true;
    }

    public boolean isIgnoreRuntimeTypeChecksForTestingEnabled() {
      return ignoreRuntimeTypeChecksForTesting;
    }

    public boolean isSameFilePolicyEnabled() {
      return enableSameFilePolicy;
    }

    public boolean isSyntheticMergingEnabled() {
      return enableSyntheticMerging;
    }

    public boolean isInterfaceMergingEnabled(HorizontalClassMerger.Mode mode) {
      if (!enableInterfaceMerging) {
        return false;
      }
      if (mode.isInitial()) {
        return enableInterfaceMergingInInitial;
      }
      assert mode.isFinal();
      return true;
    }

    public boolean isRestrictedToSynthetics() {
      return restrictToSynthetics || !isOptimizing() || !isShrinking();
    }

    public void setEnableClassInitializerDeadlockDetection() {
      enableClassInitializerDeadlockDetection = true;
    }

    public void setEnableInterfaceMerging() {
      enableInterfaceMerging = true;
    }

    public void setEnableInterfaceMerging(boolean enableInterfaceMerging) {
      this.enableInterfaceMerging = enableInterfaceMerging;
    }

    public void setEnableInterfaceMergingInInitial() {
      enableInterfaceMergingInInitial = true;
    }

    public void setEnableSameFilePolicy(boolean enableSameFilePolicy) {
      this.enableSameFilePolicy = enableSameFilePolicy;
    }

    public void setIgnoreRuntimeTypeChecksForTesting() {
      ignoreRuntimeTypeChecksForTesting = true;
    }

    public void setRestrictToSynthetics() {
      restrictToSynthetics = true;
    }
  }

  public static class OpenClosedInterfacesOptions {

    public interface OpenInterfaceWitnessSuppression {

      boolean isSuppressed(
          AppView<? extends AppInfoWithClassHierarchy> appView,
          TypeElement valueType,
          DexClass openInterface);
    }

    // Allow open interfaces by default. This is set to false in testing.
    private boolean allowOpenInterfaces = true;

    // When open interfaces are not allowed, compilation fails with an assertion error unless each
    // open interface witness is expected according to some suppression.
    private List<OpenInterfaceWitnessSuppression> suppressions = new ArrayList<>();

    public void disallowOpenInterfaces() {
      allowOpenInterfaces = false;
    }

    public OpenClosedInterfacesOptions suppressSingleOpenInterface(ClassReference classReference) {
      assert !allowOpenInterfaces;
      suppressions.add(
          (appView, valueType, openInterface) ->
              openInterface.getTypeName().equals(classReference.getTypeName()));
      return this;
    }

    public void suppressAllOpenInterfaces() {
      assert !allowOpenInterfaces;
      suppressions.add((appView, valueType, openInterface) -> true);
    }

    public void suppressAllOpenInterfacesDueToMissingClasses() {
      assert !allowOpenInterfaces;
      suppressions.add(
          (appView, valueType, openInterface) -> valueType.isBasedOnMissingClass(appView));
    }

    public void suppressArrayAssignmentsToJavaLangSerializable() {
      assert !allowOpenInterfaces;
      suppressions.add(
          (appView, valueType, openInterface) ->
              valueType.isArrayType()
                  && openInterface.getTypeName().equals("java.io.Serializable"));
    }

    public void suppressZipFileAssignmentsToJavaLangAutoCloseable() {
      assert !allowOpenInterfaces;
      suppressions.add(
          (appView, valueType, openInterface) ->
              valueType.isClassType()
                  && valueType
                      .asClassType()
                      .getClassType()
                      .getTypeName()
                      .equals("java.util.zip.ZipFile")
                  && openInterface.getTypeName().equals("java.lang.AutoCloseable"));
    }

    public boolean isOpenInterfacesAllowed() {
      return allowOpenInterfaces;
    }

    public boolean hasSuppressions() {
      return !suppressions.isEmpty();
    }

    public boolean isSuppressed(
        AppView<? extends AppInfoWithClassHierarchy> appView,
        TypeElement valueType,
        DexClass openInterface) {
      return allowOpenInterfaces
          || suppressions.stream()
              .anyMatch(suppression -> suppression.isSuppressed(appView, valueType, openInterface));
    }
  }

  public static class MappingComposeOptions {
    // TODO(b/241763080): Remove when enabled.
    public boolean enableExperimentalMappingComposition = false;
    // TODO(b/247136434): Disable for internal builds.
    public boolean allowNonExistingOriginalRanges = true;
    public Consumer<ClassNameMapper> generatedClassNameMapperConsumer = null;
  }

  public static class ApiModelTestingOptions {

    // Flag to specify if we should load the database or not. The api database is used for
    // library member rebinding.
    public boolean enableLibraryApiModeling =
        System.getProperty("com.android.tools.r8.disableApiModeling") == null;

    // The flag enableApiCallerIdentification controls if we can inline or merge targets with
    // different api levels. It is also the flag that specifies if we assign api levels to
    // references.
    public boolean enableApiCallerIdentification =
        System.getProperty("com.android.tools.r8.disableApiModeling") == null;
    public boolean checkAllApiReferencesAreSet =
        System.getProperty("com.android.tools.r8.disableApiModeling") == null;
    public boolean enableStubbingOfClasses =
        System.getProperty("com.android.tools.r8.disableApiModeling") == null;
    public boolean enableOutliningOfMethods =
        System.getProperty("com.android.tools.r8.disableApiModeling") == null;
    public boolean reportUnknownApiReferences =
        System.getProperty("com.android.tools.r8.reportUnknownApiReferences") != null;

    // TODO(b/232823652): Enable when we can compute the offset correctly.
    public boolean useMemoryMappedByteBuffer = false;

    // A mapping from references to the api-level introducing them.
    public Map<MethodReference, AndroidApiLevel> methodApiMapping = new HashMap<>();
    public Map<FieldReference, AndroidApiLevel> fieldApiMapping = new HashMap<>();
    public Map<ClassReference, AndroidApiLevel> classApiMapping = new HashMap<>();
    public BiConsumer<MethodReference, ComputedApiLevel> tracedMethodApiLevelCallback = null;

    public void visitMockedApiLevelsForReferences(
        DexItemFactory factory, BiConsumer<DexReference, AndroidApiLevel> apiLevelConsumer) {
      if (methodApiMapping.isEmpty() && fieldApiMapping.isEmpty() && classApiMapping.isEmpty()) {
        return;
      }
      classApiMapping.forEach(
          (classReference, apiLevel) -> {
            apiLevelConsumer.accept(factory.createType(classReference.getDescriptor()), apiLevel);
          });
      fieldApiMapping.forEach(
          (fieldReference, apiLevel) -> {
            apiLevelConsumer.accept(factory.createField(fieldReference), apiLevel);
          });
      methodApiMapping.forEach(
          (methodReference, apiLevel) -> {
            apiLevelConsumer.accept(factory.createMethod(methodReference), apiLevel);
          });
    }

    public boolean isApiLibraryModelingEnabled() {
      return enableLibraryApiModeling;
    }

    public boolean isCheckAllApiReferencesAreSet() {
      return enableLibraryApiModeling && checkAllApiReferencesAreSet;
    }

    public boolean isApiCallerIdentificationEnabled() {
      return enableLibraryApiModeling && enableApiCallerIdentification;
    }

    public void disableApiModeling() {
      enableLibraryApiModeling = false;
      enableApiCallerIdentification = false;
      enableOutliningOfMethods = false;
      enableStubbingOfClasses = false;
      checkAllApiReferencesAreSet = false;
    }

    /**
     * Disable the workarounds for missing APIs. This does not disable the use of the database, just
     * the introduction of soft-verification workarounds for potentially missing API references.
     */
    public void disableOutliningAndStubbing() {
      enableOutliningOfMethods = false;
      enableStubbingOfClasses = false;
    }

    public void disableApiCallerIdentification() {
      enableApiCallerIdentification = false;
    }

    public void disableStubbingOfClasses() {
      enableStubbingOfClasses = false;
    }

    private boolean isThrowable(AppView<?> appView, DexLibraryClass libraryClass) {
      DexClass current = libraryClass;
      while (current.getSuperType() != null) {
        DexType superType = current.getSuperType();
        if (superType == appView.dexItemFactory().throwableType) {
          return true;
        }
        current = appView.definitionFor(current.getSuperType());
      }
      return false;
    }
  }

  public static class ProtoShrinkingOptions {

    public boolean enableGeneratedExtensionRegistryShrinking = false;
    public boolean enableGeneratedMessageLiteShrinking = false;
    public boolean enableGeneratedMessageLiteBuilderShrinking = false;
    public boolean traverseOneOfAndRepeatedProtoFields = false;
    public boolean enableEnumLiteProtoShrinking = false;
    // Breaks the Chrome build if this is not enabled because of MethodToInvoke switchMaps.
    // See b/174530756 for more details.
    public boolean enableProtoEnumSwitchMapShrinking = true;

    public void disable() {
      enableGeneratedExtensionRegistryShrinking = false;
      enableGeneratedMessageLiteShrinking = false;
      enableGeneratedMessageLiteBuilderShrinking = false;
      traverseOneOfAndRepeatedProtoFields = false;
      enableEnumLiteProtoShrinking = false;
    }

    public boolean enableRemoveProtoEnumSwitchMap() {
      return isProtoShrinkingEnabled() && enableProtoEnumSwitchMapShrinking;
    }

    public boolean isProtoShrinkingEnabled() {
      return enableGeneratedExtensionRegistryShrinking
          || enableGeneratedMessageLiteShrinking
          || enableGeneratedMessageLiteBuilderShrinking
          || enableEnumLiteProtoShrinking;
    }

    public boolean isEnumLiteProtoShrinkingEnabled() {
      return enableEnumLiteProtoShrinking;
    }

    public boolean shouldApplyInliningToInlinee(
        AppView<?> appView, ProgramMethod inlinee, int inliningDepth) {
      if (isProtoShrinkingEnabled() && inliningDepth == 1) {
        ProtoReferences protoReferences = appView.protoShrinker().getProtoReferences();
        return inlinee.getHolderType() == protoReferences.generatedMessageLiteType;
      }
      return false;
    }
  }

  public static class TestingOptions {

    // If false, use the desugared library implementation when desugared library is enabled.
    public boolean alwaysBackportListSetMapMethods = true;
    public boolean neverReuseCfLocalRegisters = false;
    public boolean roundtripThroughLIR = false;
    public boolean checkReceiverAlwaysNullInCallSiteOptimization = true;
    private boolean hasReadCheckDeterminism = false;
    private DeterminismChecker determinismChecker = null;
    public boolean usePcEncodingInCfForTesting = false;
    public boolean dexContainerExperiment =
        System.getProperty("com.android.tools.r8.dexContainerExperiment") != null;

    // Testing options to analyse locality of items in DEX files when they are generated.
    public boolean calculateItemUseCountInDex = false;
    public boolean calculateItemUseCountInDexDumpSingleUseStrings = false;

    private DeterminismChecker getDeterminismChecker() {
      // Lazily read the env-var so that it can be set after options init.
      if (determinismChecker == null && !hasReadCheckDeterminism) {
        hasReadCheckDeterminism = true;
        String dir = System.getProperty("com.android.tools.r8.checkdeterminism");
        if (dir != null) {
          setDeterminismChecker(DeterminismChecker.createWithFileBacking(Paths.get(dir)));
        }
      }
      return determinismChecker;
    }

    public void setDeterminismChecker(DeterminismChecker checker) {
      determinismChecker = checker;
    }

    public void checkDeterminism(AppView<?> appView) {
      DeterminismChecker determinismChecker = getDeterminismChecker();
      if (determinismChecker != null) {
        determinismChecker.check(appView);
      }
    }

    public <E extends Exception> void checkDeterminism(
        ThrowingConsumer<DeterminismChecker, E> consumer) {
      DeterminismChecker determinismChecker = getDeterminismChecker();
      if (determinismChecker != null) {
        consumer.acceptWithRuntimeException(determinismChecker);
      }
    }

    public static int NO_LIMIT = -1;

    public ArgumentPropagatorEventConsumer argumentPropagatorEventConsumer =
        ArgumentPropagatorEventConsumer.emptyConsumer();

    public Predicate<DexProgramClass> isEligibleForBridgeHoisting = Predicates.alwaysTrue();

    // Force writing the specified bytes as the DEX version content.
    public byte[] forceDexVersionBytes = null;

    public IROrdering irOrdering =
        InternalOptions.assertionsEnabled() && !InternalOptions.DETERMINISTIC_DEBUGGING
            ? NondeterministicIROrdering.getInstance()
            : IdentityIROrdering.getInstance();

    public BiFunction<MixedSectionLayoutStrategy, VirtualFile, MixedSectionLayoutStrategy>
        mixedSectionLayoutStrategyInspector = (strategy, virtualFile) -> strategy;

    public void setMixedSectionLayoutStrategyInspector(
        BiFunction<MixedSectionLayoutStrategy, VirtualFile, MixedSectionLayoutStrategy>
            mixedSectionLayoutStrategyInspector) {
      this.mixedSectionLayoutStrategyInspector = mixedSectionLayoutStrategyInspector;
    }

    public BiConsumer<AppInfoWithLiveness, Enqueuer.Mode> enqueuerInspector = null;

    public Consumer<String> processingContextsConsumer = null;

    public Function<AppView<AppInfoWithLiveness>, RepackagingConfiguration>
        repackagingConfigurationFactory = DefaultRepackagingConfiguration::new;

    public BiConsumer<DexItemFactory, HorizontallyMergedClasses> horizontallyMergedClassesConsumer =
        ConsumerUtils.emptyBiConsumer();
    public Function<List<Policy>, List<Policy>> horizontalClassMergingPolicyRewriter =
        Function.identity();
    public TriFunction<AppView<?>, Iterable<DexProgramClass>, DexProgramClass, DexProgramClass>
        horizontalClassMergingTarget = (appView, candidates, target) -> target;

    public BiConsumer<DexItemFactory, EnumDataMap> unboxedEnumsConsumer =
        ConsumerUtils.emptyBiConsumer();

    public BiConsumer<DexItemFactory, VerticallyMergedClasses> verticallyMergedClassesConsumer =
        ConsumerUtils.emptyBiConsumer();

    public Consumer<Deque<ProgramMethodSet>> waveModifier = waves -> {};

    public Consumer<DebugRepresentation> debugRepresentationCallback = null;

    /**
     * If this flag is enabled, we will also compute the set of possible targets for invoke-
     * interface and invoke-virtual instructions that target a library method, and add the
     * corresponding edges to the call graph.
     *
     * <p>Setting this flag leads to more call graph edges, which can be good for size (e.g., it
     * increases the likelihood that virtual methods have been processed by the time their call
     * sites are processed, which allows more inlining).
     *
     * <p>However, the set of possible targets for such invokes can be very large. As an example,
     * consider the instruction {@code invoke-virtual {v0, v1}, `void Object.equals(Object)`}).
     * Therefore, tracing such invokes comes at a considerable performance penalty.
     */
    public boolean addCallEdgesForLibraryInvokes = false;

    public boolean allowCheckDiscardedErrors = false;
    public boolean allowClassInliningOfSynthetics = true;
    public boolean allowInjectedAnnotationMethods = false;
    public boolean allowInliningOfSynthetics = true;
    public boolean allowTypeErrors =
        !Version.isDevelopmentVersion()
            || System.getProperty("com.android.tools.r8.allowTypeErrors") != null;
    public boolean allowInvokeErrors = false;
    public boolean allowUnnecessaryDontWarnWildcards = true;
    public boolean allowUnusedDontWarnRules = true;
    public boolean alwaysUseExistingAccessInfoCollectionsInMemberRebinding = true;
    public boolean alwaysUsePessimisticRegisterAllocation = false;
    public boolean enableCheckCastAndInstanceOfRemoval = true;
    public boolean enableDeadSwitchCaseElimination = true;
    public boolean enableInvokeSuperToInvokeVirtualRewriting = true;
    public boolean enableMultiANewArrayDesugaringForClassFiles = false;
    public boolean enableRetargetingConstructorBridgeCalls = false;
    public boolean enableSwitchToIfRewriting = true;
    public boolean enableEnumUnboxingDebugLogs =
        System.getProperty("com.android.tools.r8.enableEnumUnboxingDebugLogs") != null;
    public boolean forceRedundantConstNumberRemoval = false;
    public boolean enableExperimentalDesugaredLibraryKeepRuleGenerator = false;
    public boolean invertConditionals = false;
    public boolean placeExceptionalBlocksLast = false;
    public boolean forceJumboStringProcessing = false;
    public boolean forcePcBasedEncoding = false;
    public int pcBasedDebugEncodingOverheadThreshold =
        System.getProperty("com.android.tools.r8.pc2pcOverheadThreshold") != null
            ? Integer.parseInt(System.getProperty("com.android.tools.r8.pc2pcOverheadThreshold"))
            : 200000;
    public Set<Inliner.Reason> validInliningReasons = null;
    public boolean noLocalsTableOnInput = false;
    public boolean forceNameReflectionOptimization = false;
    public boolean enableNarrowAndWideningingChecksInD8 = false;
    public BiConsumer<IRCode, AppView<?>> irModifier = null;
    public Consumer<IRCode> inlineeIrModifier = null;
    public int basicBlockMuncherIterationLimit = NO_LIMIT;
    public boolean dontReportFailingCheckDiscarded = false;
    public boolean disableRecordApplicationReaderMap = false;
    public PrintStream whyAreYouNotInliningConsumer = System.out;
    public boolean trackDesugaredAPIConversions =
        System.getProperty("com.android.tools.r8.trackDesugaredAPIConversions") != null;
    public boolean enumUnboxingRewriteJavaCGeneratedMethod = false;
    // TODO(b/154793333): Enable assertions always when resolved.
    public boolean assertConsistentRenamingOfSignature = false;
    public boolean allowStaticInterfaceMethodsForPreNApiLevel = false;
    public int verificationSizeLimitInBytesOverride = -1;
    public boolean forceIRForCfToCfDesugar =
        System.getProperty("com.android.tools.r8.forceIRForCfToCfDesugar") != null;
    public boolean disableMappingToOriginalProgramVerification = false;
    public boolean allowInvalidCfAccessFlags =
        System.getProperty("com.android.tools.r8.allowInvalidCfAccessFlags") != null;
    public boolean verifyInputs = System.getProperty("com.android.tools.r8.verifyInputs") != null;
    // TODO(b/177333791): Set to true
    public boolean checkForNotExpandingMainDexTracingResult = false;
    public Set<String> allowedUnusedDontWarnPatterns = new HashSet<>();
    public boolean enableTestAssertions =
        System.getProperty("com.android.tools.r8.enableTestAssertions") != null;
    public boolean disableMarkingMethodsFinal =
        System.getProperty("com.android.tools.r8.disableMarkingMethodsFinal") != null;
    public boolean disableMarkingClassesFinal =
        System.getProperty("com.android.tools.r8.disableMarkingClassesFinal") != null;
    public boolean testEnableTestAssertions = false;
    public boolean keepMetadataInR8IfNotRewritten = true;

    // If set, pruned record fields are not used in hashCode/equals/toString and toString prints
    // minified field names instead of original field names.
    public boolean enableRecordModeling = true;

    // Flag to allow processing of resources in D8. A data resource consumer still needs to be
    // specified.
    public boolean enableD8ResourcesPassThrough = false;

    // TODO(b/144781417): This is disabled by default as some test apps appear to have such classes.
    public boolean allowNonAbstractClassesWithAbstractMethods = true;

    public boolean verifyKeptGraphInfo = false;

    public boolean readInputStackMaps = true;
    public boolean disableStackMapVerification = false;

    public boolean disableShortenLiveRanges = false;

    // Option for testing outlining with interface array arguments, see b/132420510.
    public boolean allowOutlinerInterfaceArrayArguments = false;

    public int limitNumberOfClassesPerDex = -1;

    public MinifierTestingOptions minifier = new MinifierTestingOptions();

    // Testing hooks to trigger effects in various compiler places.
    public Runnable hookInIrConversion = null;

    public static class MinifierTestingOptions {

      public Comparator<DexMethod> interfaceMethodOrdering = null;

      public Comparator<Wrapper<DexEncodedMethod>> getInterfaceMethodOrderingOrDefault(
          Comparator<Wrapper<DexEncodedMethod>> comparator) {
        if (interfaceMethodOrdering != null) {
          return (a, b) ->
              interfaceMethodOrdering.compare(a.get().getReference(), b.get().getReference());
        }
        return comparator;
      }
    }

    public boolean measureProguardIfRuleEvaluations = false;
    public ProguardIfRuleEvaluationData proguardIfRuleEvaluationData =
        new ProguardIfRuleEvaluationData();

    public static class ProguardIfRuleEvaluationData {

      public int numberOfProguardIfRuleClassEvaluations = 0;
      public int numberOfProguardIfRuleMemberEvaluations = 0;
    }

    public Consumer<ProgramMethod> callSiteOptimizationInfoInspector =
        ConsumerUtils.emptyConsumer();

    public Predicate<DexMethod> cfByteCodePassThrough = null;

    public boolean enableExperimentalMapFileVersion = false;

    public boolean alwaysGenerateLambdaFactoryMethods = false;
  }

  public MapVersion getMapFileVersion() {
    return testing.enableExperimentalMapFileVersion
        ? MapVersion.MAP_VERSION_EXPERIMENTAL
        : MapVersion.STABLE;
  }

  @VisibleForTesting
  public void disableNameReflectionOptimization() {
    // Use this util to disable get*Name() computation if the main intention of tests is checking
    // const-class, e.g., canonicalization, or some test classes' only usages are get*Name().
    enableNameReflectionOptimization = false;
  }

  private boolean hasMinApi(AndroidApiLevel level) {
    return getMinApiLevel().isGreaterThanOrEqualTo(level);
  }

  /**
   * Predicate to guard on the support of a language feature.
   *
   * <p>Note that if not desugaring or compiling to DEX, then the output is a mapping of the input
   * and thus all parts should be representable (assuming the compiler has support for them).
   */
  private boolean hasFeaturePresentFrom(AndroidApiLevel level) {
    if (desugarState.isOn() || isGeneratingDex()) {
      return level != null && hasMinApi(level);
    }
    // If not desugaring and not compiling to DEX, then the API level is effectively ignored and
    // we assume that everything in the input is supported in the output.
    assert minApiLevel.equals(B);
    return true;
  }

  /**
   * Predicate to guard against the possible presence of a VM bug.
   *
   * <p>Note that if the compilation is not desugaring to a min-api or targeting DEX at a min-api,
   * then the bug is assumed to be present as the CF output could be futher compiled to any target.
   */
  private boolean canHaveBugPresentUntil(AndroidApiLevel level) {
    if (desugarState.isOn() || isGeneratingDex()) {
      return level == null || !hasMinApi(level);
    }
    assert minApiLevel.equals(B);
    return true;
  }

  /**
   * Allow access modification of synthetic lambda implementation methods in D8 to avoid generating
   * an excessive amount of accessibility bridges. In R8, the lambda implementation methods are
   * inlined into the synthesized accessibility bridges, thus we don't allow access modification.
   */
  public boolean canAccessModifyLambdaImplementationMethods(AppView<?> appView) {
    return !appView.enableWholeProgramOptimizations();
  }

  /**
   * Dex2Oat issues a warning for abstract methods on non-abstract classes, so we never allow this.
   *
   * <p>Note that having an invoke instruction that targets an abstract method on a non-abstract
   * class will fail with a verification error on Dalvik. Therefore, this must not be more
   * permissive than {@code return minApiLevel >= AndroidApiLevel.L.getLevel()}.
   *
   * <p>See b/132953944.
   */
  @SuppressWarnings("ConstantConditions")
  public boolean canUseAbstractMethodOnNonAbstractClass() {
    boolean result = false;
    assert !(result && canHaveDalvikAbstractMethodOnNonAbstractClassVerificationBug());
    return result;
  }

  public boolean canUseConstClassInstructions(CfVersion cfVersion) {
    assert isGeneratingClassFiles();
    return cfVersion.isGreaterThanOrEqualTo(requiredCfVersionForConstClassInstructions());
  }

  public CfVersion requiredCfVersionForConstClassInstructions() {
    assert isGeneratingClassFiles();
    return CfVersion.V1_5;
  }

  public static AndroidApiLevel invokePolymorphicOnMethodHandleApiLevel() {
    return AndroidApiLevel.O;
  }

  public boolean canUseInvokePolymorphicOnMethodHandle() {
    return hasFeaturePresentFrom(invokePolymorphicOnMethodHandleApiLevel());
  }

  public static AndroidApiLevel invokePolymorphicOnVarHandleApiLevel() {
    return AndroidApiLevel.P;
  }

  public boolean canUseInvokePolymorphicOnVarHandle() {
    return hasFeaturePresentFrom(invokePolymorphicOnMethodHandleApiLevel());
  }

  public static AndroidApiLevel constantMethodHandleApiLevel() {
    return AndroidApiLevel.P;
  }

  public boolean canUseConstantMethodHandle() {
    return hasFeaturePresentFrom(constantMethodHandleApiLevel());
  }

  public static AndroidApiLevel constantMethodTypeApiLevel() {
    return AndroidApiLevel.P;
  }

  public boolean canUseConstantMethodType() {
    return hasFeaturePresentFrom(constantMethodTypeApiLevel());
  }

  public static AndroidApiLevel invokeCustomApiLevel() {
    return AndroidApiLevel.O;
  }

  public boolean canUseInvokeCustom() {
    return hasFeaturePresentFrom(invokeCustomApiLevel());
  }

  public static AndroidApiLevel constantDynamicApiLevel() {
    return null;
  }

  public boolean canUseConstantDynamic() {
    return hasFeaturePresentFrom(constantDynamicApiLevel());
  }

  public static AndroidApiLevel defaultAndStaticInterfaceMethodsApiLevel() {
    return AndroidApiLevel.N;
  }

  public static AndroidApiLevel defaultInterfaceMethodsApiLevel() {
    return defaultAndStaticInterfaceMethodsApiLevel();
  }

  public static AndroidApiLevel staticInterfaceMethodsApiLevel() {
    return defaultAndStaticInterfaceMethodsApiLevel();
  }

  public boolean canUseDefaultAndStaticInterfaceMethods() {
    return hasFeaturePresentFrom(defaultInterfaceMethodsApiLevel());
  }

  public static AndroidApiLevel privateInterfaceMethodsApiLevel() {
    return AndroidApiLevel.N;
  }

  public boolean canUsePrivateInterfaceMethods() {
    return hasFeaturePresentFrom(privateInterfaceMethodsApiLevel());
  }

  public static AndroidApiLevel varHandleApiLevel() {
    return AndroidApiLevel.T;
  }

  public boolean canUseVarHandle() {
    return hasFeaturePresentFrom(varHandleApiLevel());
  }

  public boolean canUseNestBasedAccess() {
    return hasFeaturePresentFrom(null) || emitNestAnnotationsInDex;
  }

  public boolean canUseRecords() {
    return hasFeaturePresentFrom(null) || emitRecordAnnotationsInDex;
  }

  public boolean canUseSealedClasses() {
    return hasFeaturePresentFrom(null) || emitPermittedSubclassesAnnotationsInDex;
  }

  public boolean canLeaveStaticInterfaceMethodInvokes() {
    return hasFeaturePresentFrom(AndroidApiLevel.L);
  }

  public boolean canUseTwrCloseResourceMethod() {
    return hasFeaturePresentFrom(AndroidApiLevel.K);
  }

  public boolean canUseSpacesInSimpleName() {
    return itemFactory.getSkipNameValidationForTesting()
        || hasFeaturePresentFrom(AndroidApiLevel.R);
  }

  public boolean enableBackportedMethodRewriting() {
    return desugarState.isOn();
  }

  public boolean enableTryWithResourcesDesugaring() {
    switch (tryWithResourcesDesugaring) {
      case Off:
        return false;
      case Auto:
        return desugarState.isOn() && !canUseTwrCloseResourceMethod();
    }
    throw new Unreachable();
  }

  // Debug entries may be dropped only if the source file content allows being omitted from
  // stack traces, or if the VM will report the source file even with a null valued debug info.
  public boolean allowDiscardingResidualDebugInfo() {
    // TODO(b/146565491): We can drop debug info once fixed at a known min-api.
    return sourceFileProvider != null && sourceFileProvider.allowDiscardingSourceFile();
  }

  public boolean canUseDexPc2PcAsDebugInformation() {
    return isGeneratingDex() && lineNumberOptimization == LineNumberOptimization.ON;
  }

  public boolean canUseNativeDexPcInsteadOfDebugInfo() {
    return canUseDexPc2PcAsDebugInformation()
        && hasMinApi(AndroidApiLevel.O)
        && allowDiscardingResidualDebugInfo();
  }

  public boolean isInterfaceMethodDesugaringEnabled() {
    // This condition is to filter out tests that never set program consumer.
    if (!hasConsumer()) {
      return false;
    }
    return desugarState.isOn()
        && interfaceMethodDesugaring == OffOrAuto.Auto
        && !canUseDefaultAndStaticInterfaceMethods();
  }

  public boolean isSwitchRewritingEnabled() {
    return enableSwitchRewriting && !debug;
  }

  public boolean isStringSwitchConversionEnabled() {
    return enableStringSwitchConversion && !debug;
  }

  public boolean canUseMultidex() {
    assert isGeneratingDex();
    return intermediate || hasMinApi(AndroidApiLevel.L);
  }

  public boolean canUseJavaUtilObjects() {
    return hasFeaturePresentFrom(AndroidApiLevel.K);
  }

  public boolean canUseJavaUtilObjectsIsNull() {
    return hasFeaturePresentFrom(AndroidApiLevel.N);
  }

  public boolean canUseSuppressedExceptions() {
    // TODO(b/214239152): Suppressed exceptions are @hide from at least 4.0.1 / Android I / API 14.
    return hasFeaturePresentFrom(AndroidApiLevel.K);
  }

  public boolean canUseAssertionErrorTwoArgumentConstructor() {
    return hasFeaturePresentFrom(AndroidApiLevel.K);
  }

  public CfVersion classFileVersionAfterDesugaring(CfVersion version) {
    assert isGeneratingClassFiles();
    if (!isDesugaring()) {
      return version;
    }
    CfVersion maxVersionAfterDesugar =
        canUseDefaultAndStaticInterfaceMethods() ? CfVersion.V1_8 : CfVersion.V1_7;
    return Ordered.min(maxVersionAfterDesugar, version);
  }

  // The Apache Harmony-based AssertionError constructor which takes an Object on API 15 and older
  // calls the Error supertype constructor with null as the exception cause. This prevents
  // subsequent calls to initCause() because its implementation checks that cause==this before
  // allowing a cause to be set.
  //
  // https://android.googlesource.com/platform/libcore/+/refs/heads/ics-mr1/luni/src/main/java/java/lang/AssertionError.java#56
  public boolean canInitCauseAfterAssertionErrorObjectConstructor() {
    return hasFeaturePresentFrom(AndroidApiLevel.J);
  }

  // Art had a bug (b/68761724) for Android N and O in the arm32 interpreter
  // where an aget-wide instruction using the same register for the array
  // and the first register of the result could lead to the wrong exception
  // being thrown on out of bounds.
  public boolean canUseSameArrayAndResultRegisterInArrayGetWide() {
    return hasFeaturePresentFrom(AndroidApiLevel.P);
  }

  // Some Lollipop versions of Art found in the wild perform invalid bounds
  // check elimination. There is a fast path of loops and a slow path.
  // The bailout to the slow path is performed too early and therefore
  // the array-index variable might not be defined in the slow path code leading
  // to use of undefined registers as indices into arrays. The result
  // is ArrayIndexOutOfBounds exceptions.
  //
  // In an attempt to help these Art VMs, all single-width constants are initialized and not moved.
  //
  // There is no guarantee that this works, but it does make the problem
  // disappear on the one known instance of this problem.
  //
  // See b/69364976 and b/77996377.
  public boolean canHaveBoundsCheckEliminationBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.M);
  }

  // MediaTek JIT compilers for KitKat phones did not implement the not
  // instruction as it was not generated by DX. Therefore, apps containing
  // not instructions would crash if the code was JIT compiled. Therefore,
  // we can only use not instructions if we are targeting Art-based
  // phones.
  public boolean canUseNotInstruction() {
    return hasFeaturePresentFrom(AndroidApiLevel.L);
  }

  // Art before M has a verifier bug where the type of the contents of the receiver register is
  // assumed to not change. If the receiver register is reused for something else the verifier
  // will fail and the code will not run.
  public boolean canHaveThisTypeVerifierBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.M);
  }

  // Art crashes if we do dead reference elimination of the receiver in release mode and Art
  // is asked for the |this| object over a JDWP connection at a point where the receiver
  // register has been clobbered.
  //
  // See b/116683601 and b/116837585.
  public boolean canHaveThisJitCodeDebuggingBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.Q);
  }

  // The dalvik jit had a bug where the long operations add, sub, or, xor and and would write
  // the first part of the result long before reading the second part of the input longs.
  public boolean canHaveOverlappingLongRegisterBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.L);
  }

  // Some dalvik versions found in the wild perform invalid JIT compilation of cmp-long
  // instructions where the result register overlaps with the input registers.
  // See b/74084493.
  //
  // The same dalvik versions also have a bug where the JIT compilation of code such as:
  //
  // void method(long l) {
  //  if (l < 0) throw new RuntimeException("less than");
  //  if (l == 0) throw new RuntimeException("equal");
  // }
  //
  // Will enter the case for l==0 even when l is non-zero. The code generated for this is of
  // the form:
  //
  // 0:   0x00: ConstWide16         v0, 0x0000000000000000 (0)
  // 1:   0x02: CmpLong             v2, v4, v0
  // 2:   0x04: IfLtz               v2, 0x0c (+8)
  // 3:   0x06: IfNez               v2, 0x0a (+4)
  //
  // However, the jit apparently clobbers the input register in the IfLtz instruction. Therefore,
  // for dalvik VMs we have to instead generate the following code:
  //
  // 0:   0x00: ConstWide16         v0, 0x0000000000000000 (0)
  // 1:   0x02: CmpLong             v2, v4, v0
  // 2:   0x04: IfLtz               v2, 0x0e (+10)
  // 3:   0x06: CmpLong             v2, v4, v0
  // 4:   0x08: IfNez               v2, 0x0c (+4)
  //
  // See b/75408029.
  public boolean canHaveCmpLongBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.L);
  }

  // Some Lollipop VMs crash if there is a const instruction between a cmp and an if instruction.
  //
  // Crashing code:
  //
  //    :goto_0
  //    cmpg-float v0, p0, p0
  //    const/4 v1, 0
  //    if-gez v0, :cond_0
  //    add-float/2addr p0, v1
  //    goto :goto_0
  //    :cond_0
  //    return p0
  //
  // Working code:
  //    :goto_0
  //    const/4 v1, 0
  //    cmpg-float v0, p0, p0
  //    if-gez v0, :cond_0
  //    add-float/2addr p0, v1
  //    goto :goto_0
  //    :cond_0
  //    return p0
  //
  // See b/115552239.
  public boolean canHaveCmpIfFloatBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.M);
  }

  // Some Lollipop VMs incorrectly optimize code with mul2addr instructions. In particular,
  // the following hash code method produces wrong results after optimizations:
  //
  //    0:   0x00: IgetObject          v0, v3, Field java.lang.Class MultiClassKey.first
  //    1:   0x02: InvokeVirtual       { v0 } Ljava/lang/Object;->hashCode()I
  //    2:   0x05: MoveResult          v0
  //    3:   0x06: Const16             v1, 0x001f (31)
  //    4:   0x08: MulInt2Addr         v1, v0
  //    5:   0x09: IgetObject          v2, v3, Field java.lang.Class MultiClassKey.second
  //    6:   0x0b: InvokeVirtual       { v2 } Ljava/lang/Object;->hashCode()I
  //    7:   0x0e: MoveResult          v2
  //    8:   0x0f: AddInt2Addr         v1, v2
  //    9:   0x10: Return              v1
  //
  // It seems that the issue is the MulInt2Addr instructions. Avoiding that, the VM computes
  // hash codes correctly also after optimizations.
  //
  // This issue has only been observed on a Verizon Ellipsis 8 tablet. See b/76115465.
  public boolean canHaveMul2AddrBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.M);
  }

  // Some Marshmallow VMs create an incorrect doubly-linked list of instructions. When the VM
  // attempts to create a fixup for a Cortex 53 long add/sub issue, it may diverge due to the cyclic
  // list.
  //
  // See b/77842465.
  public boolean canHaveDex2OatLinkedListBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.N);
  }

  // dex2oat on Marshmallow VMs does aggressive inlining which can eat up all the memory on
  // devices for self-recursive methods.
  //
  // See b/111960171
  public boolean canHaveDex2OatInliningIssue() {
    return canHaveBugPresentUntil(AndroidApiLevel.N);
  }

  // Art 7.0.0 and later Art JIT may perform an invalid optimization if a string new-instance does
  // not flow directly to the init call.
  //
  // See b/78493232 and b/80118070.
  public boolean canHaveArtStringNewInitBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.Q);
  }

  // Dalvik tracing JIT may perform invalid optimizations when int/float values are converted to
  // double and used in arithmetic operations.
  //
  // See b/77496850.
  public boolean canHaveNumberConversionRegisterAllocationBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.L);
  }

  // Some Lollipop mediatek VMs have a peculiar bug where the inliner crashes if there is a
  // simple constructor that just forwards its arguments to the super constructor. Strangely,
  // this happens only for specific signatures: so far the only reproduction we have is for
  // a constructor accepting two doubles and one object.
  //
  // To workaround this we insert a materializing const instruction before the super init
  // call. Having a temporary register seems to disable the buggy optimizations.
  //
  // See b/68378480.
  public boolean canHaveForwardingInitInliningBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.M);
  }

  // Some Lollipop x86_64 VMs have a bug causing a segfault if an exception handler directly targets
  // a conditional-loop header. This cannot happen for debug builds as the existence of a
  // move-exception instruction will ensure a non-direct target.
  //
  // To workaround this in release builds, we insert a materializing nop instruction in the
  // exception handler forcing it not directly target any loop header.
  //
  // See b/111337896.
  public boolean canHaveExceptionTargetingLoopHeaderBug() {
    assert isGeneratingDex();
    return !debug && canHaveBugPresentUntil(AndroidApiLevel.M);
  }

  // The Dalvik tracing JIT can trace past the end of the instruction stream and end up
  // parsing non-code bytes as code (typically leading to a crash). See b/117907456.
  //
  // In order to workaround this we insert a goto past the throw, and another goto after the throw
  // jumping back to the throw.

  // We used to insert a empty loop at the end, however, mediatek has an optimizer
  // on lollipop devices that cannot deal with an unreachable infinite loop, so we
  // couldn't do that. See b/119895393.
  // We also could not insert any dead code (e.g. a return) because that would make mediatek
  // dominator calculations on 7.0.0 crash. See b/128926846.
  public boolean canHaveTracingPastInstructionsStreamBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.L);
  }

  // The art verifier incorrectly propagates type information for the following pattern:
  //
  //  move vA, vB
  //  instance-of vB, vA, Type
  //  if-eqz/nez vB
  //
  // In that case it will assume that vB has object type after the if. Therefore, if the
  // result of the instance-of operation is reused in a boolean context the verifier will
  // fail with a type conflict.
  //
  // In order to make sure that cannot happen, we insert a nop between the move and
  // the instance-of instruction so that this pattern in the art verifier does not
  // match.
  //
  //  move vA, vB
  //  nop
  //  instance-of vB, vA, Type
  //  if-eqz/nez vB
  //
  // This happens rarely, but it can happen in debug mode where the move
  // put a value into a new register which has associated locals information.
  //
  // Fixed in Android Q, see b/120985556.
  public boolean canHaveArtInstanceOfVerifierBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.Q);
  }

  // Some Art Lollipop version do not deal correctly with long-to-int conversions.
  //
  // In particular, the following code performs an out of bounds array access when the
  // long loaded from the long array is very large (has non-zero values in the upper 32 bits).
  //
  //   aget-wide v9, v3, v1
  //   long-to-int v9, v9
  //   aget-wide v10, v3, v9
  //
  // The issue seems to be that the higher bits of the 64-bit register holding the long
  // are not cleared and the integer is therefore a 64-bit integer that is not truncated
  // to 32 bits.
  //
  // As a workaround, we do not allow long-to-int to have the same source and target register
  // for min-apis where lollipop devices could be targeted.
  //
  // See b/80262475.
  public boolean canHaveLongToIntBug() {
    // We have only seen this happening on Lollipop arm64 backends. We have tested on
    // Marshmallow and Nougat arm64 devices and they do not have the bug.
    return canHaveBugPresentUntil(AndroidApiLevel.M);
  }

  // The Art VM for Android N through P has a bug in the JIT that means that if the same
  // exception block with a move-exception instruction is targeted with more than one type
  // of exception the JIT will incorrectly assume that the exception object has one of these
  // types and will optimize based on that one type instead of taking all the types into account.
  //
  // In order to workaround that, we always generate distinct move-exception instructions for
  // distinct dex types.
  //
  // See b/120164595.
  public boolean canHaveExceptionTypeBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.Q);
  }

  // Art 4.0.4 fails with a verification error when a null-literal is being passed directly to an
  // aget instruction. We therefore need to be careful when performing trivial check-cast
  // elimination of check-cast instructions where the value being cast is the constant null.
  // See b/123269162.
  public boolean canHaveArtCheckCastVerifierBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.J);
  }

  // The verifier will merge A[] and B[] to Object[], even when both A and B implement an interface
  // I, i.e., the join should have been I[]. This can lead to verification errors when the value is
  // used as an I[].
  //
  // See b/69826014.
  public boolean canHaveIncorrectJoinForArrayOfInterfacesBug() {
    return true;
  }

  // The dalvik verifier will crash the program if there is a try catch block with an exception
  // type that does not exist.
  // We don't do anything special about this, except that we don't inline methods that have a
  // catch handler with the ReflectiveOperationException type, i.e., if the program did not crash
  // in the non R8 case it should not in the R8 case.
  // Currently we handle only the ReflectiveOperationException, but there could be other exceptions.
  // We do this for all pre art version, in case we add more Exception types later on. The
  // problem is there for all dalvik vms, but the exception was added in api level 19
  // so we don't see it there.
  //
  // See b/131349148
  public boolean canHaveDalvikCatchHandlerVerificationBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.L);
  }

  // Having an invoke instruction that targets an abstract method on a non-abstract class will fail
  // with a verification error.
  //
  // See b/132953944.
  public boolean canHaveDalvikAbstractMethodOnNonAbstractClassVerificationBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.L);
  }

  // On dalvik we see issues when using an int value in places where a boolean, byte, char, or short
  // is expected.
  //
  // For example, if we inline the following method into the call site:
  //   public int value;
  //   public boolean getValue() {
  //     return value;
  //   }
  //
  // See also b/134304597 and b/124152497.
  public boolean canHaveDalvikIntUsedAsNonIntPrimitiveTypeBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.L);
  }

  // The standard library prior to API 19 did not contain a ZipFile that implemented Closable.
  //
  // See b/177532008.
  public boolean canHaveZipFileWithMissingCloseableBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.K);
  }

  // Some versions of Dalvik had a bug where a switch with a MAX_INT key would still go to
  // the default case when switching on the value MAX_INT.
  //
  // See b/177790310.
  public boolean canHaveSwitchMaxIntBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.K);
  }

  // On Dalvik the methods Integer.parseInt and Long.parseLong does not support strings with a '+'
  // prefix
  //
  // See b/182137865.
  public boolean canParseNumbersWithPlusPrefix() {
    return hasFeaturePresentFrom(AndroidApiLevel.L);
  }

  // Lollipop and Marshmallow devices do not correctly handle invoke-super when the static holder
  // is higher up in the hierarchy than the method that the invoke-super should resolve to.
  //
  // See b/215573892.
  public boolean canHaveSuperInvokeBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.N);
  }

  // Some Dalvik and Art MVs does not support interface invokes to Object
  // members not explicitly defined on the symbolic reference of the
  // interface invoke. In these cases rewrite to a virtual invoke with
  // the symbolic reference java.lang.Object.
  //
  // The support was added in Android O, however at least for j.l.CharSequence.equals the handling
  // in Art was incorrect (b/231450655).
  //
  // javac started generating code like this with the fix for JDK-8272564, which will be part of
  // JDK 18.
  //
  // See b/218298666.
  public boolean canHaveInvokeInterfaceToObjectMethodBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.P);
  }

  // Until we fully drop support for API levels < 16, we have to emit an empty annotation set to
  // work around a DALVIK bug. See b/36951668.
  public boolean canHaveDalvikEmptyAnnotationSetBug() {
    return canHaveBugPresentUntil(AndroidApiLevel.J_MR1);
  }

  public boolean canHaveNonReboundConstructorInvoke() {
    // TODO(b/246679983): Turned off while diagnosing b/246679983.
    return false && isGeneratingDex() && minApiLevel.isGreaterThanOrEqualTo(AndroidApiLevel.L);
  }

  // b/238399429 Some art 6 vms have issues with multiple monitors in the same method
  // Don't inline code with monitors into methods that already have monitors.
  public boolean canHaveIssueWithInlinedMonitors() {
    return canHaveBugPresentUntil(AndroidApiLevel.N);
  }
}
