// 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.google.common.base.Predicates.not;

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.ProgramConsumer;
import com.android.tools.r8.StringConsumer;
import com.android.tools.r8.Version;
import com.android.tools.r8.cf.CfVersion;
import com.android.tools.r8.dex.Marker;
import com.android.tools.r8.dex.Marker.Tool;
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.features.FeatureSplitConfiguration;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexDefinition;
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.DexMethod;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.inspector.internal.InspectorImpl;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.conversion.MethodProcessingId;
import com.android.tools.r8.ir.desugar.DesugaredLibraryConfiguration;
import com.android.tools.r8.ir.optimize.Inliner;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.position.Position;
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.SortedProgramMethodSet;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Equivalence.Wrapper;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import java.io.IOException;
import java.io.PrintStream;
import java.lang.reflect.GenericSignatureFormatError;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
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.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.BiConsumer;
import java.util.function.BiPredicate;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
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 = false;

  public enum LineNumberOptimization {
    OFF,
    ON
  }

  public enum DesugarState {
    OFF,
    ON
  }

  public static final CfVersion SUPPORTED_CF_VERSION = CfVersion.V11;
  public static final int SUPPORTED_DEX_VERSION =
      AndroidApiLevel.LATEST.getDexVersion().getIntValue();

  public static final int ASM_VERSION = Opcodes.ASM7;

  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 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.
  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(ProguardConfiguration proguardConfiguration, Reporter reporter) {
    assert reporter != null;
    assert proguardConfiguration != null;
    this.reporter = reporter;
    this.proguardConfiguration = proguardConfiguration;
    itemFactory = proguardConfiguration.getDexItemFactory();
    enableTreeShaking = proguardConfiguration.isShrinking();
    enableMinification = proguardConfiguration.isObfuscating();
    // -dontoptimize disables optimizations by flipping related flags.
    if (!proguardConfiguration.isOptimizing()) {
      disableAllOptimizations();
    }
    configurationDebugging = proguardConfiguration.isConfigurationDebugging();
    if (proguardConfiguration.isProtoShrinkingEnabled()) {
      enableProtoShrinking();
    }
  }

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

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

  public void disableGlobalOptimizations() {
    enableArgumentRemoval = false;
    enableInlining = false;
    enableClassInlining = false;
    enableClassStaticizer = false;
    enableDevirtualization = false;
    enableLambdaMerging = false;
    enableHorizontalClassMerging = false;
    enableStaticClassMerging = false;
    enableVerticalClassMerging = false;
    enableEnumUnboxing = false;
    enableUninstantiatedTypeOptimization = false;
    outline.enabled = false;
    enableEnumValueOptimization = false;
    enableValuePropagation = false;
    enableSideEffectAnalysis = false;
    enableTreeShakingOfLibraryMethodOverrides = false;
    callSiteOptimizationOptions.disableOptimization();
  }

  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;

  public String dumpInputToFile = System.getProperty("com.android.tools.r8.dumpinputtofile");
  public String dumpInputToDirectory =
      System.getProperty("com.android.tools.r8.dumpinputtodirectory");

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

  // Flag to toggle if the prefix based merge restriction should be enforced.
  public boolean enableNeverMergePrefixes = true;
  public Set<String> neverMergePrefixes = ImmutableSet.of("j$.");

  public boolean libraryInterfacesMayHaveStaticInitialization = false;

  // Optimization-related flags. These should conform to -dontoptimize and disableAllOptimizations.
  public boolean enableFieldAssignmentTracker = true;
  public boolean enableFieldBitAccessAnalysis =
      System.getProperty("com.android.tools.r8.fieldBitAccessAnalysis") != null;
  public boolean enableStaticClassMerging = true;
  public boolean enableHorizontalClassMerging =
      System.getProperty("com.android.tools.r8.horizontalClassMerging") != null;
  public boolean enableVerticalClassMerging = true;
  public boolean enableArgumentRemoval = true;
  public boolean enableUnusedInterfaceRemoval = true;
  public boolean enableDevirtualization = true;
  public boolean enableInlining =
      !Version.isDevelopmentVersion()
          || System.getProperty("com.android.tools.r8.disableinlining") == null;
  public boolean enableEnumUnboxing = true;
  // TODO(b/141451716): Evaluate the effect of allowing inlining in the inlinee.
  public boolean applyInliningToInlinee =
      System.getProperty("com.android.tools.r8.applyInliningToInlinee") != null;
  public int applyInliningToInlineeMaxDepth = 0;
  public boolean enableInliningOfInvokesWithClassInitializationSideEffects = true;
  public boolean enableInliningOfInvokesWithNullableReceivers = true;
  public boolean disableInliningOfLibraryMethodOverrides = true;
  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 cfToCfDesugar = false;

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

  // TODO(b/141719453): The inlining limit at least should be consistent with normal inlining.
  public int classInliningInstructionLimit = 10;
  public int classInliningInstructionAllowance = 50;
  // This defines the limit of instructions in the inlinee
  public int inliningInstructionLimit = 3;
  // 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 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;
  public boolean enableValuePropagation = true;
  public boolean enableValuePropagationForInstanceFields = true;
  public boolean enableUninstantiatedTypeOptimization = true;
  // Currently disabled, see b/146957343.
  public boolean enableUninstantiatedTypeOptimizationForInterfaces = false;
  // TODO(b/138917494): Disable until we have numbers on potential performance penalties.
  public boolean enableRedundantConstNumberOptimization = false;

  public boolean enablePcDebugInfoOutput = 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;

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

  // 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) {
    if (tool == Tool.D8 && testing.dontCreateMarkerInD8) {
      return null;
    }
    Marker marker =
        new Marker(tool)
            .setVersion(Version.LABEL)
            .setCompilationMode(debug ? CompilationMode.DEBUG : CompilationMode.RELEASE)
            .setHasChecksums(encodeChecksums);
    // Compiling with D8 and L8 is always with a min API level and desugaring to that level. If
    // desugaring is explicitly turned off for D8 the input is expected to already have been
    // desugared to the specified min API level. For R8 desugaring is optional.
    if (tool == Tool.D8
        || tool == Tool.L8
        || (tool == Tool.R8 && desugarState != DesugarState.OFF)) {
      marker.setMinApi(minApiLevel);
    }
    if (desugaredLibraryConfiguration.getIdentifier() != null) {
      marker.setDesugaredLibraryIdentifiers(desugaredLibraryConfiguration.getIdentifier());
    }
    if (Version.isDevelopmentVersion()) {
      marker.setSha1(VersionProperties.INSTANCE.getSha());
    }
    if (tool == Tool.R8) {
      marker.setR8Mode(forceProguardCompatibility ? "compatibility" : "full");
    }
    return marker;
  }

  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 isDesugaredLibraryCompilation() {
    return desugaredLibraryConfiguration.isLibraryCompilation();
  }

  public boolean isRelocatorCompilation() {
    return relocatorCompilation;
  }

  public boolean shouldBackportMethods() {
    return !hasConsumer() || isGeneratingDex() || cfToCfDesugar;
  }

  public boolean shouldKeepStackMapTable() {
    assert cfToCfDesugar || isRelocatorCompilation() || getProguardConfiguration() != null;
    return cfToCfDesugar
        || 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 !isGeneratingClassFiles() || cfToCfDesugar;
  }

  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() {
    if (testing.enableForceNestBasedAccessDesugaringForTest) {
      return true;
    }
    return enableNestBasedAccessDesugaring && !canUseNestBasedAccess();
  }

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

  public List<String> methodsFilter = ImmutableList.of();
  public int minApiLevel = AndroidApiLevel.getDefault().getLevel();
  // 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;
  public boolean readCompileTimeAnnotations = true;
  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 lambda class merging in R8.
  public boolean enableLambdaMerging = false;
  // Flag to turn on/off desugaring in D8/R8.
  public DesugarState desugarState = DesugarState.ON;
  // Flag to turn on/off JDK11+ nest-access control
  public boolean enableNestBasedAccessDesugaring = true;
  // 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;

  // 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 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 isTreeShakingEnabled() {
    return isShrinking();
  }

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

  @Override
  public boolean isRepackagingEnabled() {
    return proguardConfiguration.getPackageObfuscationMode().isSome()
        && (isShrinking() || isMinifying());
  }

  /**
   * 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() {
    return enableHorizontalClassMerging || enableVerticalClassMerging;
  }

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

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

  public boolean printCfg = false;
  public String printCfgFile;
  public boolean ignoreMissingClasses = 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 CallSiteOptimizationOptions callSiteOptimizationOptions =
      new CallSiteOptimizationOptions();
  private final ProtoShrinkingOptions protoShrinking = new ProtoShrinkingOptions();
  private final KotlinOptimizationOptions kotlinOptimizationOptions =
      new KotlinOptimizationOptions();
  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 CallSiteOptimizationOptions callSiteOptimizationOptions() {
    return callSiteOptimizationOptions;
  }

  public ProtoShrinkingOptions protoShrinking() {
    return protoShrinking;
  }

  public KotlinOptimizationOptions kotlinOptimizationOptions() {
    return kotlinOptimizationOptions;
  }

  public static boolean shouldEnableKeepRuleSynthesisForRecompilation() {
    return System.getProperty("com.android.tools.r8.keepRuleSynthesisForRecompilation") != null;
  }

  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> getExtensiveFieldMinifierLoggingFilter() {
    String property =
        System.getProperty("com.android.tools.r8.extensiveFieldMinifierLoggingFilter");
    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();
  }

  private static Set<String> getNullableReceiverInliningFilter() {
    String property = System.getProperty("com.android.tools.r8.nullableReceiverInliningFilter");
    if (property != null) {
      // The property is allowed to be either (1) a path to a file where each line is a method
      // signature, or (2) a semicolon separated list of method signatures.
      Path path = null;
      try {
        Path tmp = Paths.get(property);
        if (Files.exists(tmp)) {
          path = tmp;
        }
      } catch (InvalidPathException | NullPointerException e) {
        // Ignore, treat as a semicolon separated list of method signatures.
      }
      ImmutableSet.Builder<String> builder = ImmutableSet.builder();
      if (path != null) {
        try {
          Files.readAllLines(path).stream()
              .map(String::trim)
              .filter(not(String::isEmpty))
              .forEach(builder::add);
        } catch (IOException e) {
          throw new RuntimeException(e);
        }
      } else {
        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 proguad 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 proguad 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;

  // If null, no desugaring of library is performed.
  // If non null it contains flags describing library desugaring.
  public DesugaredLibraryConfiguration desugaredLibraryConfiguration =
      DesugaredLibraryConfiguration.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 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 Set<DexItem> invalidLibraryClasses = Sets.newConcurrentHashSet();

  public void errorMissingClassMissingNestHost(DexClass compiledClass) {
    throw reporter.fatalError(messageErrorMissingNestHost(compiledClass));
  }

  public void warningMissingClassMissingNestHost(DexClass compiledClass) {
    if (compiledClass.isLibraryClass()) {
      errorMissingClassMissingNestHost(compiledClass);
    }
    reporter.warning(new StringDiagnostic(messageWarningMissingNestHost(compiledClass)));
  }

  public void nestDesugaringWarningMissingNestHost(DexClass compiledClass) {
    if (compiledClass.isLibraryClass()) {
      errorMissingClassMissingNestHost(compiledClass);
    }
    reporter.warning(
        new MissingNestHostNestDesugarDiagnostic(
            compiledClass.getOrigin(),
            Position.UNKNOWN,
            messageWarningMissingNestHost(compiledClass)));
  }

  public void errorMissingClassIncompleteNest(List<DexType> nest, AppView<?> appView) {
    throw reporter.fatalError(messageErrorIncompleteNest(nest, appView));
  }

  public void warningMissingClassIncompleteNest(List<DexType> nest, AppView<?> appView) {
    for (DexType type : nest) {
      DexClass clazz = appView.definitionFor(type);
      if (clazz != null && clazz.isLibraryClass()) {
        errorMissingClassIncompleteNest(nest, appView);
        return;
      }
    }
    reporter.warning(new StringDiagnostic(messageWarningIncompleteNest(nest, appView)));
  }

  public void nestDesugaringWarningIncompleteNest(List<DexType> nest, AppView<?> appView) {
    DexClass availableClass = null;
    for (DexType type : nest) {
      DexClass clazz = appView.definitionFor(type);
      if (clazz != null && clazz.isProgramClass()) {
        availableClass = clazz;
      } else if (clazz != null && clazz.isLibraryClass()) {
        errorMissingClassIncompleteNest(nest, appView);
        return;
      }
    }
    assert availableClass != null;
    reporter.warning(
        new IncompleteNestNestDesugarDiagnosic(
            availableClass.getOrigin(),
            Position.UNKNOWN,
            messageWarningIncompleteNest(nest, appView)));
  }

  private 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. ";
  }

  private String messageWarningMissingNestHost(DexClass compiledClass) {
    return messageErrorMissingNestHost(compiledClass)
        + "Class "
        + compiledClass.type.getName()
        + " is considered as not being part of any nest.";
  }

  private String messageErrorIncompleteNest(List<DexType> nest, AppView<?> appView) {
    List<String> programClassesFromNest = new ArrayList<>();
    List<String> unavailableClasses = new ArrayList<>();
    List<String> classPathClasses = new ArrayList<>();
    List<String> libraryClasses = new ArrayList<>();
    for (DexType type : nest) {
      DexClass clazz = appView.definitionFor(appView.graphLens().lookupType(type));
      if (clazz == null) {
        unavailableClasses.add(type.getName());
      } else if (clazz.isLibraryClass()) {
        libraryClasses.add(type.getName());
      } else if (clazz.isProgramClass()) {
        programClassesFromNest.add(type.getName());
      } else {
        assert clazz.isClasspathClass();
        classPathClasses.add(type.getName());
      }
    }
    StringBuilder stringBuilder =
        new StringBuilder("Compilation of classes ")
            .append(String.join(", ", programClassesFromNest))
            .append(" requires its nest mates ");
    if (!unavailableClasses.isEmpty()) {
      stringBuilder.append(String.join(", ", unavailableClasses)).append(" (unavailable) ");
    }
    if (!libraryClasses.isEmpty()) {
      stringBuilder.append(String.join(", ", unavailableClasses)).append(" (on library path) ");
    }
    stringBuilder.append("to be on program or class path.");
    if (!classPathClasses.isEmpty()) {
      stringBuilder
          .append("(Classes ")
          .append(String.join(", ", classPathClasses))
          .append(" from the same nest are on class path).");
    }
    return stringBuilder.toString();
  }

  private String messageWarningIncompleteNest(List<DexType> nest, AppView<?> appView) {
    return messageErrorIncompleteNest(nest, appView)
        + " Unavailable classes are considered as not being part of the nest.";
  }

  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 warningInvalidLibrarySuperclassForDesugar(
      Origin origin,
      DexType libraryType,
      DexType invalidSuperType,
      String message,
      Set<DexEncodedMethod> retarget) {
    if (invalidLibraryClasses.add(invalidSuperType)) {
      reporter.warning(
          new InvalidLibrarySuperclassDiagnostic(
              origin,
              Reference.classFromDescriptor(libraryType.toDescriptorString()),
              Reference.classFromDescriptor(invalidSuperType.toDescriptorString()),
              message,
              ListUtils.map(retarget, method -> method.getReference().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 void warningInvalidSignature(
      DexDefinition item, Origin origin, String signature, GenericSignatureFormatError e) {
    StringBuilder message = new StringBuilder("Invalid signature '");
    message.append(signature);
    message.append("' for ");
    if (item.isDexClass()) {
      message.append("class ");
      message.append((item.asDexClass()).getType().toSourceString());
    } else if (item.isDexEncodedField()) {
      message.append("field ");
      message.append(item.toSourceString());
    } else {
      assert item.isDexEncodedMethod();
      message.append("method ");
      message.append(item.toSourceString());
    }
    message.append(".");
    message.append(System.lineSeparator());
    message.append("Signature is ignored and will not be present in the output.");
    message.append(System.lineSeparator());
    message.append("Parser error: ");
    message.append(e.getMessage());
    reporter.warning(new StringDiagnostic(message.toString(), origin));
  }

  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.indexOf(qualifiedName) >= 0;
  }

  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.indexOf(qualifiedName) >= 0;
  }

  public enum PackageObfuscationMode {
    // General package obfuscation.
    NONE,
    // 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 isSome() {
      return !isNone();
    }
  }

  public static class OutlineOptions {

    public static final String CLASS_NAME = "com.android.tools.r8.GeneratedOutlineSupport";
    public static final String METHOD_PREFIX = "outline";

    public boolean enabled = true;
    public int minSize = 3;
    public int maxSize = 99;
    public int threshold = 20;
  }

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

  public static class CallSiteOptimizationOptions {

    // Each time we see an invoke with more dispatch targets than the threshold, we stop call site
    // propagation for all these dispatch targets. The motivation for this is that it is expensive
    // and that we are somewhat unlikely to have precise knowledge about the value of arguments when
    // there are many (possibly spurious) call graph edges.
    private final int maxNumberOfDispatchTargetsBeforeAbandoning = 10;

    // TODO(b/69963623): enable if everything is ready, including signature rewriting at call sites.
    private boolean enableConstantPropagation = false;
    private boolean enableTypePropagation = true;

    private void disableOptimization() {
      enableConstantPropagation = false;
      enableTypePropagation = false;
    }

    public void disableTypePropagationForTesting() {
      enableTypePropagation = false;
    }

    // TODO(b/69963623): Remove this once enabled.
    @VisibleForTesting
    public static void enableConstantPropagationForTesting(InternalOptions options) {
      assert !options.callSiteOptimizationOptions().isConstantPropagationEnabled();
      options.callSiteOptimizationOptions().enableConstantPropagation = true;
    }

    public int getMaxNumberOfDispatchTargetsBeforeAbandoning() {
      return maxNumberOfDispatchTargetsBeforeAbandoning;
    }

    public boolean isEnabled() {
      return enableConstantPropagation || enableTypePropagation;
    }

    public boolean isConstantPropagationEnabled() {
      return enableConstantPropagation;
    }

    public boolean isTypePropagationEnabled() {
      return enableTypePropagation;
    }
  }

  public static class ProtoShrinkingOptions {

    public boolean enableGeneratedExtensionRegistryShrinking = false;
    public boolean enableGeneratedMessageLiteShrinking = false;
    public boolean enableGeneratedMessageLiteBuilderShrinking = false;
    public boolean traverseOneOfAndRepeatedProtoFields = false;
    public boolean enableEnumLiteProtoShrinking = false;

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

  public static class TestingOptions {

    public static int NO_LIMIT = -1;

    // 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 BiConsumer<AppInfoWithLiveness, Enqueuer.Mode> enqueuerInspector = null;

    public BiConsumer<ProgramMethod, MethodProcessingId> methodProcessingIdConsumer = null;

    public Function<AppView<AppInfoWithLiveness>, RepackagingConfiguration>
        repackagingConfigurationFactory =
            appView ->
                new DefaultRepackagingConfiguration(
                    appView.dexItemFactory(), appView.options().getProguardConfiguration());

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

    /**
     * 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 allowInjectedAnnotationMethods = false;
    public boolean allowTypeErrors =
        !Version.isDevelopmentVersion()
            || System.getProperty("com.android.tools.r8.allowTypeErrors") != null;
    public boolean allowInvokeErrors = false;
    public boolean disableL8AnnotationRemoval = false;
    public boolean allowClassInlinerGracefulExit =
        System.getProperty("com.android.tools.r8.disallowClassInlinerGracefulExit") == null;
    public boolean reportUnusedProguardConfigurationRules = false;
    public boolean alwaysUseExistingAccessInfoCollectionsInMemberRebinding = true;
    public boolean alwaysUsePessimisticRegisterAllocation = false;
    public boolean enableCheckCastAndInstanceOfRemoval = true;
    public boolean enableDeadSwitchCaseElimination = true;
    public boolean enableExperimentalRepackaging = false;
    public boolean enableInvokeSuperToInvokeVirtualRewriting = true;
    public boolean enableSwitchToIfRewriting = true;
    public boolean enableEnumUnboxingDebugLogs = false;
    public boolean forceRedundantConstNumberRemoval = false;
    public boolean invertConditionals = false;
    public boolean placeExceptionalBlocksLast = false;
    public boolean dontCreateMarkerInD8 = false;
    public boolean forceJumboStringProcessing = false;
    public Set<Inliner.Reason> validInliningReasons = null;
    public boolean noLocalsTableOnInput = false;
    public boolean forceNameReflectionOptimization = false;
    public boolean enableNarrowAndWideningingChecksInD8 = false;
    public Consumer<IRCode> irModifier = null;
    public int basicBlockMuncherIterationLimit = NO_LIMIT;
    public boolean dontReportFailingCheckDiscarded = false;
    public boolean deterministicSortingBasedOnDexType = true;
    public PrintStream whyAreYouNotInliningConsumer = System.out;
    public boolean trackDesugaredAPIConversions =
        System.getProperty("com.android.tools.r8.trackDesugaredAPIConversions") != null;
    public boolean forceLibBackportsInL8CfToCf = false;
    public boolean enumUnboxingRewriteJavaCGeneratedMethod = false;
    public boolean assertConsistentRenamingOfSignature = false;
    public boolean allowStaticInterfaceMethodsForPreNApiLevel = false;
    public int verificationSizeLimitInBytesOverride = -1;
    public boolean forceIRForCfToCfDesugar =
        System.getProperty("com.android.tools.r8.forceIRForCfToCfDesugar") != null;

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

    // Flag to turn on/off JDK11+ nest-access control even when not required (Cf backend)
    public boolean enableForceNestBasedAccessDesugaringForTest = false;
    public boolean verifyKeptGraphInfo = false;

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

    // Force each call of application read to dump its inputs to a file, which is subsequently
    // deleted. Useful to check that our dump functionality does not cause compilation failure.
    public boolean dumpAll = 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 = null;

    public Predicate<DexMethod> cfByteCodePassThrough = null;
  }

  @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 minApiLevel >= level.getLevel();
  }

  /**
   * 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.isGreaterThanOrEqual(requiredCfVersionForConstClassInstructions());
  }

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

  public boolean canUseInvokePolymorphicOnVarHandle() {
    return isGeneratingClassFiles() || hasMinApi(AndroidApiLevel.P);
  }

  public boolean canUseInvokePolymorphic() {
    return isGeneratingClassFiles() || hasMinApi(AndroidApiLevel.O);
  }

  public boolean canUseConstantMethodHandle() {
    return isGeneratingClassFiles() || hasMinApi(AndroidApiLevel.P);
  }

  public boolean canUseConstantMethodType() {
    return isGeneratingClassFiles() || hasMinApi(AndroidApiLevel.P);
  }

  public boolean canUseInvokeCustom() {
    return isGeneratingClassFiles() || hasMinApi(AndroidApiLevel.O);
  }

  public boolean canUseDefaultAndStaticInterfaceMethods() {
    return !isDesugaring() || hasMinApi(AndroidApiLevel.N);
  }

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

  public boolean canLeaveStaticInterfaceMethodInvokes() {
    return !isDesugaring() || hasMinApi(AndroidApiLevel.L);
  }

  public boolean canUseTwrCloseResourceMethod() {
    return !isDesugaring() || hasMinApi(AndroidApiLevel.K);
  }

  public boolean canUsePrivateInterfaceMethods() {
    return !isDesugaring() || hasMinApi(AndroidApiLevel.N);
  }

  public boolean canUseDexPcAsDebugInformation() {
    // TODO(b/37830524): Enable for min-api 26 (OREO) and above.
    return enablePcDebugInfoOutput;
  }

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

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

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

  public boolean canUseRequireNonNull() {
    return isGeneratingDex() && hasMinApi(AndroidApiLevel.K);
  }

  public boolean canUseSuppressedExceptions() {
    return (isGeneratingClassFiles() && !cfToCfDesugar) || hasMinApi(AndroidApiLevel.K);
  }

  public boolean canUseAssertionErrorTwoArgumentConstructor() {
    return (isGeneratingClassFiles() && !cfToCfDesugar) || hasMinApi(AndroidApiLevel.K);
  }

  // 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 (isGeneratingClassFiles() && !cfToCfDesugar) || hasMinApi(AndroidApiLevel.J);
  }

  // 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 canUseFilledNewArrayOfObjects() {
    assert isGeneratingDex();
    return hasMinApi(AndroidApiLevel.K);
  }

  // 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() {
    assert isGeneratingDex();
    return minApiLevel > AndroidApiLevel.O_MR1.getLevel();
  }

  // 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 isGeneratingDex() && minApiLevel < AndroidApiLevel.M.getLevel();
  }

  // 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 isGeneratingClassFiles() || hasMinApi(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 isGeneratingDex() && minApiLevel < AndroidApiLevel.M.getLevel();
  }

  // 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 minApiLevel < AndroidApiLevel.Q.getLevel();
  }

  // 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 isGeneratingDex() && minApiLevel < AndroidApiLevel.L.getLevel();
  }

  // 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 isGeneratingDex() && minApiLevel < AndroidApiLevel.L.getLevel();
  }

  // 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 minApiLevel < AndroidApiLevel.M.getLevel();
  }

  // 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 isGeneratingDex() && minApiLevel < AndroidApiLevel.M.getLevel();
  }

  // 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 isGeneratingDex() && minApiLevel < AndroidApiLevel.N.getLevel();
  }

  // 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 isGeneratingDex() && minApiLevel < AndroidApiLevel.N.getLevel();
  }

  // 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 isGeneratingDex() && minApiLevel < AndroidApiLevel.Q.getLevel();
  }

  // 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 isGeneratingDex() && minApiLevel < AndroidApiLevel.L.getLevel();
  }

  // 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 isGeneratingDex() && minApiLevel < AndroidApiLevel.M.getLevel();
  }

  // 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() {
    return isGeneratingDex() && !debug && minApiLevel < AndroidApiLevel.M.getLevel();
  }

  // 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 minApiLevel < AndroidApiLevel.L.getLevel();
  }

  // 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() {
    assert isGeneratingDex();
    return minApiLevel < AndroidApiLevel.Q.getLevel();
  }

  // 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 minApiLevel < AndroidApiLevel.M.getLevel();
  }

  // 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 minApiLevel < AndroidApiLevel.Q.getLevel();
  }

  // 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 minApiLevel < AndroidApiLevel.J.getLevel();
  }

  // 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 isGeneratingClassFiles() || minApiLevel < AndroidApiLevel.L.getLevel();
  }

  // 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 isGeneratingDex() && minApiLevel < AndroidApiLevel.L.getLevel();
  }

  // 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 isGeneratingClassFiles() || minApiLevel < AndroidApiLevel.L.getLevel();
  }
}
