// 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.cf.code.CfArithmeticBinop;
import com.android.tools.r8.cf.code.CfArithmeticBinop.Opcode;
import com.android.tools.r8.cf.code.CfLogicalBinop;
import com.android.tools.r8.cf.code.CfNumberConversion;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.graph.DebugLocalInfo;
import com.android.tools.r8.graph.DexCallSite;
import com.android.tools.r8.graph.DexField;
import com.android.tools.r8.graph.DexItemFactory;
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.bytecodemetadata.BytecodeInstructionMetadata;
import com.android.tools.r8.graph.lens.GraphLens;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.code.BasicBlock;
import com.android.tools.r8.ir.code.CatchHandlers;
import com.android.tools.r8.ir.code.Cmp;
import com.android.tools.r8.ir.code.Cmp.Bias;
import com.android.tools.r8.ir.code.IfType;
import com.android.tools.r8.ir.code.MemberType;
import com.android.tools.r8.ir.code.MonitorType;
import com.android.tools.r8.ir.code.NumericType;
import com.android.tools.r8.ir.code.Position;
import com.android.tools.r8.ir.code.Position.SyntheticPosition;
import com.android.tools.r8.ir.code.ValueType;
import com.android.tools.r8.lightir.LirCode.DebugLocalInfoTable;
import com.android.tools.r8.lightir.LirCode.LinePositionEntry;
import com.android.tools.r8.lightir.LirCode.PositionEntry;
import com.android.tools.r8.lightir.LirCode.StructuredPositionEntry;
import com.android.tools.r8.lightir.LirCode.TryCatchTable;
import com.android.tools.r8.naming.dexitembasedstring.NameComputationInfo;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ListUtils;
import com.android.tools.r8.utils.structural.CompareToVisitor;
import com.android.tools.r8.utils.structural.HashingVisitor;
import com.android.tools.r8.utils.structural.StructuralItem;
import com.android.tools.r8.utils.structural.StructuralMapping;
import com.android.tools.r8.utils.structural.StructuralSpecification;
import com.google.common.collect.ImmutableList;
import it.unimi.dsi.fastutil.ints.Int2ReferenceMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceOpenHashMap;
import it.unimi.dsi.fastutil.ints.Int2ReferenceSortedMap;
import it.unimi.dsi.fastutil.objects.Reference2IntMap;
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

/** Builder for constructing LIR code from IR. */
public class LirBuilder<V, EV> {
  private static final int FLOAT_0 = Float.floatToRawIntBits(0);
  private static final int FLOAT_1 = Float.floatToRawIntBits(1);
  private static final int FLOAT_2 = Float.floatToRawIntBits(2);
  private static final long DOUBLE_0 = Double.doubleToRawLongBits(0);
  private static final long DOUBLE_1 = Double.doubleToRawLongBits(1);

  private final boolean useDexEstimationStrategy;
  private final DexItemFactory factory;
  private final ByteArrayWriter byteWriter = new ByteArrayWriter();
  private final LirWriter writer = new LirWriter(byteWriter);
  private final Reference2IntMap<LirConstant> constants;
  private final List<PositionEntry> positionTable;
  private int argumentCount = 0;
  private int instructionCount = 0;

  private final LirEncodingStrategy<V, EV> strategy;

  private BytecodeInstructionMetadata currentMetadata;
  private Int2ReferenceMap<BytecodeInstructionMetadata> metadataMap;

  private Position currentPosition;
  private Position flushedPosition;

  private final Int2ReferenceMap<CatchHandlers<Integer>> tryCatchRanges =
      new Int2ReferenceOpenHashMap<>();

  // Mapping from SSA value definition to the local name index in the constant pool.
  private final Map<EV, DebugLocalInfo> debugLocals = new HashMap<>();
  // Mapping from instruction to the end usage of SSA values with debug local info.
  private final Int2ReferenceMap<int[]> debugLocalEnds = new Int2ReferenceOpenHashMap<>();

  /**
   * Internal "LirConstant" for the instruction payloads such that they can be put in the pool.
   *
   * <p>The instruction encoding is optimized for an instruction operand payload size of u1, so this
   * allows potentially large data payloads to be stored in the constant pool instead.
   */
  public abstract static class InstructionPayload implements LirConstant {}

  /**
   * Internal "DexItem" for the fill-array payloads such that they can be put in the pool.
   *
   * <p>The instruction encoding assumes the instruction operand payload size is u1, so the data
   * payload is stored in the constant pool instead.
   */
  public static class FillArrayPayload extends InstructionPayload
      implements StructuralItem<FillArrayPayload> {
    public final int element_width;
    public final long size;
    public final short[] data;

    public FillArrayPayload(int element_width, long size, short[] data) {
      this.element_width = element_width;
      this.size = size;
      this.data = data;
    }

    @Override
    public FillArrayPayload self() {
      return this;
    }

    @Override
    public StructuralMapping<FillArrayPayload> getStructuralMapping() {
      return FillArrayPayload::specify;
    }

    private static void specify(StructuralSpecification<FillArrayPayload, ?> spec) {
      spec.withInt(s -> s.element_width).withLong(s -> s.size).withShortArray(s -> s.data);
    }

    @Override
    public LirConstantOrder getLirConstantOrder() {
      return LirConstantOrder.FILL_ARRAY;
    }

    @Override
    public int internalLirConstantAcceptCompareTo(LirConstant other, CompareToVisitor visitor) {
      return acceptCompareTo((FillArrayPayload) other, visitor);
    }

    @Override
    public void internalLirConstantAcceptHashing(HashingVisitor visitor) {
      acceptHashing(visitor);
    }
  }

