// Copyright (c) 2017, 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.cf.code;

import com.android.tools.r8.cf.CfPrinter;
import com.android.tools.r8.dex.Constants;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.CfCompareHelper;
import com.android.tools.r8.graph.DexClassAndMethod;
import com.android.tools.r8.graph.DexItemFactory;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.graph.UseRegistry;
import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.graph.lens.InitClassLens;
import com.android.tools.r8.graph.lens.MethodLookupResult;
import com.android.tools.r8.ir.code.InvokeType;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.conversion.CfSourceCode;
import com.android.tools.r8.ir.conversion.CfState;
import com.android.tools.r8.ir.conversion.CfState.Slot;
import com.android.tools.r8.ir.conversion.IRBuilder;
import com.android.tools.r8.ir.conversion.LensCodeRewriterUtils;
import com.android.tools.r8.naming.NamingLens;
import com.android.tools.r8.optimize.interfaces.analysis.CfAnalysisConfig;
import com.android.tools.r8.optimize.interfaces.analysis.CfFrameState;
import com.android.tools.r8.utils.DescriptorUtils;
import com.android.tools.r8.utils.structural.CompareToVisitor;
import com.android.tools.r8.utils.structural.HashingVisitor;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import java.util.Arrays;
import java.util.ListIterator;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;

public class CfInvoke extends CfInstruction {

  private final DexMethod method;
  private final int opcode;
  private final boolean itf;

  private static void specify(StructuralSpecification<CfInvoke, ?> spec) {
    spec.withBool(CfInvoke::isInterface).withItem(CfInvoke::getMethod);
  }

  public CfInvoke(int opcode, DexMethod method, boolean itf) {
    assert Opcodes.INVOKEVIRTUAL <= opcode && opcode <= Opcodes.INVOKEINTERFACE;
    assert !(opcode == Opcodes.INVOKEVIRTUAL && itf) : "InvokeVirtual on interface type";
    assert !(opcode == Opcodes.INVOKEINTERFACE && !itf) : "InvokeInterface on class type";
    this.opcode = opcode;
    this.method = method;
    this.itf = itf;
  }

  @Override
  public int getCompareToId() {
    return getOpcode();
  }

  @Override
  public int internalAcceptCompareTo(
      CfInstruction other, CompareToVisitor visitor, CfCompareHelper helper) {
    CfInvoke otherInvoke = other.asInvoke();
    return visitor.visit(this, otherInvoke, CfInvoke::specify);
  }

  @Override
  public void internalAcceptHashing(HashingVisitor visitor) {
    visitor.visit(this, CfInvoke::specify);
  }

  public DexMethod getMethod() {
    return method;
  }

  public int getOpcode() {
    return opcode;
  }

  public boolean isInterface() {
    return itf;
  }

  @Override
  public CfInvoke asInvoke() {
    return this;
  }

  @Override
  public boolean isInvoke() {
    return true;
  }

  @Override
  public void write(
      AppView<?> appView,
      ProgramMethod context,
      DexItemFactory dexItemFactory,
      GraphLens graphLens,
      GraphLens codeLens,
      InitClassLens initClassLens,
      NamingLens namingLens,
      LensCodeRewriterUtils rewriter,
      MethodVisitor visitor) {
    InvokeType invokeType = InvokeType.fromCfOpcode(opcode, method, context, appView);
    if (invokeType == InvokeType.POLYMORPHIC) {
      assert dexItemFactory.polymorphicMethods.isPolymorphicInvoke(method);
      // The method is one of java.lang.MethodHandle.invoke/invokeExact.
      // Only the method signature (getProto()) is to be type rewritten.
      DexProto rewrittenProto = rewriter.rewriteProto(method.getProto());
      visitor.visitMethodInsn(
          invokeType.getCfOpcode(),
          DescriptorUtils.descriptorToInternalName(method.holder.toDescriptorString()),
          method.getName().toString(),
          rewrittenProto.toDescriptorString(namingLens),
          itf);
    } else {
      MethodLookupResult lookup =
          graphLens.lookupMethod(method, context.getReference(), invokeType, codeLens);
      InvokeType rewrittenType = lookup.getType();
      DexMethod rewrittenMethod = lookup.getReference();
      String owner = namingLens.lookupInternalName(rewrittenMethod.holder);
      String name = namingLens.lookupName(rewrittenMethod).toString();
      String desc = rewrittenMethod.proto.toDescriptorString(namingLens);
      visitor.visitMethodInsn(
          rewrittenType.getCfOpcode(), owner, name, desc, rewrittenType.isInterface() || itf);
    }
  }

  @Override
  public int bytecodeSizeUpperBound() {
    return opcode == Opcodes.INVOKEINTERFACE ? 5 : 3;
  }

  @Override
  public void print(CfPrinter printer) {
    printer.print(this);
  }

  @Override
  void internalRegisterUse(
      UseRegistry<?> registry, DexClassAndMethod context, ListIterator<CfInstruction> iterator) {
    switch (opcode) {
      case Opcodes.INVOKEINTERFACE:
        registry.registerInvokeInterface(method);
        break;
      case Opcodes.INVOKESPECIAL:
        registry.registerInvokeSpecial(method, itf);
        break;
      case Opcodes.INVOKESTATIC:
        registry.registerInvokeStatic(method, itf);
        break;
      case Opcodes.INVOKEVIRTUAL:
        registry.registerInvokeVirtual(method);
        break;
      default:
        throw new Unreachable("Unknown CfInvoke opcode " + opcode);
    }
  }

