// Copyright (c) 2021, 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.classinliner.analysis;

import static com.android.tools.r8.ir.code.Opcodes.ASSUME;
import static com.android.tools.r8.ir.code.Opcodes.CHECK_CAST;
import static com.android.tools.r8.ir.code.Opcodes.IF;
import static com.android.tools.r8.ir.code.Opcodes.INSTANCE_GET;
import static com.android.tools.r8.ir.code.Opcodes.INSTANCE_PUT;
import static com.android.tools.r8.ir.code.Opcodes.INVOKE_DIRECT;
import static com.android.tools.r8.ir.code.Opcodes.INVOKE_INTERFACE;
import static com.android.tools.r8.ir.code.Opcodes.INVOKE_STATIC;
import static com.android.tools.r8.ir.code.Opcodes.INVOKE_VIRTUAL;
import static com.android.tools.r8.ir.code.Opcodes.MONITOR;
import static com.android.tools.r8.ir.code.Opcodes.RETURN;

import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.ClasspathOrLibraryClass;
import com.android.tools.r8.graph.DexClass;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexProgramClass;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.FieldResolutionResult;
import com.android.tools.r8.graph.MethodResolutionResult.SingleResolutionResult;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.AbstractTransferFunction;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.FailedTransferFunctionResult;
import com.android.tools.r8.ir.analysis.framework.intraprocedural.TransferFunctionResult;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.AliasedValueConfiguration;
import com.android.tools.r8.ir.code.Argument;
import com.android.tools.r8.ir.code.Assume;
import com.android.tools.r8.ir.code.AssumeAndCheckCastAliasedValueConfiguration;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CheckCast;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.If;
import com.android.tools.r8.ir.code.InstanceGet;
import com.android.tools.r8.ir.code.InstancePut;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.InvokeInterface;
import com.android.tools.r8.ir.code.InvokeStatic;
import com.android.tools.r8.ir.code.InvokeVirtual;
import com.android.tools.r8.ir.code.Monitor;
import com.android.tools.r8.ir.code.Return;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.optimize.info.initializer.InstanceInitializerInfo;
import com.android.tools.r8.shaking.AppInfoWithLiveness;
import com.google.common.collect.Sets;
import java.util.Set;

class TransferFunction implements AbstractTransferFunction<ParameterUsages> {

  private static final AliasedValueConfiguration aliasedValueConfiguration =
      AssumeAndCheckCastAliasedValueConfiguration.getInstance();

  private final AppView<AppInfoWithLiveness> appView;
  private final DexItemFactory dexItemFactory;
  private final ProgramMethod method;

  // The last argument instruction.
  private final Argument lastArgument;

  // Caches the parent or forwarding constructor call (only used in constructors).
  private InvokeDirect constructorInvoke;

  // The arguments that are considered by the analysis. We don't consider primitive arguments since
  // they cannot be class inlined.
  private Set<Value> argumentsOfInterest = Sets.newIdentityHashSet();

  // Instructions that use one of the arguments. Instructions that don't use any of the arguments
  // do not have any impact on the ability to class inline the arguments, therefore they are
  // skipped.
  private Set<Instruction> instructionsOfInterest = Sets.newIdentityHashSet();

  TransferFunction(AppView<AppInfoWithLiveness> appView, ProgramMethod method, IRCode code) {
    this.appView = appView;
    this.dexItemFactory = appView.dexItemFactory();
    this.method = method;
    this.lastArgument = code.getLastArgument();
  }

  @Override
  public TransferFunctionResult<ParameterUsages> apply(
      Instruction instruction, ParameterUsages state) {
    if (instruction.isArgument()) {
      Argument argument = instruction.asArgument();
      ParameterUsages result = analyzeArgument(argument, state);
      // After analyzing the last argument instruction, only proceed if there is at least one
      // argument that may be eligible for class inlining.
      if (argument == lastArgument
          && result.asNonEmpty().allMatch((context, usagePerContext) -> usagePerContext.isTop())) {
        return fail();
      }
      return result;
    }
    if (!instructionsOfInterest.contains(instruction)) {
      // The instruction does not use any of the argument values that we are analyzing, so for the
      // purpose of class inlining we can ignore this instruction.
      return state;
    }
    assert !state.isBottom();
    assert !state.isTop();
    ParameterUsages outState = apply(instruction, state.asNonEmpty());
    return outState != state ? widen(outState) : outState;
  }