  public static class IntSwitchPayload extends InstructionPayload
      implements StructuralItem<IntSwitchPayload> {
    public final int[] keys;
    public final int[] targets;

    private static void specify(StructuralSpecification<IntSwitchPayload, ?> spec) {
      spec.withIntArray(s -> s.keys).withIntArray(s -> s.targets);
    }

    public IntSwitchPayload(int[] keys, int[] targets) {
      assert keys.length == targets.length;
      this.keys = keys;
      this.targets = targets;
    }

    @Override
    public IntSwitchPayload self() {
      return this;
    }

    @Override
    public StructuralMapping<IntSwitchPayload> getStructuralMapping() {
      return IntSwitchPayload::specify;
    }

    @Override
    public LirConstantOrder getLirConstantOrder() {
      return LirConstantOrder.INT_SWITCH;
    }

    @Override
    public int internalLirConstantAcceptCompareTo(LirConstant other, CompareToVisitor visitor) {
      return acceptCompareTo((IntSwitchPayload) other, visitor);
    }

    @Override
    public void internalLirConstantAcceptHashing(HashingVisitor visitor) {
      acceptHashing(visitor);
    }
  }

  public static class StringSwitchPayload extends InstructionPayload
      implements StructuralItem<StringSwitchPayload> {
    public final int[] keys;
    public final int[] targets;

    public StringSwitchPayload(int[] keys, int[] targets) {
      assert keys.length == targets.length;
      this.keys = keys;
      this.targets = targets;
    }

    private static void specify(StructuralSpecification<StringSwitchPayload, ?> spec) {
      spec.withIntArray(s -> s.keys).withIntArray(s -> s.targets);
    }

    @Override
    public StringSwitchPayload self() {
      return this;
    }

    @Override
    public StructuralMapping<StringSwitchPayload> getStructuralMapping() {
      return StringSwitchPayload::specify;
    }

    @Override
    public LirConstantOrder getLirConstantOrder() {
      return LirConstantOrder.STRING_SWITCH;
    }

    @Override
    public void internalLirConstantAcceptHashing(HashingVisitor visitor) {
      acceptHashing(visitor);
    }

    @Override
    public int internalLirConstantAcceptCompareTo(LirConstant other, CompareToVisitor visitor) {
      return acceptCompareTo((StringSwitchPayload) other, visitor);
    }
  }

  public static class NameComputationPayload extends InstructionPayload {
    public final NameComputationInfo<?> nameComputationInfo;

    public NameComputationPayload(NameComputationInfo<?> nameComputationInfo) {
      this.nameComputationInfo = nameComputationInfo;
    }

    @Override
    public LirConstantOrder getLirConstantOrder() {
      return LirConstantOrder.NAME_COMPUTATION;
    }

    @Override
    public int internalLirConstantAcceptCompareTo(LirConstant other, CompareToVisitor visitor) {
      return 0;
    }

    @Override
    public void internalLirConstantAcceptHashing(HashingVisitor visitor) {}

    public NameComputationPayload rewrittenWithLens(GraphLens graphLens, GraphLens codeLens) {
      NameComputationInfo<?> rewrittenNameComputationInfo =
          nameComputationInfo.rewrittenWithLens(graphLens, codeLens);
      return rewrittenNameComputationInfo != nameComputationInfo
          ? new NameComputationPayload(rewrittenNameComputationInfo)
          : this;
    }
  }

  public static class RecordFieldValuesPayload extends InstructionPayload {
    public final DexField[] fields;

    public RecordFieldValuesPayload(DexField[] fields) {
      this.fields = fields;
    }

    @Override
    public LirConstantOrder getLirConstantOrder() {
      return LirConstantOrder.RECORD_FIELD_VALUES;
    }

    @Override
    public int internalLirConstantAcceptCompareTo(LirConstant other, CompareToVisitor visitor) {
      return visitor.visitItemArray(fields, ((RecordFieldValuesPayload) other).fields);
    }

    @Override
    public void internalLirConstantAcceptHashing(HashingVisitor visitor) {
      visitor.visitItemArray(fields);
    }
  }

  public LirBuilder(
      DexMethod method,
      boolean isD8R8Synthesized,
      LirEncodingStrategy<V, EV> strategy,
      InternalOptions options) {
    useDexEstimationStrategy = options.isGeneratingDex();
    factory = options.dexItemFactory();
    constants = new Reference2IntOpenHashMap<>();
    positionTable = new ArrayList<>();
    this.strategy = strategy;
    currentPosition =
        SyntheticPosition.builder()
            .setLine(0)
            .setMethod(method)
            .setIsD8R8Synthesized(isD8R8Synthesized)
            .build();
    flushedPosition = currentPosition;
  }

  public DexItemFactory factory() {
    return factory;
  }

