// Copyright (c) 2019, 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.ir.optimize;

import com.android.tools.r8.AssertionsConfiguration;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexEncodedMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.DominatorTree;
import com.android.tools.r8.ir.code.FieldInstruction;
import com.android.tools.r8.ir.code.Goto;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.If;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InstructionListIterator;
import com.android.tools.r8.ir.code.InvokeMethod;
import com.android.tools.r8.ir.code.InvokeStatic;
import com.android.tools.r8.ir.code.StaticGet;
import com.android.tools.r8.ir.code.StaticPut;
import com.android.tools.r8.ir.code.Throw;
import com.android.tools.r8.references.MethodReference;
import com.android.tools.r8.utils.AssertionConfigurationWithDefault;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.LazyBox;
import com.android.tools.r8.utils.ThrowingCharIterator;
import com.android.tools.r8.utils.Timing;
import com.android.tools.r8.utils.WorkList;
import com.google.common.collect.ImmutableList;
import java.io.UTFDataFormatException;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class AssertionsRewriter {

  private static class ConfigurationEntryWithDexString {

    private final AssertionsConfiguration entry;
    private final DexString value;

    private ConfigurationEntryWithDexString(
        AssertionsConfiguration configuration, DexItemFactory dexItemFactory) {
      this.entry = configuration;
      switch (configuration.getScope()) {
        case PACKAGE:
          if (configuration.getValue().length() == 0) {
            value = dexItemFactory.createString("");
          } else {
            value =
                dexItemFactory.createString(
                    "L"
                        + configuration
                            .getValue()
                            .replace(
                                DescriptorUtils.JAVA_PACKAGE_SEPARATOR,
                                DescriptorUtils.DESCRIPTOR_PACKAGE_SEPARATOR)
                        + "/");
          }
          break;
        case CLASS:
          value =
              dexItemFactory.createString(
                  "L"
                      + configuration
                          .getValue()
                          .replace(
                              DescriptorUtils.JAVA_PACKAGE_SEPARATOR,
                              DescriptorUtils.DESCRIPTOR_PACKAGE_SEPARATOR)
                      + ";");
          break;
        case ALL:
          value = null;
          break;
        default:
          throw new Unreachable();
      }
    }

    public boolean isCompileTimeEnabled() {
      return entry.isCompileTimeEnabled();
    }

    public boolean isCompileTimeDisabled() {
      return entry.isCompileTimeDisabled();
    }

    public boolean isPassthrough() {
      return entry.isPassthrough();
    }

    public boolean isAssertionHandler() {
      return entry.isAssertionHandler();
    }

    public MethodReference getAssertionHandler() {
      assert isAssertionHandler();
      return entry.getAssertionHandler();
    }
  }

  private final AppView<?> appView;
  private final DexItemFactory dexItemFactory;
  private final ConfigurationEntryWithDexString defaultConfiguration;
  private final List<ConfigurationEntryWithDexString> configuration;
  private final ConfigurationEntryWithDexString kotlinTransformation;
  private final boolean enabled;

  public AssertionsRewriter(AppView<?> appView) {
    this.appView = appView;
    this.dexItemFactory = appView.dexItemFactory();
    this.enabled = isEnabled(appView.options());
    if (!enabled) {
      defaultConfiguration = null;
      configuration = null;
      kotlinTransformation = null;
      return;
    }
    // Convert the assertion configuration to the representation used for this rewriter.
    this.defaultConfiguration =
        new ConfigurationEntryWithDexString(
            appView.options().assertionsConfiguration.defaultConfiguration, dexItemFactory);
    this.configuration =
        appView.options().assertionsConfiguration.assertionsConfigurations.stream()
            .map(entry -> new ConfigurationEntryWithDexString(entry, appView.dexItemFactory()))
            .collect(Collectors.toList());
    kotlinTransformation =
        getTransformationForType(appView.dexItemFactory().kotlin.assertions.type);
  }

  // Static method used by other analyses to see if additional analysis is required to support
  // this rewriting.
  public static boolean isEnabled(InternalOptions options) {
    AssertionConfigurationWithDefault configuration = options.assertionsConfiguration;
    return configuration != null && !configuration.isPassthroughAll();
  }

  private ConfigurationEntryWithDexString getTransformationForMethod(DexEncodedMethod method) {
    return getTransformationForType(method.getHolderType());
  }

  private ConfigurationEntryWithDexString getTransformationForType(DexType type) {
    ConfigurationEntryWithDexString result = defaultConfiguration;
    for (ConfigurationEntryWithDexString entry : configuration) {
      switch (entry.entry.getScope()) {
        case ALL:
          result = entry;
          break;
        case PACKAGE:
          if (entry.value.size == 0) {
            if (!type.descriptor.contains(dexItemFactory.descriptorSeparator)) {
              result = entry;
            }
          } else if (type.descriptor.startsWith(entry.value)) {
            result = entry;
          }
          break;
        case CLASS:
          if (type.descriptor.equals(entry.value)) {
            result = entry;
          }
          if (isDescriptorForClassOrInnerClass(entry.value, type.descriptor)) {
            result = entry;
          }
          break;
        default:
          throw new Unreachable();
      }
    }
    assert result != null;
    return result;
  }

  private boolean isDescriptorForClassOrInnerClass(
      DexString classDescriptor, DexString classOrInnerClassDescriptor) {
    // Same string same class.
    if (classOrInnerClassDescriptor == classDescriptor) {
      return true;
    }

    // Check for inner class name by checking if the prefix is the class descriptor,
    // where ';' is replaced whit '$' and no '/' after that.
    if (classOrInnerClassDescriptor.size < classDescriptor.size) {
      return false;
    }
    ThrowingCharIterator<UTFDataFormatException> i1 = classDescriptor.iterator();
    ThrowingCharIterator<UTFDataFormatException> i2 = classOrInnerClassDescriptor.iterator();
    try {
      while (i1.hasNext()) {
        char c1 = i1.nextChar();
        char c2 = i2.nextChar();
        // The Java VM behaviour is including all inner classes as well when a class is specified.
        if (c1 == ';' && c2 == DescriptorUtils.INNER_CLASS_SEPARATOR) {
          // If there is a '/' after the '$' this is not an inner class after all.
          while (i2.hasNext()) {
            if (i2.nextChar() == DescriptorUtils.DESCRIPTOR_PACKAGE_SEPARATOR) {
              return false;
            }
          }
          return true;
        }
        if (c1 != c2) {
          return false;
        }
      }
      assert i2.hasNext();
      return false;
    } catch (UTFDataFormatException e) {
      return false;
    }
  }

  /**
   * For supporting assert javac adds the static field $assertionsDisabled to all classes which have
   * methods with assertions. This is used to support the Java VM -ea flag.
   *
   * <p>The class:
   *
   * <pre>
   * class A {
   *   void m() {
   *     assert xxx;
   *   }
   * }
   * </pre>
   *
   * Is compiled into:
   *
   * <pre>
   * class A {
   *   static boolean $assertionsDisabled;
   *   static {
   *     $assertionsDisabled = A.class.desiredAssertionStatus();
   *   }
   *
   *   // method with "assert xxx";
   *   void m() {
   *     if (!$assertionsDisabled) {
   *       if (!xxx) {
   *         throw new AssertionError(...);
   *       }
   *     }
   *   }
   * }
   * </pre>
   *
   * With the rewriting below and AssertionTransformation.DISABLE (and other rewritings) the
   * resulting code is:
   *
   * <pre>
   * class A {
   *   void m() {
   *   }
   * }
   * </pre>
   *
   * With AssertionTransformation.ENABLE (and other rewritings) the resulting code is:
   *
   * <pre>
   * class A {
   *   static boolean $assertionsDisabled;
   *   void m() {
   *     if (!xxx) {
   *       throw new AssertionError(...);
   *     }
   *   }
   * }
   * </pre>
   * For Kotlin the Class instance method desiredAssertionStatus() is only called for the class
   * kotlin._Assertions, where kotlin._Assertions.class.desiredAssertionStatus() is read into the
   * static field kotlin._Assertions.ENABLED.
   *
   * <pre>
   * class _Assertions {
   *   public static boolean ENABLED = _Assertions.class.desiredAssertionStatus();
   * }
   * </pre>
   *
   * <p>(actual code
   * https://github.com/JetBrains/kotlin/blob/master/libraries/stdlib/jvm/src/kotlin/util/AssertionsJVM.kt)
   *
   * <p>The class:
   *
   * <pre>
   * class A {
   *   void m() {
   *     assert(xxx)
   *   }
   * }
   * </pre>
   *
   * Is compiled into:
   *
   * <pre>
   * class A {
   *   void m() {
   *     if (!xxx) {
   *       if (kotlin._Assertions.ENABLED) {
   *         throw new AssertionError("Assertion failed")
   *       }
   *     }
   *   }
   * }
   * </pre>
   *
   * With the rewriting below and AssertionTransformation.DISABLE (and other rewritings) the resulting code is:
   *
   * <pre>
   * class A {
   *   void m() {
   *     if (!xxx) {}
   *   }
   * }
   * </pre>
   *
   * With AssertionTransformation.ENABLE (and other rewritings) the resulting code is:
   *
   * <pre>
   * class A {
   *   void m() {
   *     if (!xxx) {
   *       throw new AssertionError("Assertion failed")
   *     }
   *   }
   * }
   * </pre>

   * NOTE: that in Kotlin the assertion condition is always calculated. So it is still present in
   * the code and even for AssertionTransformation.DISABLE.
   */
  public void run(DexEncodedMethod method, IRCode code, Timing timing) {
    if (enabled) {
      timing.begin("Rewrite assertions");
      runInternal(method, code);
      assert code.isConsistentSSA(appView);
      timing.end();
    }
  }

  private void runInternal(DexEncodedMethod method, IRCode code) {
    ConfigurationEntryWithDexString configuration = getTransformationForMethod(method);
    if (configuration.isPassthrough()) {
      return;
    }
    DexEncodedMethod clinit;
    // If the <clinit> of this class did not have have code to turn on assertions don't try to
    // remove assertion code from the method (including <clinit> itself.
    if (method.isClassInitializer()) {
      clinit = method;
    } else {
      DexClass clazz = appView.definitionFor(method.getHolderType());
      if (clazz == null) {
        return;
      }
      clinit = clazz.getClassInitializer();
    }
    // For the transformation to rewrite the throw with a callback collect information on the
    // blocks covered by the if (!$assertionsDisabled or ENABLED) condition together with weather
    // the assertion handling is on the true or false branch.
    Map<If, Boolean> assertionEntryIfs = new IdentityHashMap<>();
    Map<Throw, BasicBlock> throwSuccessorAfterHandler = new IdentityHashMap<>();
    if (configuration.isAssertionHandler()) {
      LazyBox<DominatorTree> dominatorTree = new LazyBox<>(() -> new DominatorTree(code));
      code.getBlocks()
          .forEach(
              basicBlock -> {
                If theIf = isCheckAssertionsEnabledBlock(basicBlock);
                if (theIf != null) {
                  // All blocks dominated by the if is the assertion code. For Java it is on the
                  // false branch and for Kotlin on the true branch (for Java it is negated
                  // $assertionsDisabled field and for Kotlin it is the ENABLED field).
                  boolean conditionForAssertionBlock =
                      !isUsingJavaAssertionsDisabledField(
                          theIf.lhs().getDefinition().asStaticGet());
                  BasicBlock assertionBlockEntry =
                      theIf.targetFromBoolean(conditionForAssertionBlock);
                  List<BasicBlock> blocks =
                      dominatorTree.computeIfAbsent().dominatedBlocks(assertionBlockEntry);
                  Throw throwInstruction = isAlwaysThrowingEntry(assertionBlockEntry, blocks);
                  if (throwInstruction != null) {
                    assertionEntryIfs.put(theIf, conditionForAssertionBlock);
                    throwSuccessorAfterHandler.put(
                        throwInstruction, theIf.targetFromBoolean(!conditionForAssertionBlock));
                  }
                }
              });
    }
    assert assertionEntryIfs.size() == throwSuccessorAfterHandler.size();

    // For javac generated code it is assumed that the code in <clinit> will tell if the code
    // in other methods of the class can have assertion checks.
    boolean isInitializerEnablingJavaVmAssertions =
        clinit != null && clinit.getOptimizationInfo().isInitializerEnablingJavaVmAssertions();
    // This code will process the assertion code in all methods including <clinit>.
    InstructionListIterator iterator = code.instructionListIterator();
    while (iterator.hasNext()) {
      Instruction current = iterator.next();
      if (current.isInvokeMethod()) {
        InvokeMethod invoke = current.asInvokeMethod();
        if (invoke.getInvokedMethod() == dexItemFactory.classMethods.desiredAssertionStatus) {
          if (method.getHolderType() == dexItemFactory.kotlin.assertions.type) {
            rewriteKotlinAssertionEnable(code, configuration, iterator, invoke);
          } else {
            iterator.replaceCurrentInstruction(code.createIntConstant(0, current.getLocalInfo()));
          }
        }
      } else if (current.isStaticPut()) {
        StaticPut staticPut = current.asStaticPut();
        if (isInitializerEnablingJavaVmAssertions
            && isUsingJavaAssertionsDisabledField(staticPut)) {
          iterator.remove();
        }
      } else if (current.isStaticGet()) {
        StaticGet staticGet = current.asStaticGet();
        // Rewrite $assertionsDisabled getter (only if the initializer enabled assertions).
        if (isInitializerEnablingJavaVmAssertions
            && isUsingJavaAssertionsDisabledField(staticGet)) {
          // For assertion handler rewrite just leave the static get, as it will become dead code.
          if (!configuration.isAssertionHandler()) {
            iterator.replaceCurrentInstruction(
                code.createIntConstant(
                    configuration.isCompileTimeDisabled() ? 1 : 0, current.getLocalInfo()));
          }
        }
        // Rewrite kotlin._Assertions.ENABLED getter.
        if (staticGet.getField() == dexItemFactory.kotlin.assertions.enabledField) {
          // For assertion handler rewrite just leave the static get, as it will become dead code.
          if (!configuration.isAssertionHandler()) {
            iterator.replaceCurrentInstruction(
                code.createIntConstant(
                    kotlinTransformation.isCompileTimeDisabled() ? 0 : 1, current.getLocalInfo()));
          }
        }
      }

      // Rewriting of if and throw to replace throw with invoke of the assertion handler.
      if (configuration.isAssertionHandler()) {
        if (current.isIf()) {
          If ifInstruction = current.asIf();
          if (assertionEntryIfs.containsKey(ifInstruction)) {
            ifInstruction
                .targetFromBoolean(!assertionEntryIfs.get(ifInstruction))
                .unlinkSinglePredecessorSiblingsAllowed();
            ifInstruction.lhs().removeUser(ifInstruction);
            iterator.replaceCurrentInstruction(new Goto());
          }
        } else if (current.isThrow()) {
          Throw throwInstruction = current.asThrow();
          if (throwSuccessorAfterHandler.containsKey(throwInstruction)) {
            BasicBlock throwingBlock = throwInstruction.getBlock();
            iterator.replaceCurrentInstruction(
                new InvokeStatic(
                    dexItemFactory.createMethod(configuration.getAssertionHandler()),
                    null,
                    ImmutableList.of(throwInstruction.exception())));
            Goto gotoBlockAfterAssertion = new Goto(throwingBlock);
            gotoBlockAfterAssertion.setPosition(throwInstruction.getPosition());
            throwingBlock.link(throwSuccessorAfterHandler.get(throwInstruction));
            iterator.add(gotoBlockAfterAssertion);
          }
        }
      }
    }
  }

  private void rewriteKotlinAssertionEnable(
      IRCode code,
      ConfigurationEntryWithDexString configuration,
      InstructionListIterator iterator,
      InvokeMethod invoke) {
    if (iterator.hasNext() && configuration.isCompileTimeDisabled()) {
      // Check if the invocation of Class.desiredAssertionStatus() is followed by a static
      // put to kotlin._Assertions.ENABLED, and if so remove both instructions.
      // See comment in ClassInitializerAssertionEnablingAnalysis for the expected instruction
      // sequence.
      Instruction nextInstruction = iterator.next();
      if (nextInstruction.isStaticPut()
          && nextInstruction.asStaticPut().getField().holder
              == dexItemFactory.kotlin.assertions.type
          && nextInstruction.asStaticPut().getField().name == dexItemFactory.enabledFieldName
          && invoke.outValue().numberOfUsers() == 1
          && invoke.outValue().numberOfPhiUsers() == 0
          && invoke.outValue().singleUniqueUser() == nextInstruction) {
        iterator.removeOrReplaceByDebugLocalRead();
        Instruction prevInstruction = iterator.previous();
        assert prevInstruction == invoke;
        iterator.removeOrReplaceByDebugLocalRead();
      } else {
        Instruction instruction = iterator.previous();
        assert instruction == nextInstruction;
        instruction = iterator.previous();
        assert instruction == invoke;
        instruction = iterator.next();
        assert instruction == invoke;
        iterator.replaceCurrentInstruction(code.createIntConstant(0));
      }
    } else {
      iterator.replaceCurrentInstruction(
          code.createIntConstant(configuration.isCompileTimeEnabled() ? 1 : 0));
    }
  }

  private boolean isUsingAssertionsControlField(FieldInstruction instruction) {
    return isUsingJavaAssertionsDisabledField(instruction)
        || isUsingKotlinAssertionsEnabledField(instruction);
  }

  private boolean isUsingJavaAssertionsDisabledField(FieldInstruction instruction) {
    // This does not check the holder, as for inner classe the field is read from the outer class
    // and not the class itself.
    return instruction.getField().getName() == dexItemFactory.assertionsDisabled
        && instruction.getField().getType() == dexItemFactory.booleanType;
  }

  private boolean isUsingKotlinAssertionsEnabledField(FieldInstruction instruction) {
    return instruction.getField() == dexItemFactory.kotlin.assertions.enabledField;
  }

  private If isCheckAssertionsEnabledBlock(BasicBlock basicBlock) {
    if (!basicBlock.exit().isIf()) {
      return null;
    }
    If theIf = basicBlock.exit().asIf();
    if (!theIf.isZeroTest()
        || !theIf.lhs().isDefinedByInstructionSatisfying(Instruction::isStaticGet)) {
      return null;
    }
    StaticGet staticGet = theIf.lhs().getDefinition().asStaticGet();
    return isUsingAssertionsControlField(staticGet)
            && staticGet.value().hasSingleUniqueUser()
            && !staticGet.value().hasPhiUsers()
        ? theIf
        : null;
  }

  private Throw isAlwaysThrowingEntry(BasicBlock block, List<BasicBlock> blocks) {
    WorkList<BasicBlock> workList = WorkList.newIdentityWorkList(block);
    Throw theThrow = null;
    while (workList.hasNext()) {
      BasicBlock current = workList.next();
      workList.addIfNotSeen(current.getNormalSuccessors());
      if (!blocks.containsAll(current.getNormalSuccessors())) {
        return null;
      }
      if (current.exit().isReturn()) {
        return null;
      }
      if (current.exit().isThrow()) {
        if (theThrow != null) {
          return null;
        }
        theThrow = current.exit().asThrow();
      }
    }
    return theThrow;
  }
}