  private ParameterUsages apply(Instruction instruction, NonEmptyParameterUsages state) {
    switch (instruction.opcode()) {
      case ASSUME:
        return analyzeAssume(instruction.asAssume(), state);
      case CHECK_CAST:
        return analyzeCheckCast(instruction.asCheckCast(), state);
      case IF:
        return analyzeIf(instruction.asIf(), state);
      case INSTANCE_GET:
        return analyzeInstanceGet(instruction.asInstanceGet(), state);
      case INSTANCE_PUT:
        return analyzeInstancePut(instruction.asInstancePut(), state);
      case INVOKE_DIRECT:
        return analyzeInvokeDirect(instruction.asInvokeDirect(), state);
      case INVOKE_INTERFACE:
        return analyzeInvokeInterface(instruction.asInvokeInterface(), state);
      case INVOKE_STATIC:
        return analyzeInvokeStatic(instruction.asInvokeStatic(), state);
      case INVOKE_VIRTUAL:
        return analyzeInvokeVirtual(instruction.asInvokeVirtual(), state);
      case MONITOR:
        return analyzeMonitor(instruction.asMonitor(), state);
      case RETURN:
        return analyzeReturn(instruction.asReturn(), state);
      default:
        return fail(instruction, state);
    }
  }

  @Override
  public ParameterUsages computeBlockEntryState(
      BasicBlock block, BasicBlock predecessor, ParameterUsages predecessorExitState) {
    // TODO(b/173337498): Fork a new `FIELD=x` analysis context for the successor block if the
    //  predecessor ends with an if or switch instruction, and the successor block is the
    //  `FIELD=x` target of the predecessor. To avoid an excessive number of contexts being
    //  created, only allow forking new contexts for $r8$classId fields synthesized by the
    //  horizontal class merger.
    return predecessorExitState;
  }

  private ParameterUsages analyzeArgument(Argument argument, ParameterUsages state) {
    // Only consider arguments that could store an instance eligible for class inlining. Note that
    // we can't ignore parameters with a library type, since instances of program classes could
    // still flow into such parameters.
    Value value = argument.outValue();
    if (!isMaybeEligibleForClassInlining(value.getType()) || value.hasPhiUsers()) {
      return state.put(argument.getIndex(), ParameterUsagePerContext.top());
    }

    // Mark the users of this argument for analysis, and fork the analysis of this argument in the
    // default analysis context.
    argumentsOfInterest.add(value);
    instructionsOfInterest.addAll(value.aliasedUsers(aliasedValueConfiguration));
    return state.put(argument.getIndex(), NonEmptyParameterUsagePerContext.createInitial());
  }

  private ParameterUsages analyzeAssume(Assume assume, NonEmptyParameterUsages state) {
    // Mark the value as ineligible for class inlining if it has phi users.
    return assume.outValue().hasPhiUsers() ? fail(assume, state) : state;
  }

  private ParameterUsages analyzeCheckCast(CheckCast checkCast, NonEmptyParameterUsages state) {
    // Mark the value as ineligible for class inlining if it has phi users.
    if (checkCast.outValue().hasPhiUsers()) {
      return fail(checkCast, state);
    }
    return state.rebuildParameter(
        checkCast.object(), (context, usage) -> usage.addCastWithParameter(checkCast.getType()));
  }

  private ParameterUsages analyzeIf(If theIf, NonEmptyParameterUsages state) {
    // Null/not-null tests are ok.
    if (theIf.isZeroTest()) {
      assert argumentsOfInterest.contains(theIf.lhs().getAliasedValue(aliasedValueConfiguration));
      return state;
    }

    // For non-null tests, mark the inputs as ineligible for class inlining.
    return fail(theIf, state);
  }

  private ParameterUsages analyzeInstanceGet(
      InstanceGet instanceGet, NonEmptyParameterUsages state) {
    // Instance field reads are OK, as long as the field resolves, since the class inliner will
    // just replace the field read by the value of the field.
    FieldResolutionResult resolutionResult = appView.appInfo().resolveField(instanceGet.getField());
    if (resolutionResult.isSingleFieldResolutionResult()) {
      // Record that the field is read from the parameter. For class inlining of singletons, this
      // parameter is only eligible for class inlining if the singleton's field value is known.
      return state.rebuildParameter(
          instanceGet.object(),
          (context, usage) -> usage.addFieldReadFromParameter(instanceGet.getField()));
    }

    return fail(instanceGet, state);
  }