  public boolean verifyCurrentValueIndex(int valueIndex) {
    assert instructionCount + argumentCount == valueIndex;
    return true;
  }

  public DexType toDexType(TypeElement typeElement) {
    if (typeElement.isPrimitiveType()) {
      return typeElement.asPrimitiveType().toDexType(factory);
    }
    if (typeElement.isReferenceType()) {
      return typeElement.asReferenceType().toDexType(factory);
    }
    throw new Unreachable("Unexpected type element: " + typeElement);
  }

  public void addTryCatchHanders(int blockIndex, CatchHandlers<Integer> handlers) {
    tryCatchRanges.put(blockIndex, handlers);
  }

  public LirBuilder<V, EV> prepareForBytecodeInstructionMetadata(int expectedSize) {
    if (expectedSize > 0) {
      metadataMap = new Int2ReferenceOpenHashMap<>(expectedSize);
    }
    return this;
  }

  public LirBuilder<V, EV> setCurrentMetadata(BytecodeInstructionMetadata metadata) {
    currentMetadata = metadata;
    return this;
  }

  public LirBuilder<V, EV> setCurrentPosition(Position position) {
    assert position != null;
    if (!position.isNone()) {
      currentPosition = position;
    }
    return this;
  }

  private boolean isSimpleLinePosition(Position position) {
    return (position.isSourcePosition() || position.isSyntheticPosition())
        && !position.hasCallerPosition();
  }

  private boolean setPositionIndex(int instructionIndex, Position position) {
    assert positionTable.isEmpty()
        || ListUtils.last(positionTable).getFromInstructionIndex() < instructionIndex;

    if (!isSimpleLinePosition(position)) {
      positionTable.add(new StructuredPositionEntry(instructionIndex, position));
      return true;
    }

    // Don't emit simple preamble lines in the table.
    if (positionTable.isEmpty() && position.getLine() == 0) {
      return false;
    }

    // Due to source/synthetic lines we may have non-equal positions with the same simple lines.
    if (!positionTable.isEmpty()) {
      PositionEntry last = ListUtils.last(positionTable);
      if (last instanceof LinePositionEntry) {
        if (((LinePositionEntry) last).getLine() == position.getLine()) {
          return false;
        }
      }
    }

    positionTable.add(new LinePositionEntry(instructionIndex, position.getLine()));
    return true;
  }

  private int getConstantIndex(LirConstant item) {
    int nextIndex = constants.size();
    Integer oldIndex = constants.putIfAbsent(item, nextIndex);
    return oldIndex != null ? oldIndex : nextIndex;
  }

  @SuppressWarnings("UnusedVariable")
  private int constantIndexSize(LirConstant item) {
    return 4;
  }

  private void writeConstantIndex(LirConstant item) {
    int index = getConstantIndex(item);
    assert constantIndexSize(item) == ByteUtils.intEncodingSize(index);
    ByteUtils.writeEncodedInt(index, writer::writeOperand);
  }

  private EV getEncodedValue(V value) {
    return strategy.getEncodedValue(value);
  }

  private int getEncodedValueIndex(EV value, int referencingInstructionIndex) {
    int referencingValueIndex = referencingInstructionIndex + argumentCount;
    return strategy.getEncodedValueIndexForReference(value, referencingValueIndex);
  }

  private int encodedValueIndexSize(int encodedValueIndex) {
    return ByteUtils.intEncodingSize(encodedValueIndex);
  }

  private void writeEncodedValueIndex(int encodedValueIndex) {
    ByteUtils.writeEncodedInt(encodedValueIndex, writer::writeOperand);
  }

  private int getBlockIndex(BasicBlock block) {
    return strategy.getBlockIndex(block);
  }

  private int blockIndexSize(int index) {
    return ByteUtils.intEncodingSize(index);
  }

  private void writeBlockIndex(int index) {
    ByteUtils.writeEncodedInt(index, writer::writeOperand);
  }

  public LirBuilder<V, EV> setDebugValue(DebugLocalInfo debugInfo, EV valueIndex) {
    DebugLocalInfo old = debugLocals.put(valueIndex, debugInfo);
    assert old == null;
    return this;
  }

  public LirBuilder<V, EV> setDebugLocalEnds(int instructionValueIndex, Set<V> endValues) {
    int size = endValues.size();
    int[] indices = new int[size];
    Iterator<V> iterator = endValues.iterator();
    for (int i = 0; i < size; i++) {
      EV value = getEncodedValue(iterator.next());
      // The index is already the value index (it has been offset by argument count).
      indices[i] = strategy.getEncodedValueIndexForReference(value, instructionValueIndex);
    }
    debugLocalEnds.put(instructionValueIndex, indices);
    return this;
  }

  public LirBuilder<V, EV> addArgument(int index, boolean knownToBeBoolean) {
    // Arguments are implicitly given by method descriptor and not an actual instruction.
    assert argumentCount == index;
    argumentCount++;
    return this;
  }

  private int advanceInstructionState() {
    if (!currentPosition.equals(flushedPosition)) {
      if (setPositionIndex(instructionCount, currentPosition)) {
        flushedPosition = currentPosition;
      }
    }
    if (currentMetadata != null) {
      metadataMap.put(instructionCount, currentMetadata);
      currentMetadata = null;
    }
    return instructionCount++;
  }