  public boolean isInvokeConstructor(DexItemFactory dexItemFactory) {
    return getMethod().isInstanceInitializer(dexItemFactory);
  }

  // We should avoid interpreting a CF invoke using DEX semantics.
  @Deprecated
  @SuppressWarnings("ReferenceEquality")
  public boolean isInvokeSuper(DexType clazz) {
    return opcode == Opcodes.INVOKESPECIAL
        && method.holder != clazz
        && !method.name.toString().equals(Constants.INSTANCE_INITIALIZER_NAME);
  }

  @Override
  public boolean isInvokeSpecial() {
    return opcode == Opcodes.INVOKESPECIAL;
  }

  @Override
  public boolean isInvokeStatic() {
    return opcode == Opcodes.INVOKESTATIC;
  }

  @Override
  public boolean isInvokeVirtual() {
    return opcode == Opcodes.INVOKEVIRTUAL;
  }

  @Override
  public boolean isInvokeInterface() {
    return opcode == Opcodes.INVOKEINTERFACE;
  }

  @Override
  public boolean canThrow() {
    return true;
  }

  @Override
  public void buildIR(IRBuilder builder, CfState state, CfSourceCode code) {
    InvokeType type;
    DexMethod canonicalMethod;
    DexProto callSiteProto = null;
    switch (opcode) {
      case Opcodes.INVOKEINTERFACE:
        {
          canonicalMethod = method;
          type = InvokeType.INTERFACE;
          break;
        }
      case Opcodes.INVOKEVIRTUAL:
        {
          canonicalMethod = builder.dexItemFactory().polymorphicMethods.canonicalize(method);
          if (canonicalMethod == null) {
            type = InvokeType.VIRTUAL;
            canonicalMethod = method;
          } else {
            if (builder.appView.options().shouldDesugarVarHandle()) {
              type = InvokeType.VIRTUAL;
              canonicalMethod = method;
            } else {
              type = InvokeType.POLYMORPHIC;
              callSiteProto = method.proto;
            }
          }
          break;
        }
      case Opcodes.INVOKESPECIAL:
        {
          // Per https://source.android.com/devices/tech/dalvik/dalvik-bytecode, for Dex files
          // version >= 037, if the method refers to an interface method, invoke-super is used to
          // invoke the most specific, non-overridden version of that method.
          // In https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.12.3, it is
          // a compile-time error in the case that "If TypeName denotes an interface, let T be the
          // type declaration immediately enclosing the method invocation. A compile-time error
          // occurs if there exists a method, distinct from the compile-time declaration, that
          // overrides (§9.4.1) the compile-time declaration from a direct superclass or
          // direct superinterface of T."
          // Using invoke-super should therefore observe the correct semantics since we cannot
          // target less specific targets (up in the hierarchy).
          AppView<?> appView = builder.appView;
          ProgramMethod context = builder.getProgramMethod();
          canonicalMethod = method;
          type = InvokeType.fromInvokeSpecial(method, context, appView, builder.getCodeLens());
          break;
        }
      case Opcodes.INVOKESTATIC:
        {
          canonicalMethod = method;
          type = InvokeType.STATIC;
          break;
        }
      default:
        throw new Unreachable("unknown CfInvoke opcode " + opcode);
    }

    int parameterCount = method.getParameters().size();
    if (type != InvokeType.STATIC) {
      parameterCount += 1;
    }
    ValueType[] types = new ValueType[parameterCount];
    Integer[] registers = new Integer[parameterCount];
    for (int i = parameterCount - 1; i >= 0; i--) {
      Slot slot = state.pop();
      types[i] = slot.type;
      registers[i] = slot.register;
    }
    builder.addInvoke(
        type, canonicalMethod, callSiteProto, Arrays.asList(types), Arrays.asList(registers), itf);
    if (!method.getReturnType().isVoidType()) {
      builder.addMoveResult(state.push(method.getReturnType()).register);
    }
    assert type
        == InvokeType.fromCfOpcode(
            opcode, method, builder.getProgramMethod(), builder.appView, builder.getCodeLens());
  }

  @Override
  public CfFrameState evaluate(CfFrameState frame, AppView<?> appView, CfAnalysisConfig config) {
    // ..., objectref, [arg1, [arg2 ...]] →
    // ... [ returnType ]
    // OR, for static method calls:
    // ..., [arg1, [arg2 ...]] →
    // ...
    frame = frame.popInitialized(appView, config, method.getParameters().getBacking());
    if (opcode != Opcodes.INVOKESTATIC) {
      if (method.getHolderType().isArrayType()) {
        frame = frame.popArray(appView);
      } else {
        DexItemFactory dexItemFactory = appView.dexItemFactory();
        frame =
            opcode == Opcodes.INVOKESPECIAL && method.isInstanceInitializer(dexItemFactory)
                ? frame.popAndInitialize(appView, method, config)
                : frame.popInitialized(appView, config, method.getHolderType());
      }
    }
    if (method.getReturnType().isVoidType()) {
      return frame;
    }
    return frame.push(config, method.getReturnType());
  }
}