  private ParameterUsages analyzeInstancePut(
      InstancePut instancePut, NonEmptyParameterUsages state) {
    // Instance field writes are OK, as long as the field resolves and the receiver is not being
    // assigned (in that case the receiver escapes, and thus it is not eligible for class
    // inlining).
    Value valueRoot = instancePut.value().getAliasedValue(aliasedValueConfiguration);
    if (isArgumentOfInterest(valueRoot)) {
      state = state.abandonClassInliningInCurrentContexts(valueRoot);
    }

    Value objectRoot = instancePut.object().getAliasedValue(aliasedValueConfiguration);
    if (!isArgumentOfInterest(objectRoot)) {
      return state;
    }

    FieldResolutionResult resolutionResult = appView.appInfo().resolveField(instancePut.getField());
    if (resolutionResult.isSingleFieldResolutionResult()) {
      return state.rebuildParameter(objectRoot, (context, usage) -> usage.setParameterMutated());
    } else {
      return state.abandonClassInliningInCurrentContexts(objectRoot);
    }
  }

  private ParameterUsages analyzeInvokeDirect(InvokeDirect invoke, NonEmptyParameterUsages state) {
    // We generally don't class inline instances that escape through invoke-direct calls, but we
    // make an exception for forwarding/parent constructor calls that does not leak the receiver.
    state =
        state.abandonClassInliningInCurrentContexts(
            invoke.getNonReceiverArguments(), this::isArgumentOfInterest);

    Value receiverRoot = invoke.getReceiver().getAliasedValue(aliasedValueConfiguration);
    if (!isArgumentOfInterest(receiverRoot)) {
      return state;
    }

    if (!receiverRoot.isThis()
        || !method.getDefinition().isInstanceInitializer()
        || !invoke.isInvokeConstructor(dexItemFactory)) {
      return state.abandonClassInliningInCurrentContexts(receiverRoot);
    }

    SingleResolutionResult resolutionResult =
        appView
            .appInfo()
            .resolveMethodOnClassHolder(invoke.getInvokedMethod())
            .asSingleResolution();
    if (resolutionResult == null) {
      return state.abandonClassInliningInCurrentContexts(receiverRoot);
    }

    InstanceInitializerInfo instanceInitializerInfo =
        resolutionResult
            .getResolvedMethod()
            .getOptimizationInfo()
            .getInstanceInitializerInfo(invoke);
    if (instanceInitializerInfo.receiverMayEscapeOutsideConstructorChain()) {
      return state.abandonClassInliningInCurrentContexts(receiverRoot);
    }

    // We require that there is exactly one forwarding/parent constructor call.
    if (constructorInvoke != null && constructorInvoke != invoke) {
      return state.abandonClassInliningInCurrentContexts(receiverRoot);
    }

    constructorInvoke = invoke;
    return state;
  }

  private ParameterUsages analyzeInvokeInterface(
      InvokeInterface invoke, NonEmptyParameterUsages state) {
    // We only allow invoke-interface instructions where the parameter is in the receiver position.
    state =
        state.abandonClassInliningInCurrentContexts(
            invoke.getNonReceiverArguments(), this::isArgumentOfInterest);

    Value receiverRoot = invoke.getReceiver().getAliasedValue(aliasedValueConfiguration);
    if (!isArgumentOfInterest(receiverRoot)) {
      return state;
    }

    SingleResolutionResult resolutionResult =
        appView
            .appInfo()
            .resolveMethodOnInterfaceHolder(invoke.getInvokedMethod())
            .asSingleResolution();
    if (resolutionResult == null) {
      return state.abandonClassInliningInCurrentContexts(receiverRoot);
    }

    return state.rebuildParameter(
        receiverRoot, (context, usage) -> usage.addMethodCallWithParameterAsReceiver(invoke));
  }

  private ParameterUsages analyzeInvokeStatic(InvokeStatic invoke, NonEmptyParameterUsages state) {
    // We generally don't class inline instances that escape through invoke-static calls, but we
    // make an exception for calls to Objects.requireNonNull().
    SingleResolutionResult resolutionResult =
        appView
            .appInfo()
            .unsafeResolveMethodDueToDexFormat(invoke.getInvokedMethod())
            .asSingleResolution();
    if (resolutionResult != null
        && resolutionResult.getResolvedMethod().getReference()
            == dexItemFactory.objectsMethods.requireNonNull) {
      return state;
    }

    return fail(invoke, state);
  }