  private LirBuilder<V, EV> addNoOperandInstruction(int opcode) {
    advanceInstructionState();
    writer.writeOneByteInstruction(opcode);
    return this;
  }

  private LirBuilder<V, EV> addOneItemInstruction(int opcode, LirConstant item) {
    return addInstructionTemplate(opcode, Collections.singletonList(item), Collections.emptyList());
  }

  private LirBuilder<V, EV> addOneValueInstruction(int opcode, V value) {
    return addInstructionTemplate(
        opcode, Collections.emptyList(), Collections.singletonList(value));
  }

  private LirBuilder<V, EV> addTwoValueInstruction(int opcode, V leftValue, V rightValue) {
    return addInstructionTemplate(
        opcode, Collections.emptyList(), ImmutableList.of(leftValue, rightValue));
  }

  private LirBuilder<V, EV> addInstructionTemplate(
      int opcode, List<LirConstant> items, List<V> values) {
    int instructionIndex = advanceInstructionState();
    int operandSize = 0;
    for (LirConstant item : items) {
      operandSize += constantIndexSize(item);
    }
    for (int i = 0; i < values.size(); i++) {
      EV value = getEncodedValue(values.get(i));
      int encodedValueIndex = getEncodedValueIndex(value, instructionIndex);
      operandSize += encodedValueIndexSize(encodedValueIndex);
    }
    writer.writeInstruction(opcode, operandSize);
    for (LirConstant item : items) {
      writeConstantIndex(item);
    }
    for (int i = 0; i < values.size(); i++) {
      // TODO(b/225838009): Consider backpatching operand size to avoid recomputing value indexes.
      EV value = getEncodedValue(values.get(i));
      int encodedValueIndex = getEncodedValueIndex(value, instructionIndex);
      writeEncodedValueIndex(encodedValueIndex);
    }
    return this;
  }

  public LirBuilder<V, EV> addConstNull() {
    return addNoOperandInstruction(LirOpcodes.ACONST_NULL);
  }

  public LirBuilder<V, EV> addConstInt(int value) {
    if (-1 <= value && value <= 5) {
      addNoOperandInstruction(LirOpcodes.ICONST_0 + value);
    } else {
      advanceInstructionState();
      writer.writeInstruction(LirOpcodes.ICONST, ByteUtils.intEncodingSize(value));
      ByteUtils.writeEncodedInt(value, writer::writeOperand);
    }
    return this;
  }

  public LirBuilder<V, EV> addConstFloat(int value) {
    if (value == FLOAT_0) {
      return addNoOperandInstruction(LirOpcodes.FCONST_0);
    }
    if (value == FLOAT_1) {
      return addNoOperandInstruction(LirOpcodes.FCONST_1);
    }
    if (value == FLOAT_2) {
      return addNoOperandInstruction(LirOpcodes.FCONST_2);
    }
    advanceInstructionState();
    writer.writeInstruction(LirOpcodes.FCONST, ByteUtils.intEncodingSize(value));
    ByteUtils.writeEncodedInt(value, writer::writeOperand);
    return this;
  }

  public LirBuilder<V, EV> addConstLong(long value) {
    if (value == 0) {
      return addNoOperandInstruction(LirOpcodes.LCONST_0);
    }
    if (value == 1) {
      return addNoOperandInstruction(LirOpcodes.LCONST_1);
    }
    advanceInstructionState();
    writer.writeInstruction(LirOpcodes.LCONST, ByteUtils.longEncodingSize(value));
    ByteUtils.writeEncodedLong(value, writer::writeOperand);
    return this;
  }

  public LirBuilder<V, EV> addConstDouble(long value) {
    if (value == DOUBLE_0) {
      return addNoOperandInstruction(LirOpcodes.DCONST_0);
    }
    if (value == DOUBLE_1) {
      return addNoOperandInstruction(LirOpcodes.DCONST_1);
    }
    advanceInstructionState();
    writer.writeInstruction(LirOpcodes.DCONST, ByteUtils.longEncodingSize(value));
    ByteUtils.writeEncodedLong(value, writer::writeOperand);
    return this;
  }

  public LirBuilder<V, EV> addConstNumber(ValueType type, long value) {
    switch (type) {
      case OBJECT:
        return addConstNull();
      case INT:
        return addConstInt((int) value);
      case FLOAT:
        return addConstFloat((int) value);
      case LONG:
        return addConstLong(value);
      case DOUBLE:
        return addConstDouble(value);
      default:
        throw new Unreachable();
    }
  }

  public LirBuilder<V, EV> addResourceConstNumber(int value) {
    advanceInstructionState();
    writer.writeInstruction(LirOpcodes.RESOURCENUMBER, ByteUtils.intEncodingSize(value));
    ByteUtils.writeEncodedInt(value, writer::writeOperand);
    return this;
  }

  public LirBuilder<V, EV> addConstString(DexString string) {
    return addOneItemInstruction(LirOpcodes.LDC, string);
  }

  public LirBuilder<V, EV> addConstClass(DexType type, boolean ignoreCompatRules) {
    int opcode = ignoreCompatRules ? LirOpcodes.CONSTCLASS_IGNORE_COMPAT : LirOpcodes.LDC;
    return addOneItemInstruction(opcode, type);
  }

