// Copyright (c) 2022, 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.lightir;

import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.AppView;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexMethod;
import com.android.tools.r8.graph.DexMethodHandle;
import com.android.tools.r8.graph.DexProto;
import com.android.tools.r8.graph.DexReference;
import com.android.tools.r8.graph.DexString;
import com.android.tools.r8.graph.DexType;
import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.ir.analysis.type.Nullability;
import com.android.tools.r8.ir.analysis.type.PrimitiveTypeElement;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.Add;
import com.android.tools.r8.ir.code.And;
import com.android.tools.r8.ir.code.Argument;
import com.android.tools.r8.ir.code.ArrayGet;
import com.android.tools.r8.ir.code.ArrayLength;
import com.android.tools.r8.ir.code.ArrayPut;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CatchHandlers;
import com.android.tools.r8.ir.code.CheckCast;
import com.android.tools.r8.ir.code.Cmp;
import com.android.tools.r8.ir.code.Cmp.Bias;
import com.android.tools.r8.ir.code.ConstClass;
import com.android.tools.r8.ir.code.ConstMethodHandle;
import com.android.tools.r8.ir.code.ConstMethodType;
import com.android.tools.r8.ir.code.ConstNumber;
import com.android.tools.r8.ir.code.ConstString;
import com.android.tools.r8.ir.code.DebugLocalRead;
import com.android.tools.r8.ir.code.DebugLocalWrite;
import com.android.tools.r8.ir.code.DebugPosition;
import com.android.tools.r8.ir.code.DexItemBasedConstString;
import com.android.tools.r8.ir.code.Div;
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.IfType;
import com.android.tools.r8.ir.code.InitClass;
import com.android.tools.r8.ir.code.InstanceGet;
import com.android.tools.r8.ir.code.InstanceOf;
import com.android.tools.r8.ir.code.InstancePut;
import com.android.tools.r8.ir.code.Instruction;
import com.android.tools.r8.ir.code.IntSwitch;
import com.android.tools.r8.ir.code.InvokeCustom;
import com.android.tools.r8.ir.code.InvokeDirect;
import com.android.tools.r8.ir.code.InvokeInterface;
import com.android.tools.r8.ir.code.InvokeMultiNewArray;
import com.android.tools.r8.ir.code.InvokeNewArray;
import com.android.tools.r8.ir.code.InvokePolymorphic;
import com.android.tools.r8.ir.code.InvokeStatic;
import com.android.tools.r8.ir.code.InvokeSuper;
import com.android.tools.r8.ir.code.InvokeVirtual;
import com.android.tools.r8.ir.code.MemberType;
import com.android.tools.r8.ir.code.Monitor;
import com.android.tools.r8.ir.code.MonitorType;
import com.android.tools.r8.ir.code.MoveException;
import com.android.tools.r8.ir.code.Mul;
import com.android.tools.r8.ir.code.Neg;
import com.android.tools.r8.ir.code.NewArrayEmpty;
import com.android.tools.r8.ir.code.NewArrayFilledData;
import com.android.tools.r8.ir.code.NewInstance;
import com.android.tools.r8.ir.code.NewUnboxedEnumInstance;
import com.android.tools.r8.ir.code.Not;
import com.android.tools.r8.ir.code.NumberConversion;
import com.android.tools.r8.ir.code.NumberGenerator;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.code.Or;
import com.android.tools.r8.ir.code.Phi;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.Position.SyntheticPosition;
import com.android.tools.r8.ir.code.RecordFieldValues;
import com.android.tools.r8.ir.code.Rem;
import com.android.tools.r8.ir.code.Return;
import com.android.tools.r8.ir.code.SafeCheckCast;
import com.android.tools.r8.ir.code.Shl;
import com.android.tools.r8.ir.code.Shr;
import com.android.tools.r8.ir.code.StaticGet;
import com.android.tools.r8.ir.code.StaticPut;
import com.android.tools.r8.ir.code.Sub;
import com.android.tools.r8.ir.code.Throw;
import com.android.tools.r8.ir.code.Ushr;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.ir.code.Xor;
import com.android.tools.r8.ir.conversion.MethodConversionOptions.MutableMethodConversionOptions;
import com.android.tools.r8.lightir.LirBuilder.IntSwitchPayload;
import com.android.tools.r8.lightir.LirCode.PositionEntry;
import com.android.tools.r8.lightir.LirCode.TryCatchTable;
import com.android.tools.r8.naming.dexitembasedstring.NameComputationInfo;
import com.android.tools.r8.utils.ListUtils;
import com.google.common.collect.ImmutableList;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import it.unimi.dsi.fastutil.ints.IntList;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class Lir2IRConverter {

  private Lir2IRConverter() {}

  public static <EV> IRCode translate(
      ProgramMethod method,
      LirCode<EV> lirCode,
      LirDecodingStrategy<Value, EV> strategy,
      AppView<?> appView) {
    Parser<EV> parser = new Parser<>(lirCode, method.getReference(), appView, strategy);
    parser.parseArguments(method);
    parser.ensureDebugInfo();
    lirCode.forEach(view -> view.accept(parser));
    return parser.getIRCode(method);
  }

  /**
   * When building IR the structured LIR parser is used to obtain the decoded operand indexes. The
   * below parser subclass handles translation of indexes to SSA values.
   */
  private static class Parser<EV> extends LirParsedInstructionCallback<EV> {

    private static final int ENTRY_BLOCK_INDEX = -1;

    private final AppView<?> appView;
    private final LirCode<EV> code;
    private final LirDecodingStrategy<Value, EV> strategy;
    private final NumberGenerator valueNumberGenerator = new NumberGenerator();
    private final NumberGenerator basicBlockNumberGenerator = new NumberGenerator();

    private final Int2ReferenceMap<BasicBlock> blocks = new Int2ReferenceOpenHashMap<>();

    private BasicBlock currentBlock = null;
    private int nextInstructionIndex = 0;

    private Position currentPosition;
    private PositionEntry nextPositionEntry = null;
    private int nextIndexInPositionsTable = 0;

    public Parser(
        LirCode<EV> code,
        DexMethod method,
        AppView<?> appView,
        LirDecodingStrategy<Value, EV> strategy) {
      super(code);
      this.appView = appView;
      this.code = code;
      this.strategy = strategy;
      // Recreate the preamble position. This is active for arguments and code with no positions.
      currentPosition = SyntheticPosition.builder().setLine(0).setMethod(method).build();
    }

    @Override
    public int getCurrentValueIndex() {
      return nextInstructionIndex + code.getArgumentCount();
    }

    private void closeCurrentBlock() {
      currentBlock = null;
    }

    private void ensureCurrentBlock() {
      // Control instructions must close the block, thus the current block is null iff the
      // instruction denotes a new block.
      if (currentBlock == null) {
        currentBlock = getBasicBlock(nextInstructionIndex);
        TryCatchTable tryCatchTable = code.getTryCatchTable();
        if (tryCatchTable != null) {
          CatchHandlers<Integer> handlers = tryCatchTable.getHandlersForBlock(nextInstructionIndex);
          if (handlers != null) {
            List<BasicBlock> targets = ListUtils.map(handlers.getAllTargets(), this::getBasicBlock);
            targets.forEach(currentBlock::link);
            currentBlock.linkCatchSuccessors(handlers.getGuards(), targets);
          }
        }
      } else {
        assert !blocks.containsKey(nextInstructionIndex);
      }
    }

    private void ensureCurrentPosition() {
      if (nextPositionEntry != null
          && nextPositionEntry.fromInstructionIndex <= nextInstructionIndex) {
        currentPosition = nextPositionEntry.position;
        advanceNextPositionEntry();
      }
    }

    private void advanceNextPositionEntry() {
      nextPositionEntry =
          nextIndexInPositionsTable < code.getPositionTable().length
              ? code.getPositionTable()[nextIndexInPositionsTable++]
              : null;
    }

    public void parseArguments(ProgramMethod method) {
      currentBlock = getBasicBlock(ENTRY_BLOCK_INDEX);
      boolean hasReceiverArgument = !method.getDefinition().isStatic();
      assert code.getArgumentCount()
          == method.getParameters().size() + (hasReceiverArgument ? 1 : 0);
      if (hasReceiverArgument) {
        addThisArgument(method.getHolderType());
      }
      int index = hasReceiverArgument ? 1 : 0;
      for (DexType parameter : method.getParameters()) {
        addArgument(parameter, index++);
      }
      // Set up position state after adding arguments.
      advanceNextPositionEntry();
    }

    public void ensureDebugInfo() {
      if (code.getDebugLocalInfoTable() == null) {
        return;
      }
      code.getDebugLocalInfoTable()
          .forEachLocalDefinition(
              (encodedValue, localInfo) -> {
                Value value = getValue(encodedValue);
                if (!value.hasLocalInfo()) {
                  value.setLocalInfo(localInfo);
                }
                assert value.getLocalInfo() == localInfo;
              });
    }

    // TODO(b/270398965): Replace LinkedList.
    @SuppressWarnings("JdkObsolete")
    public IRCode getIRCode(ProgramMethod method) {
      LinkedList<BasicBlock> blockList = new LinkedList<>();
      IntList blockIndices = new IntArrayList(blocks.keySet());
      blockIndices.sort(Integer::compare);
      for (int i = 0; i < blockIndices.size(); i++) {
        BasicBlock block = blocks.get(blockIndices.getInt(i));
        block.setFilled();
        blockList.add(block);
        // LIR has no value-user info so after building is done, removed unused values.
        for (Instruction instruction : block.getInstructions()) {
          if (instruction.hasOutValue()
              && instruction.isInvoke()
              && instruction.hasUnusedOutValue()) {
            instruction.clearOutValue();
          }
        }
      }
      for (int i = 0; i < peekNextInstructionIndex(); ++i) {
        valueNumberGenerator.next();
      }
      return new IRCode(
          appView.options(),
          method,
          Position.syntheticNone(),
          blockList,
          valueNumberGenerator,
          basicBlockNumberGenerator,
          code.getMetadata(),
          method.getOrigin(),
          new MutableMethodConversionOptions(appView.options()));
    }

    public BasicBlock getBasicBlock(int instructionIndex) {
      return blocks.computeIfAbsent(
          instructionIndex,
          k -> {
            BasicBlock block = new BasicBlock();
            block.setNumber(basicBlockNumberGenerator.next());
            return block;
          });
    }

    public Value getValue(EV encodedValue) {
      return strategy.getValue(encodedValue, code.getStrategyInfo());
    }

    public List<Value> getValues(List<EV> indices) {
      List<Value> arguments = new ArrayList<>(indices.size());
      for (int i = 0; i < indices.size(); i++) {
        arguments.add(getValue(indices.get(i)));
      }
      return arguments;
    }

    public int toInstructionIndexInIR(int lirIndex) {
      return lirIndex + code.getArgumentCount();
    }

    public int peekNextInstructionIndex() {
      return nextInstructionIndex;
    }

    public Value getOutValueForNextInstruction(TypeElement type) {
      int valueIndex = toInstructionIndexInIR(peekNextInstructionIndex());
      return strategy.getValueDefinitionForInstructionIndex(
          valueIndex, type, code::getDebugLocalInfo);
    }

    public Phi getPhiForNextInstructionAndAdvanceState(TypeElement type) {
      int instructionIndex = peekNextInstructionIndex();
      int valueIndex = toInstructionIndexInIR(instructionIndex);
      Phi phi =
          strategy.getPhiDefinitionForInstructionIndex(
              valueIndex,
              blockIndex -> getBasicBlockOrEnsureCurrentBlock(blockIndex, instructionIndex),
              type,
              code::getDebugLocalInfo,
              code.getStrategyInfo());
      ensureCurrentPosition();
      ++nextInstructionIndex;
      return phi;
    }

    private BasicBlock getBasicBlockOrEnsureCurrentBlock(int index, int currentInstructionIndex) {
      // If the index is at current or past it ensure the block.
      if (index >= currentInstructionIndex) {
        ensureCurrentBlock();
        return currentBlock;
      }
      // Otherwise we assume the index is an exact block index for an existing block.
      assert blocks.containsKey(index);
      return getBasicBlock(index);
    }

    private void advanceInstructionState() {
      ensureCurrentBlock();
      ensureCurrentPosition();
      ++nextInstructionIndex;
    }

    private void addInstruction(Instruction instruction) {
      int index = toInstructionIndexInIR(peekNextInstructionIndex());
      advanceInstructionState();
      instruction.setPosition(currentPosition);
      currentBlock.getInstructions().add(instruction);
      instruction.setBlock(currentBlock);
      int[] debugEndIndices = code.getDebugLocalEnds(index);
      if (debugEndIndices != null) {
        for (int encodedDebugEndIndex : debugEndIndices) {
          EV debugEndIndex = code.decodeValueIndex(encodedDebugEndIndex, index);
          Value debugValue = getValue(debugEndIndex);
          debugValue.addDebugLocalEnd(instruction);
        }
      }
    }

    private void addThisArgument(DexType type) {
      Argument argument = addArgument(type, 0);
      argument.outValue().markAsThis();
    }

    private Argument addArgument(DexType type, int index) {
      // Arguments are not included in the "instructions" so this does not call "addInstruction"
      // which would otherwise advance the state.
      TypeElement typeElement = type.toTypeElement(appView);
      Value dest =
          strategy.getValueDefinitionForInstructionIndex(
              index, typeElement, code::getDebugLocalInfo);
      Argument argument = new Argument(dest, index, type.isBooleanType());
      assert currentBlock != null;
      assert currentPosition.isSyntheticPosition();
      argument.setPosition(currentPosition);
      currentBlock.getInstructions().add(argument);
      argument.setBlock(currentBlock);
      return argument;
    }

    @Override
    public void onInstruction() {
      throw new Unimplemented("Missing IR conversion");
    }

    @Override
    public void onConstNull() {
      Value dest = getOutValueForNextInstruction(TypeElement.getNull());
      addInstruction(new ConstNumber(dest, 0));
    }

    @Override
    public void onConstInt(int value) {
      Value dest = getOutValueForNextInstruction(TypeElement.getInt());
      addInstruction(new ConstNumber(dest, value));
    }

    @Override
    public void onConstFloat(int value) {
      Value dest = getOutValueForNextInstruction(TypeElement.getFloat());
      addInstruction(new ConstNumber(dest, value));
    }

    @Override
    public void onConstLong(long value) {
      Value dest = getOutValueForNextInstruction(TypeElement.getLong());
      addInstruction(new ConstNumber(dest, value));
    }

    @Override
    public void onConstDouble(long value) {
      Value dest = getOutValueForNextInstruction(TypeElement.getDouble());
      addInstruction(new ConstNumber(dest, value));
    }

    TypeElement valueTypeElement(NumericType type) {
      return PrimitiveTypeElement.fromNumericType(type);
    }

    @Override
    public void onAdd(NumericType type, EV leftValueIndex, EV rightValueIndex) {
      Value dest = getOutValueForNextInstruction(valueTypeElement(type));
      addInstruction(
          Add.createNonNormalized(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
    }

    @Override
    public void onSub(NumericType type, EV leftValueIndex, EV rightValueIndex) {
      Value dest = getOutValueForNextInstruction(valueTypeElement(type));
      addInstruction(new Sub(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
    }

    @Override
    public void onMul(NumericType type, EV leftValueIndex, EV rightValueIndex) {
      Value dest = getOutValueForNextInstruction(valueTypeElement(type));
      addInstruction(
          Mul.createNonNormalized(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
    }

    @Override
    public void onDiv(NumericType type, EV leftValueIndex, EV rightValueIndex) {
      Value dest = getOutValueForNextInstruction(valueTypeElement(type));
      addInstruction(new Div(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
    }

    @Override
    public void onRem(NumericType type, EV leftValueIndex, EV rightValueIndex) {
      Value dest = getOutValueForNextInstruction(valueTypeElement(type));
      addInstruction(new Rem(type, dest, getValue(leftValueIndex), getValue(rightValueIndex)));
    }

    @Override
    public void onNeg(NumericType type, EV value) {
      Value dest = getOutValueForNextInstruction(valueTypeElement(type));
      addInstruction(new Neg(type, dest, getValue(value)));
    }

    @Override
    public void onNot(NumericType type, EV value) {
      Value dest = getOutValueForNextInstruction(valueTypeElement(type));
      addInstruction(new Not(type, dest, getValue(value)));
    }

    @Override
    public void onShl(NumericType type, EV left, EV right) {
      Value dest = getOutValueForNextInstruction(valueTypeElement(type));
      addInstruction(new Shl(type, dest, getValue(left), getValue(right)));
    }

    @Override
    public void onShr(NumericType type, EV left, EV right) {
      Value dest = getOutValueForNextInstruction(valueTypeElement(type));
      addInstruction(new Shr(type, dest, getValue(left), getValue(right)));
    }

    @Override
    public void onUshr(NumericType type, EV left, EV right) {
      Value dest = getOutValueForNextInstruction(valueTypeElement(type));
      addInstruction(new Ushr(type, dest, getValue(left), getValue(right)));
    }

    @Override
    public void onAnd(NumericType type, EV left, EV right) {
      Value dest = getOutValueForNextInstruction(valueTypeElement(type));
      addInstruction(And.createNonNormalized(type, dest, getValue(left), getValue(right)));
    }

    @Override
    public void onOr(NumericType type, EV left, EV right) {
      Value dest = getOutValueForNextInstruction(valueTypeElement(type));
      addInstruction(Or.createNonNormalized(type, dest, getValue(left), getValue(right)));
    }

    @Override
    public void onXor(NumericType type, EV left, EV right) {
      Value dest = getOutValueForNextInstruction(valueTypeElement(type));
      addInstruction(Xor.createNonNormalized(type, dest, getValue(left), getValue(right)));
    }

    @Override
    public void onConstString(DexString string) {
      Value dest =
          getOutValueForNextInstruction(
              TypeElement.stringClassType(appView, Nullability.definitelyNotNull()));
      addInstruction(new ConstString(dest, string));
    }

    @Override
    public void onDexItemBasedConstString(
        DexReference item, NameComputationInfo<?> nameComputationInfo) {
      Value dest =
          getOutValueForNextInstruction(
              TypeElement.stringClassType(appView, Nullability.definitelyNotNull()));
      addInstruction(new DexItemBasedConstString(dest, item, nameComputationInfo));
    }

    @Override
    public void onConstClass(DexType type, boolean ignoreCompatRules) {
      Value dest =
          getOutValueForNextInstruction(
              type.toTypeElement(appView, Nullability.definitelyNotNull()));
      addInstruction(new ConstClass(dest, type, ignoreCompatRules));
    }

    @Override
    public void onConstMethodHandle(DexMethodHandle methodHandle) {
      TypeElement handleType =
          TypeElement.fromDexType(
              appView.dexItemFactory().methodHandleType, Nullability.definitelyNotNull(), appView);
      Value dest = getOutValueForNextInstruction(handleType);
      addInstruction(new ConstMethodHandle(dest, methodHandle));
    }

    @Override
    public void onConstMethodType(DexProto methodType) {
      TypeElement typeElement =
          TypeElement.fromDexType(
              appView.dexItemFactory().methodTypeType, Nullability.definitelyNotNull(), appView);
      Value dest = getOutValueForNextInstruction(typeElement);
      addInstruction(new ConstMethodType(dest, methodType));
    }

    @Override
    public void onNumberConversion(NumericType from, NumericType to, EV value) {
      Value dest =
          getOutValueForNextInstruction(
              to.toDexType(appView.dexItemFactory()).toTypeElement(appView));
      addInstruction(new NumberConversion(from, to, dest, getValue(value)));
    }

    @Override
    public void onIf(IfType ifKind, int blockIndex, EV valueIndex) {
      BasicBlock targetBlock = getBasicBlock(blockIndex);
      Value value = getValue(valueIndex);
      addInstruction(new If(ifKind, value));
      currentBlock.link(targetBlock);
      currentBlock.link(getBasicBlock(nextInstructionIndex));
      closeCurrentBlock();
    }

    @Override
    public void onIfCmp(IfType ifKind, int blockIndex, EV leftValueIndex, EV rightValueIndex) {
      BasicBlock targetBlock = getBasicBlock(blockIndex);
      Value leftValue = getValue(leftValueIndex);
      Value rightValue = getValue(rightValueIndex);
      addInstruction(new If(ifKind, ImmutableList.of(leftValue, rightValue)));
      currentBlock.link(targetBlock);
      currentBlock.link(getBasicBlock(nextInstructionIndex));
      closeCurrentBlock();
    }

    @Override
    public void onFallthrough() {
      int nextBlockIndex = peekNextInstructionIndex() + 1;
      onGoto(nextBlockIndex);
    }

    @Override
    public void onGoto(int blockIndex) {
      BasicBlock targetBlock = getBasicBlock(blockIndex);
      addInstruction(new Goto());
      currentBlock.link(targetBlock);
      closeCurrentBlock();
    }

    @Override
    public void onIntSwitch(EV value, IntSwitchPayload payload) {
      // keys is the 'value' -> 'target index' mapping.
      int[] keys = payload.keys;
      // successorIndices is the 'target index' to 'IR successor index'.
      int[] successorIndices = new int[keys.length];
      List<BasicBlock> successorBlocks = new ArrayList<>();
      {
        // The mapping from instruction to successor is a temp mapping to track if any targets
        // point to the same block.
        Int2IntMap instructionToSuccessor = new Int2IntOpenHashMap();
        for (int i = 0; i < successorIndices.length; i++) {
          int instructionIndex = payload.targets[i];
          if (instructionToSuccessor.containsKey(instructionIndex)) {
            successorIndices[i] = instructionToSuccessor.get(instructionIndex);
          } else {
            int successorIndex = successorBlocks.size();
            successorIndices[i] = successorIndex;
            instructionToSuccessor.put(instructionIndex, successorIndex);
            successorBlocks.add(getBasicBlock(instructionIndex));
          }
        }
      }
      int fallthrough = successorBlocks.size();
      addInstruction(new IntSwitch(getValue(value), keys, successorIndices, fallthrough));
      // The call to addInstruction will ensure the current block so don't amend to it before here.
      // If the block has successors then the index mappings are not valid / need to be offset.
      assert currentBlock.getSuccessors().isEmpty();
      successorBlocks.forEach(currentBlock::link);
      currentBlock.link(getBasicBlock(nextInstructionIndex));
      closeCurrentBlock();
    }

    @Override
    public void onInvokeDirect(DexMethod target, List<EV> arguments, boolean isInterface) {
      Value dest = getInvokeInstructionOutputValue(target);
      List<Value> ssaArgumentValues = getValues(arguments);
      InvokeDirect instruction = new InvokeDirect(target, dest, ssaArgumentValues, isInterface);
      addInstruction(instruction);
    }

    @Override
    public void onInvokeSuper(DexMethod method, List<EV> arguments, boolean isInterface) {
      Value dest = getInvokeInstructionOutputValue(method);
      List<Value> ssaArgumentValues = getValues(arguments);
      InvokeSuper instruction = new InvokeSuper(method, dest, ssaArgumentValues, isInterface);
      addInstruction(instruction);
    }

    @Override
    public void onInvokeVirtual(DexMethod target, List<EV> arguments) {
      Value dest = getInvokeInstructionOutputValue(target);
      List<Value> ssaArgumentValues = getValues(arguments);
      InvokeVirtual instruction = new InvokeVirtual(target, dest, ssaArgumentValues);
      addInstruction(instruction);
    }

    @Override
    public void onInvokeStatic(DexMethod target, List<EV> arguments, boolean isInterface) {
      Value dest = getInvokeInstructionOutputValue(target);
      List<Value> ssaArgumentValues = getValues(arguments);
      InvokeStatic instruction = new InvokeStatic(target, dest, ssaArgumentValues, isInterface);
      addInstruction(instruction);
    }

    @Override
    public void onInvokeInterface(DexMethod target, List<EV> arguments) {
      Value dest = getInvokeInstructionOutputValue(target);
      List<Value> ssaArgumentValues = getValues(arguments);
      InvokeInterface instruction = new InvokeInterface(target, dest, ssaArgumentValues);
      addInstruction(instruction);
    }

    @Override
    public void onInvokeCustom(DexCallSite callSite, List<EV> arguments) {
      Value dest = getInvokeInstructionOutputValue(callSite.methodProto);
      List<Value> ssaArgumentValues = getValues(arguments);
      InvokeCustom instruction = new InvokeCustom(callSite, dest, ssaArgumentValues);
      addInstruction(instruction);
    }

    @Override
    public void onInvokePolymorphic(DexMethod target, DexProto proto, List<EV> arguments) {
      Value dest = getInvokeInstructionOutputValue(proto);
      List<Value> ssaArgumentValues = getValues(arguments);
      InvokePolymorphic instruction = new InvokePolymorphic(target, proto, dest, ssaArgumentValues);
      addInstruction(instruction);
    }

    private Value getInvokeInstructionOutputValue(DexMethod target) {
      return getInvokeInstructionOutputValue(target.getProto());
    }

    private Value getInvokeInstructionOutputValue(DexProto target) {
      DexType returnType = target.getReturnType();
      return returnType.isVoidType()
          ? null
          : getOutValueForNextInstruction(returnType.toTypeElement(appView));
    }

    @Override
    public void onNewInstance(DexType clazz) {
      TypeElement type = TypeElement.fromDexType(clazz, Nullability.definitelyNotNull(), appView);
      Value dest = getOutValueForNextInstruction(type);
      addInstruction(new NewInstance(clazz, dest));
    }

    @Override
    public void onStaticGet(DexField field) {
      Value dest = getOutValueForNextInstruction(field.getTypeElement(appView));
      addInstruction(new StaticGet(dest, field));
    }

    @Override
    public void onStaticPut(DexField field, EV value) {
      addInstruction(new StaticPut(getValue(value), field));
    }

    @Override
    public void onInstanceGet(DexField field, EV object) {
      Value dest = getOutValueForNextInstruction(field.getTypeElement(appView));
      addInstruction(new InstanceGet(dest, getValue(object), field));
    }

    @Override
    public void onInstancePut(DexField field, EV object, EV value) {
      addInstruction(
          InstancePut.createPotentiallyInvalid(field, getValue(object), getValue(value)));
    }

    @Override
    public void onNewArrayEmpty(DexType type, EV size) {
      Value dest = getOutValueForNextInstruction(type.toTypeElement(appView));
      addInstruction(new NewArrayEmpty(dest, getValue(size), type));
    }

    @Override
    public void onThrow(EV exception) {
      addInstruction(new Throw(getValue(exception)));
      closeCurrentBlock();
    }

    @Override
    public void onReturnVoid() {
      addInstruction(new Return());
      closeCurrentBlock();
    }

    @Override
    public void onReturn(EV value) {
      addInstruction(new Return(getValue(value)));
      closeCurrentBlock();
    }

    @Override
    public void onArrayLength(EV arrayValueIndex) {
      Value dest = getOutValueForNextInstruction(TypeElement.getInt());
      Value arrayValue = getValue(arrayValueIndex);
      addInstruction(new ArrayLength(dest, arrayValue));
    }

    @Override
    public void onCheckCast(DexType type, EV value, boolean ignoreCompatRules) {
      Value dest = getOutValueForNextInstruction(type.toTypeElement(appView));
      addInstruction(new CheckCast(dest, getValue(value), type, ignoreCompatRules));
    }

    @Override
    public void onSafeCheckCast(DexType type, EV value) {
      Value dest = getOutValueForNextInstruction(type.toTypeElement(appView));
      addInstruction(new SafeCheckCast(dest, getValue(value), type));
    }

    @Override
    public void onInstanceOf(DexType type, EV value) {
      Value dest = getOutValueForNextInstruction(TypeElement.getInt());
      addInstruction(new InstanceOf(dest, getValue(value), type));
    }

    @Override
    public void onDebugPosition() {
      addInstruction(new DebugPosition());
    }

    @Override
    public void onPhi(DexType type, List<EV> operands) {
      Phi phi = getPhiForNextInstructionAndAdvanceState(type.toTypeElement(appView));
      List<Value> values = new ArrayList<>(operands.size());
      for (int i = 0; i < operands.size(); i++) {
        values.add(getValue(operands.get(i)));
      }
      phi.addOperands(values);
    }

    @Override
    public void onMoveException(DexType exceptionType) {
      Value dest = getOutValueForNextInstruction(exceptionType.toTypeElement(appView));
      addInstruction(new MoveException(dest, exceptionType, appView.options()));
    }

    @Override
    public void onDebugLocalWrite(EV srcIndex) {
      Value src = getValue(srcIndex);
      // The type is in the local table, so initialize it with bottom and reset with the local info.
      Value dest = getOutValueForNextInstruction(TypeElement.getBottom());
      TypeElement type = dest.getLocalInfo().type.toTypeElement(appView);
      dest.setType(type);
      addInstruction(new DebugLocalWrite(dest, src));
    }

    @Override
    public void onDebugLocalRead() {
      addInstruction(new DebugLocalRead());
    }

    @Override
    public void onInvokeMultiNewArray(DexType type, List<EV> arguments) {
      Value dest =
          getOutValueForNextInstruction(
              type.toTypeElement(appView, Nullability.definitelyNotNull()));
      addInstruction(new InvokeMultiNewArray(type, dest, getValues(arguments)));
    }

    @Override
    public void onInvokeNewArray(DexType type, List<EV> arguments) {
      Value dest =
          getOutValueForNextInstruction(
              type.toTypeElement(appView, Nullability.definitelyNotNull()));
      addInstruction(new InvokeNewArray(type, dest, getValues(arguments)));
    }

    @Override
    public void onNewArrayFilledData(int elementWidth, long size, short[] data, EV src) {
      addInstruction(new NewArrayFilledData(getValue(src), elementWidth, size, data));
    }

    @Override
    public void onCmpInstruction(int opcode, EV leftIndex, EV rightIndex) {
      NumericType type;
      Bias bias;
      switch (opcode) {
        case LirOpcodes.LCMP:
          type = NumericType.LONG;
          bias = Bias.NONE;
          break;
        case LirOpcodes.FCMPL:
          type = NumericType.FLOAT;
          bias = Bias.LT;
          break;
        case LirOpcodes.FCMPG:
          type = NumericType.FLOAT;
          bias = Bias.GT;
          break;
        case LirOpcodes.DCMPL:
          type = NumericType.DOUBLE;
          bias = Bias.LT;
          break;
        case LirOpcodes.DCMPG:
          type = NumericType.DOUBLE;
          bias = Bias.GT;
          break;
        default:
          throw new Unreachable("Unexpected cmp opcode: " + opcode);
      }
      Value leftValue = getValue(leftIndex);
      Value rightValue = getValue(rightIndex);
      Value dest = getOutValueForNextInstruction(TypeElement.getInt());
      addInstruction(new Cmp(type, bias, dest, leftValue, rightValue));
    }

    @Override
    public void onMonitorEnter(EV value) {
      addInstruction(new Monitor(MonitorType.ENTER, getValue(value)));
    }

    @Override
    public void onMonitorExit(EV value) {
      addInstruction(new Monitor(MonitorType.EXIT, getValue(value)));
    }

    @Override
    public void onArrayGetObject(DexType type, EV array, EV index) {
      Value dest = getOutValueForNextInstruction(type.toTypeElement(appView));
      addInstruction(new ArrayGet(MemberType.OBJECT, dest, getValue(array), getValue(index)));
    }

    @Override
    public void onArrayGetPrimitive(MemberType type, EV array, EV index) {
      // Convert the member type to a "stack value type", e.g., byte, char etc to int.
      ValueType valueType = ValueType.fromMemberType(type);
      DexType dexType = valueType.toDexType(appView.dexItemFactory());
      Value dest = getOutValueForNextInstruction(dexType.toTypeElement(appView));
      addInstruction(new ArrayGet(type, dest, getValue(array), getValue(index)));
    }

    @Override
    public void onArrayPut(MemberType type, EV array, EV index, EV value) {
      addInstruction(
          ArrayPut.createWithoutVerification(
              type, getValue(array), getValue(index), getValue(value)));
    }

    @Override
    public void onNewUnboxedEnumInstance(DexType clazz, int ordinal) {
      TypeElement type = TypeElement.fromDexType(clazz, Nullability.definitelyNotNull(), appView);
      Value dest = getOutValueForNextInstruction(type);
      addInstruction(new NewUnboxedEnumInstance(clazz, ordinal, dest));
    }

    @Override
    public void onInitClass(DexType clazz) {
      Value dest = getOutValueForNextInstruction(TypeElement.getInt());
      addInstruction(new InitClass(dest, clazz));
    }

    @Override
    public void onRecordFieldValues(DexField[] fields, List<EV> values) {
      TypeElement typeElement =
          TypeElement.fromDexType(
              appView.dexItemFactory().objectArrayType, Nullability.definitelyNotNull(), appView);
      Value dest = getOutValueForNextInstruction(typeElement);
      addInstruction(new RecordFieldValues(fields, dest, getValues(values)));
    }
  }
}