  private ParameterUsages analyzeInvokeVirtual(
      InvokeVirtual invoke, NonEmptyParameterUsages state) {
    // We only allow invoke-virtual instructions where the parameter is in the receiver position.
    state =
        state.abandonClassInliningInCurrentContexts(
            invoke.getNonReceiverArguments(), this::isArgumentOfInterest);

    Value receiverRoot = invoke.getReceiver().getAliasedValue(aliasedValueConfiguration);
    if (!isArgumentOfInterest(receiverRoot)) {
      return state;
    }

    SingleResolutionResult resolutionResult =
        appView
            .appInfo()
            .resolveMethodOnClassHolder(invoke.getInvokedMethod())
            .asSingleResolution();
    if (resolutionResult == null) {
      return state.abandonClassInliningInCurrentContexts(receiverRoot);
    }

    return state.rebuildParameter(
        receiverRoot, (context, usage) -> usage.addMethodCallWithParameterAsReceiver(invoke));
  }

  private ParameterUsages analyzeMonitor(Monitor monitor, NonEmptyParameterUsages state) {
    // Record that the receiver is used as a lock in each context that may reach this monitor
    // instruction.
    return state.rebuildParameter(
        monitor.object(), (context, usage) -> usage.setParameterUsedAsLock());
  }

  private ParameterUsages analyzeReturn(Return theReturn, NonEmptyParameterUsages state) {
    return state.rebuildParameter(
        theReturn.returnValue(), (context, usage) -> usage.setParameterReturned());
  }

  private FailedTransferFunctionResult<ParameterUsages> fail() {
    return new FailedTransferFunctionResult<>();
  }

  private ParameterUsages fail(Instruction instruction, NonEmptyParameterUsages state) {
    return state.abandonClassInliningInCurrentContexts(
        instruction.inValues(), this::isArgumentOfInterest);
  }

  private boolean isArgumentOfInterest(Value value) {
    assert value.getAliasedValue(aliasedValueConfiguration) == value;
    return value.isArgument() && argumentsOfInterest.contains(value);
  }

  private boolean isMaybeEligibleForClassInlining(TypeElement type) {
    if (!type.isClassType()) {
      // Primitives and arrays will never be class inlined.
      return false;
    }
    DexClass clazz = appView.definitionFor(type.asClassType().getClassType());
    if (clazz == null) {
      // We cannot class inline in presence of missing classes.
      return false;
    }
    return clazz.isProgramClass()
        ? isMaybeEligibleForClassInlining(clazz.asProgramClass())
        : isMaybeEligibleForClassInlining(clazz.asClasspathOrLibraryClass());
  }

  private boolean isMaybeEligibleForClassInlining(DexProgramClass clazz) {
    // We can only class inline parameters that does not inherit from other classpath or library
    // classes than java.lang.Object.
    DexType superType = clazz.getSuperType();
    do {
      DexClass superClass = appView.definitionFor(superType);
      if (superClass == null) {
        return false;
      }
      if (!superClass.isProgramClass()) {
        return superClass.getType() == dexItemFactory.objectType;
      }
      superType = superClass.getSuperType();
    } while (true);
  }

  private boolean isMaybeEligibleForClassInlining(ClasspathOrLibraryClass clazz) {
    // We can only class inline a parameter that is either java.lang.Object or an interface type.
    return clazz.getType() == dexItemFactory.objectType || clazz.isInterface();
  }

  private TransferFunctionResult<ParameterUsages> widen(ParameterUsages state) {
    // Currently we only fork one context.
    int maxNumberOfContexts = 1;
    ParameterUsages widened =
        state.rebuildParameters(
            (parameter, usagePerContext) -> {
              if (usagePerContext.isBottom() || usagePerContext.isTop()) {
                return usagePerContext;
              }
              NonEmptyParameterUsagePerContext nonEmptyUsagePerContext = usagePerContext.asKnown();
              if (nonEmptyUsagePerContext.getNumberOfContexts() == maxNumberOfContexts
                  && nonEmptyUsagePerContext.allMatch(
                      (context, usageInContext) -> usageInContext.isTop())) {
                return ParameterUsagePerContext.top();
              }
              return usagePerContext;
            });
    if (!widened.isBottom()
        && !widened.isTop()
        && widened.asNonEmpty().allMatch((parameter, usagePerContext) -> usagePerContext.isTop())) {
      return fail();
    }
    return widened;
  }
}