  public LirBuilder<V, EV> addConstMethodHandle(DexMethodHandle methodHandle) {
    return addOneItemInstruction(LirOpcodes.LDC, methodHandle);
  }

  public LirBuilder<V, EV> addConstMethodType(DexProto methodType) {
    return addOneItemInstruction(LirOpcodes.LDC, methodType);
  }

  public LirBuilder<V, EV> addNeg(NumericType type, V value) {
    int opcode;
    switch (type) {
      case BYTE:
      case CHAR:
      case SHORT:
      case INT:
        opcode = LirOpcodes.INEG;
        break;
      case LONG:
        opcode = LirOpcodes.LNEG;
        break;
      case FLOAT:
        opcode = LirOpcodes.FNEG;
        break;
      case DOUBLE:
        opcode = LirOpcodes.DNEG;
        break;
      default:
        throw new Unreachable("Unexpected type: " + type);
    }
    return addOneValueInstruction(opcode, value);
  }

  public LirBuilder<V, EV> addNot(NumericType type, V value) {
    int opcode;
    switch (type) {
      case BYTE:
      case CHAR:
      case SHORT:
      case INT:
        opcode = LirOpcodes.INOT;
        break;
      case LONG:
        opcode = LirOpcodes.LNOT;
        break;
      default:
        throw new Unreachable("Unexpected type: " + type);
    }
    return addOneValueInstruction(opcode, value);
  }

  public LirBuilder<V, EV> addDiv(NumericType type, V leftValue, V rightValue) {
    int opcode;
    switch (type) {
      case BYTE:
      case CHAR:
      case SHORT:
      case INT:
        {
          opcode = LirOpcodes.IDIV;
          break;
        }
      case LONG:
        {
          opcode = LirOpcodes.LDIV;
          break;
        }
      case FLOAT:
        {
          opcode = LirOpcodes.FDIV;
          break;
        }
      case DOUBLE:
        {
          opcode = LirOpcodes.DDIV;
          break;
        }
      default:
        throw new Unreachable("Unexpected type: " + type);
    }
    return addInstructionTemplate(
        opcode, Collections.emptyList(), ImmutableList.of(leftValue, rightValue));
  }

  public LirBuilder<V, EV> addArrayLength(V array) {
    return addOneValueInstruction(LirOpcodes.ARRAYLENGTH, array);
  }

  public LirBuilder<V, EV> addCheckCast(DexType type, V value, boolean ignoreCompatRules) {
    int opcode = ignoreCompatRules ? LirOpcodes.CHECKCAST_IGNORE_COMPAT : LirOpcodes.CHECKCAST;
    return addInstructionTemplate(
        opcode, Collections.singletonList(type), Collections.singletonList(value));
  }

  public LirBuilder<V, EV> addSafeCheckCast(DexType type, V value) {
    return addInstructionTemplate(
        LirOpcodes.CHECKCAST_SAFE,
        Collections.singletonList(type),
        Collections.singletonList(value));
  }

  public LirBuilder<V, EV> addInstanceOf(DexType type, V value) {
    return addInstructionTemplate(
        LirOpcodes.INSTANCEOF, Collections.singletonList(type), Collections.singletonList(value));
  }

  public LirBuilder<V, EV> addStaticGet(DexField field) {
    return addOneItemInstruction(LirOpcodes.GETSTATIC, field);
  }

  public LirBuilder<V, EV> addStaticPut(DexField field, V value) {
    return addInstructionTemplate(
        LirOpcodes.PUTSTATIC, Collections.singletonList(field), ImmutableList.of(value));
  }

  public LirBuilder<V, EV> addInstanceGet(DexField field, V object) {
    return addInstructionTemplate(
        LirOpcodes.GETFIELD, Collections.singletonList(field), Collections.singletonList(object));
  }

  public LirBuilder<V, EV> addInstancePut(DexField field, V object, V value) {
    return addInstructionTemplate(
        LirOpcodes.PUTFIELD, Collections.singletonList(field), ImmutableList.of(object, value));
  }

  public LirBuilder<V, EV> addInvokeInstruction(int opcode, DexMethod method, List<V> arguments) {
    return addInstructionTemplate(opcode, Collections.singletonList(method), arguments);
  }

  public LirBuilder<V, EV> addInvokeInstruction(
      int opcode, DexCallSite callSite, List<V> arguments) {
    return addInstructionTemplate(opcode, Collections.singletonList(callSite), arguments);
  }

  public LirBuilder<V, EV> addInvokeDirect(
      DexMethod method, List<V> arguments, boolean isInterface) {
    int opcode = isInterface ? LirOpcodes.INVOKEDIRECT_ITF : LirOpcodes.INVOKEDIRECT;
    return addInvokeInstruction(opcode, method, arguments);
  }

  public LirBuilder<V, EV> addInvokeSuper(
      DexMethod method, List<V> arguments, boolean isInterface) {
    int opcode = isInterface ? LirOpcodes.INVOKESUPER_ITF : LirOpcodes.INVOKESUPER;
    return addInvokeInstruction(opcode, method, arguments);
  }

  public LirBuilder<V, EV> addInvokeVirtual(DexMethod method, List<V> arguments) {
    return addInvokeInstruction(LirOpcodes.INVOKEVIRTUAL, method, arguments);
  }

  public LirBuilder<V, EV> addInvokeStatic(
      DexMethod method, List<V> arguments, boolean isInterface) {
    int opcode = isInterface ? LirOpcodes.INVOKESTATIC_ITF : LirOpcodes.INVOKESTATIC;
    return addInvokeInstruction(opcode, method, arguments);
  }

  public LirBuilder<V, EV> addInvokeInterface(DexMethod method, List<V> arguments) {
    return addInvokeInstruction(LirOpcodes.INVOKEINTERFACE, method, arguments);
  }

  public LirBuilder<V, EV> addInvokeCustom(DexCallSite callSite, List<V> arguments) {
    return addInvokeInstruction(LirOpcodes.INVOKEDYNAMIC, callSite, arguments);
  }

  public LirBuilder<V, EV> addInvokePolymorphic(
      DexMethod invokedMethod, DexProto proto, List<V> arguments) {
    return addInstructionTemplate(
        LirOpcodes.INVOKEPOLYMORPHIC, ImmutableList.of(invokedMethod, proto), arguments);
  }

  public LirBuilder<V, EV> addNewInstance(DexType clazz) {
    return addOneItemInstruction(LirOpcodes.NEW, clazz);
  }

  public LirBuilder<V, EV> addThrow(V exception) {
    return addOneValueInstruction(LirOpcodes.ATHROW, exception);
  }

  public LirBuilder<V, EV> addReturn(V value) {
    return addOneValueInstruction(LirOpcodes.ARETURN, value);
  }

  public LirBuilder<V, EV> addReturnVoid() {
    return addNoOperandInstruction(LirOpcodes.RETURN);
  }

  @SuppressWarnings("ReferenceEquality")
  public LirBuilder<V, EV> addDebugPosition(Position position) {
    assert currentPosition == position;
    return addNoOperandInstruction(LirOpcodes.DEBUGPOS);
  }

  public void addFallthrough() {
    addNoOperandInstruction(LirOpcodes.FALLTHROUGH);
  }

  public LirBuilder<V, EV> addGoto(BasicBlock target) {
    int targetIndex = getBlockIndex(target);
    int operandSize = blockIndexSize(targetIndex);
    advanceInstructionState();
    writer.writeInstruction(LirOpcodes.GOTO, operandSize);
    writeBlockIndex(targetIndex);
    return this;
  }

  public LirBuilder<V, EV> addIntSwitch(
      V value,
      int[] keys,
      Int2ReferenceSortedMap<BasicBlock> keyToTargetMap,
      BasicBlock fallthroughBlock) {
    int[] targets = new int[keys.length];
    for (int i = 0; i < keys.length; i++) {
      targets[i] = getBlockIndex(keyToTargetMap.get(keys[i]));
    }
    return addIntSwitch(value, keys, targets);
  }

  public LirBuilder<V, EV> addIntSwitch(V value, int[] keys, int[] targets) {
    IntSwitchPayload payload = new IntSwitchPayload(keys, targets);
    return addInstructionTemplate(
        LirOpcodes.TABLESWITCH,
        Collections.singletonList(payload),
        Collections.singletonList(value));
  }

  public LirBuilder<V, EV> addStringSwitch(
      V value, DexString[] keys, BasicBlock[] targetsBlocks, BasicBlock fallthroughBlock) {
    int size = keys.length;
    assert targetsBlocks.length == size;
    int[] keyIndices = new int[size];
    int[] targetsIndices = new int[size];
    for (int i = 0; i < size; i++) {
      keyIndices[i] = getConstantIndex(keys[i]);
      targetsIndices[i] = getBlockIndex(targetsBlocks[i]);
    }
    StringSwitchPayload payload = new StringSwitchPayload(keyIndices, targetsIndices);
    return addInstructionTemplate(
        LirOpcodes.STRINGSWITCH,
        Collections.singletonList(payload),
        Collections.singletonList(value));
  }

  public LirBuilder<V, EV> addIf(
      IfType ifKind, ValueType valueType, V value, BasicBlock trueTarget) {
    int opcode;
    switch (ifKind) {
      case EQ:
        opcode = valueType.isObject() ? LirOpcodes.IFNULL : LirOpcodes.IFEQ;
        break;
      case GE:
        opcode = LirOpcodes.IFGE;
        break;
      case GT:
        opcode = LirOpcodes.IFGT;
        break;
      case LE:
        opcode = LirOpcodes.IFLE;
        break;
      case LT:
        opcode = LirOpcodes.IFLT;
        break;
      case NE:
        opcode = valueType.isObject() ? LirOpcodes.IFNONNULL : LirOpcodes.IFNE;
        break;
      default:
        throw new Unreachable("Unexpected if kind: " + ifKind);
    }
    int instructionIndex = advanceInstructionState();
    int targetIndex = getBlockIndex(trueTarget);
    int valueIndex = getEncodedValueIndex(getEncodedValue(value), instructionIndex);
    int operandSize = blockIndexSize(targetIndex) + encodedValueIndexSize(valueIndex);
    writer.writeInstruction(opcode, operandSize);
    writeBlockIndex(targetIndex);
    writeEncodedValueIndex(valueIndex);
    return this;
  }

  public LirBuilder<V, EV> addIfCmp(
      IfType ifKind, ValueType valueType, List<V> inValues, BasicBlock trueTarget) {
    int opcode;
    switch (ifKind) {
      case EQ:
        opcode = valueType.isObject() ? LirOpcodes.IF_ACMPEQ : LirOpcodes.IF_ICMPEQ;
        break;
      case GE:
        opcode = LirOpcodes.IF_ICMPGE;
        break;
      case GT:
        opcode = LirOpcodes.IF_ICMPGT;
        break;
      case LE:
        opcode = LirOpcodes.IF_ICMPLE;
        break;
      case LT:
        opcode = LirOpcodes.IF_ICMPLT;
        break;
      case NE:
        opcode = valueType.isObject() ? LirOpcodes.IF_ACMPNE : LirOpcodes.IF_ICMPNE;
        break;
      default:
        throw new Unreachable("Unexpected if kind " + ifKind);
    }
    int instructionIndex = advanceInstructionState();
    int targetIndex = getBlockIndex(trueTarget);
    int valueOneIndex = getEncodedValueIndex(getEncodedValue(inValues.get(0)), instructionIndex);
    int valueTwoIndex = getEncodedValueIndex(getEncodedValue(inValues.get(1)), instructionIndex);
    int operandSize =
        blockIndexSize(targetIndex)
            + encodedValueIndexSize(valueOneIndex)
            + encodedValueIndexSize(valueTwoIndex);
    writer.writeInstruction(opcode, operandSize);
    writeBlockIndex(targetIndex);
    writeEncodedValueIndex(valueOneIndex);
    writeEncodedValueIndex(valueTwoIndex);
    return this;
  }

  public LirBuilder<V, EV> addMoveException(DexType exceptionType) {
    return addOneItemInstruction(LirOpcodes.MOVEEXCEPTION, exceptionType);
  }

  public LirBuilder<V, EV> addPhi(List<V> operands) {
    return addInstructionTemplate(LirOpcodes.PHI, Collections.emptyList(), operands);
  }

  public LirBuilder<V, EV> addDebugLocalWrite(V src) {
    return addOneValueInstruction(LirOpcodes.DEBUGLOCALWRITE, src);
  }

  public LirBuilder<V, EV> addDebugLocalRead() {
    return addNoOperandInstruction(LirOpcodes.DEBUGLOCALREAD);
  }

  public LirCode<EV> build() {
    int constantsCount = constants.size();
    LirConstant[] constantTable = new LirConstant[constantsCount];
    constants.forEach((item, index) -> constantTable[index] = item);
    DebugLocalInfoTable<EV> debugTable =
        debugLocals.isEmpty() ? null : new DebugLocalInfoTable<>(debugLocals, debugLocalEnds);
    TryCatchTable tryCatchTable =
        tryCatchRanges.isEmpty() ? null : new TryCatchTable(tryCatchRanges);
    return new LirCode<>(
        constantTable,
        positionTable.toArray(new PositionEntry[positionTable.size()]),
        argumentCount,
        byteWriter.toByteArray(),
        instructionCount,
        tryCatchTable,
        debugTable,
        strategy.getStrategyInfo(),
        useDexEstimationStrategy,
        metadataMap);
  }

  private int getCmpOpcode(NumericType type, Cmp.Bias bias) {
    switch (type) {
      case LONG:
        return LirOpcodes.LCMP;
      case FLOAT:
        return bias == Cmp.Bias.LT ? LirOpcodes.FCMPL : LirOpcodes.FCMPG;
      case DOUBLE:
        return bias == Cmp.Bias.LT ? LirOpcodes.DCMPL : LirOpcodes.DCMPG;
      default:
        throw new Unreachable("Cmp has unknown type " + type);
    }
  }

  public LirBuilder<V, EV> addCmp(NumericType type, Bias bias, V leftValue, V rightValue) {
    return addTwoValueInstruction(getCmpOpcode(type, bias), leftValue, rightValue);
  }

  public LirBuilder<V, EV> addArithmeticBinop(
      CfArithmeticBinop.Opcode binop, NumericType type, V leftValue, V rightValue) {
    // The LIR and CF opcodes are the same values, check that the two endpoints match.
    assert LirOpcodes.IADD == CfArithmeticBinop.getAsmOpcode(Opcode.Add, NumericType.INT);
    assert LirOpcodes.DREM == CfArithmeticBinop.getAsmOpcode(Opcode.Rem, NumericType.DOUBLE);
    int opcode = CfArithmeticBinop.getAsmOpcode(binop, type);
    return addTwoValueInstruction(opcode, leftValue, rightValue);
  }

  public LirBuilder<V, EV> addLogicalBinop(
      CfLogicalBinop.Opcode binop, NumericType type, V leftValue, V rightValue) {
    // The LIR and CF opcodes are the same values, check that the two endpoints match.
    assert LirOpcodes.ISHL
        == CfLogicalBinop.getAsmOpcode(CfLogicalBinop.Opcode.Shl, NumericType.INT);
    assert LirOpcodes.LXOR
        == CfLogicalBinop.getAsmOpcode(CfLogicalBinop.Opcode.Xor, NumericType.LONG);
    int opcode = CfLogicalBinop.getAsmOpcode(binop, type);
    return addTwoValueInstruction(opcode, leftValue, rightValue);
  }

  public LirBuilder<V, EV> addMonitor(MonitorType type, V value) {
    return addOneValueInstruction(
        type == MonitorType.ENTER ? LirOpcodes.MONITORENTER : LirOpcodes.MONITOREXIT, value);
  }

  public LirBuilder<V, EV> addNewArrayEmpty(V size, DexType type) {
    return addInstructionTemplate(
        LirOpcodes.NEWARRAY, Collections.singletonList(type), Collections.singletonList(size));
  }

  public LirBuilder<V, EV> addInvokeMultiNewArray(DexType type, List<V> arguments) {
    return addInstructionTemplate(
        LirOpcodes.MULTIANEWARRAY, Collections.singletonList(type), arguments);
  }

  public LirBuilder<V, EV> addNewArrayFilled(DexType type, List<V> arguments) {
    return addInstructionTemplate(
        LirOpcodes.NEWARRAYFILLED, Collections.singletonList(type), arguments);
  }

  public LirBuilder<V, EV> addNewArrayFilledData(int elementWidth, long size, short[] data, V src) {
    FillArrayPayload payloadConstant = new FillArrayPayload(elementWidth, size, data);
    return addInstructionTemplate(
        LirOpcodes.NEWARRAYFILLEDDATA,
        Collections.singletonList(payloadConstant),
        Collections.singletonList(src));
  }

  public LirBuilder<V, EV> addNumberConversion(NumericType from, NumericType to, V value) {
    int opcode = new CfNumberConversion(from, to).getAsmOpcode();
    assert LirOpcodes.I2L <= opcode;
    assert opcode <= LirOpcodes.I2S;
    return addOneValueInstruction(opcode, value);
  }

  public LirBuilder<V, EV> addArrayGet(MemberType memberType, V array, V index) {
    int opcode;
    switch (memberType) {
      case OBJECT:
        opcode = LirOpcodes.AALOAD;
        break;
      case BOOLEAN_OR_BYTE:
        opcode = LirOpcodes.BALOAD;
        break;
      case CHAR:
        opcode = LirOpcodes.CALOAD;
        break;
      case SHORT:
        opcode = LirOpcodes.SALOAD;
        break;
      case INT:
        opcode = LirOpcodes.IALOAD;
        break;
      case FLOAT:
        opcode = LirOpcodes.FALOAD;
        break;
      case LONG:
        opcode = LirOpcodes.LALOAD;
        break;
      case DOUBLE:
        opcode = LirOpcodes.DALOAD;
        break;
      default:
        throw new Unreachable("Unexpected object or imprecise member type: " + memberType);
    }
    return addInstructionTemplate(opcode, Collections.emptyList(), ImmutableList.of(array, index));
  }

  public LirBuilder<V, EV> addArrayPut(MemberType memberType, V array, V index, V value) {
    int opcode;
    switch (memberType) {
      case BOOLEAN_OR_BYTE:
        opcode = LirOpcodes.BASTORE;
        break;
      case CHAR:
        opcode = LirOpcodes.CASTORE;
        break;
      case SHORT:
        opcode = LirOpcodes.SASTORE;
        break;
      case INT:
        opcode = LirOpcodes.IASTORE;
        break;
      case FLOAT:
        opcode = LirOpcodes.FASTORE;
        break;
      case LONG:
        opcode = LirOpcodes.LASTORE;
        break;
      case DOUBLE:
        opcode = LirOpcodes.DASTORE;
        break;
      case OBJECT:
        opcode = LirOpcodes.AASTORE;
        break;
      default:
        throw new Unreachable("Unexpected imprecise member type: " + memberType);
    }
    return addInstructionTemplate(
        opcode, Collections.emptyList(), ImmutableList.of(array, index, value));
  }

  public LirBuilder<V, EV> addDexItemBasedConstString(
      DexReference item, NameComputationInfo<?> nameComputationInfo) {
    NameComputationPayload payload = new NameComputationPayload(nameComputationInfo);
    return addInstructionTemplate(
        LirOpcodes.ITEMBASEDCONSTSTRING, ImmutableList.of(item, payload), Collections.emptyList());
  }

  public LirBuilder<V, EV> addNewUnboxedEnumInstance(DexType clazz, int ordinal) {
    advanceInstructionState();
    int operandSize = constantIndexSize(clazz) + ByteUtils.intEncodingSize(ordinal);
    writer.writeInstruction(LirOpcodes.NEWUNBOXEDENUMINSTANCE, operandSize);
    writeConstantIndex(clazz);
    ByteUtils.writeEncodedInt(ordinal, writer::writeOperand);
    return this;
  }

  public LirBuilder<V, EV> addInitClass(DexType clazz) {
    return addOneItemInstruction(LirOpcodes.INITCLASS, clazz);
  }

  public LirBuilder<V, EV> addRecordFieldValues(DexField[] fields, List<V> values) {
    RecordFieldValuesPayload payload = new RecordFieldValuesPayload(fields);
    return addInstructionTemplate(
        LirOpcodes.RECORDFIELDVALUES, Collections.singletonList(payload), values);
  }
}
