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

import static com.android.tools.r8.ir.analysis.type.Nullability.definitelyNotNull;

import com.android.tools.r8.dex.DexOutputBuffer;
import com.android.tools.r8.dex.FileWriter;
import com.android.tools.r8.dex.IndexedItemCollection;
import com.android.tools.r8.dex.MixedSectionCollection;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.ir.analysis.type.TypeElement;
import com.android.tools.r8.ir.analysis.value.AbstractValue;
import com.android.tools.r8.ir.analysis.value.AbstractValueFactory;
import com.android.tools.r8.ir.analysis.value.UnknownValue;
import com.android.tools.r8.ir.code.BasicBlock.ThrowingInfo;
import com.android.tools.r8.ir.code.ConstInstruction;
import com.android.tools.r8.ir.code.ConstString;
import com.android.tools.r8.ir.code.DexItemBasedConstString;
import com.android.tools.r8.ir.code.IRCode;
import com.android.tools.r8.ir.code.Value;
import com.android.tools.r8.naming.dexitembasedstring.NameComputationInfo;
import com.android.tools.r8.utils.BooleanUtils;
import com.android.tools.r8.utils.EncodedValueUtils;
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 java.util.Arrays;
import java.util.function.Consumer;
import org.objectweb.asm.Handle;
import org.objectweb.asm.Type;

public abstract class DexValue extends DexItem implements StructuralItem<DexValue> {

  public enum DexValueKind {
    BYTE(0x00),
    SHORT(0x02),
    CHAR(0x03),
    INT(0x04),
    LONG(0x06),
    FLOAT(0x10),
    DOUBLE(0x11),
    METHOD_TYPE(0x15),
    METHOD_HANDLE(0x16),
    STRING(0x17),
    TYPE(0x18),
    FIELD(0x19),
    METHOD(0x1a),
    ENUM(0x1b),
    ARRAY(0x1c),
    ANNOTATION(0x1d),
    NULL(0x1e),
    BOOLEAN(0x1f);

    public static DexValueKind fromId(int id) {
      switch (id) {
        case 0x00:
          return BYTE;
        case 0x02:
          return SHORT;
        case 0x03:
          return CHAR;
        case 0x04:
          return INT;
        case 0x06:
          return LONG;
        case 0x10:
          return FLOAT;
        case 0x11:
          return DOUBLE;
        case 0x15:
          return METHOD_TYPE;
        case 0x16:
          return METHOD_HANDLE;
        case 0x17:
          return STRING;
        case 0x18:
          return TYPE;
        case 0x19:
          return FIELD;
        case 0x1a:
          return METHOD;
        case 0x1b:
          return ENUM;
        case 0x1c:
          return ARRAY;
        case 0x1d:
          return ANNOTATION;
        case 0x1e:
          return NULL;
        case 0x1f:
          return BOOLEAN;
        default:
          throw new Unreachable();
      }
    }

    private final byte b;

    DexValueKind(int b) {
      this.b = (byte) b;
    }

    byte toByte() {
      return b;
    }
  }

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

  @Override
  public final StructuralMapping<DexValue> getStructuralMapping() {
    // DexValue is not generic at its base type (and can't as we use it as a polymorphic value),
    // so each concrete value must implement polymorphic accept functions. This base class
    // implements (most of) the polymorphic checks and concrete types implement the internal
    // variants for that type.
    throw new Unreachable();
  }

  @Override
  public final int acceptCompareTo(DexValue other, CompareToVisitor visitor) {
    // Order first on 'kind', only equal kinds then forward to the 'kind' specific internal compare.
    if (getValueKind() != other.getValueKind()) {
      return visitor.visitInt(getValueKind().toByte(), other.getValueKind().toByte());
    } else {
      return internalAcceptCompareTo(other, visitor);
    }
  }

  @Override
  public final void acceptHashing(HashingVisitor visitor) {
    // Always hash the 'kind' which ensures that raw values of different type are distinct.
    visitor.visitInt(getValueKind().toByte());
    internalAcceptHashing(visitor);
  }

  abstract int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor);

  abstract void internalAcceptHashing(HashingVisitor visitor);

  public static final DexValue[] EMPTY_ARRAY = {};

  public abstract DexValueKind getValueKind();

  public boolean isDexItemBasedValueString() {
    return false;
  }

  public DexItemBasedValueString asDexItemBasedValueString() {
    return null;
  }

  public boolean isDexValueMethodHandle() {
    return false;
  }

  public DexValueMethodHandle asDexValueMethodHandle() {
    return null;
  }

  public boolean isDexValueMethodType() {
    return false;
  }

  public DexValueMethodType asDexValueMethodType() {
    return null;
  }

  public boolean isDexValueAnnotation() {
    return false;
  }

  public DexValueAnnotation asDexValueAnnotation() {
    return null;
  }

  public boolean isDexValueArray() {
    return false;
  }

  public DexValueArray asDexValueArray() {
    return null;
  }

  public boolean isDexValueBoolean() {
    return false;
  }

  public DexValueBoolean asDexValueBoolean() {
    return null;
  }

  public boolean isDexValueByte() {
    return false;
  }

  public DexValueByte asDexValueByte() {
    return null;
  }

  public boolean isDexValueDouble() {
    return false;
  }

  public DexValueDouble asDexValueDouble() {
    return null;
  }

  public boolean isDexValueChar() {
    return false;
  }

  public DexValueChar asDexValueChar() {
    return null;
  }

  public boolean isDexValueEnum() {
    return false;
  }

  public DexValueEnum asDexValueEnum() {
    return null;
  }

  public boolean isDexValueField() {
    return false;
  }

  public DexValueField asDexValueField() {
    return null;
  }

  public boolean isDexValueFloat() {
    return false;
  }

  public DexValueFloat asDexValueFloat() {
    return null;
  }

  public boolean isDexValueInt() {
    return false;
  }

  public DexValueInt asDexValueInt() {
    return null;
  }

  public boolean isDexValueLong() {
    return false;
  }

  public DexValueLong asDexValueLong() {
    return null;
  }

  public boolean isDexValueMethod() {
    return false;
  }

  public DexValueMethod asDexValueMethod() {
    return null;
  }

  public boolean isDexValueNull() {
    return false;
  }

  public DexValueNull asDexValueNull() {
    return null;
  }

  public boolean isDexValueNumber() {
    return false;
  }

  public DexValueNumber asDexValueNumber() {
    return null;
  }

  public boolean isDexValueShort() {
    return false;
  }

  public DexValueShort asDexValueShort() {
    return null;
  }

  public boolean isDexValueString() {
    return false;
  }

  public DexValueString asDexValueString() {
    return null;
  }

  public boolean isDexValueType() {
    return false;
  }

  public DexValueType asDexValueType() {
    return null;
  }

  public abstract AbstractValue toAbstractValue(AbstractValueFactory factory);

  static DexValue fromAsmBootstrapArgument(
      Object value, JarApplicationReader application, DexType clazz) {
    if (value instanceof Integer) {
      return DexValue.DexValueInt.create((Integer) value);
    } else if (value instanceof Long) {
      return DexValue.DexValueLong.create((Long) value);
    } else if (value instanceof Float) {
      return DexValue.DexValueFloat.create((Float) value);
    } else if (value instanceof Double) {
      return DexValue.DexValueDouble.create((Double) value);
    } else if (value instanceof String) {
      return new DexValue.DexValueString(application.getString((String) value));

    } else if (value instanceof Type) {
      Type type = (Type) value;
      switch (type.getSort()) {
        case Type.OBJECT:
          return new DexValue.DexValueType(
              application.getTypeFromDescriptor(((Type) value).getDescriptor()));
        case Type.METHOD:
          return new DexValue.DexValueMethodType(
              application.getProto(((Type) value).getDescriptor()));
        default:
          throw new Unreachable("Type sort is not supported: " + type.getSort());
      }
    } else if (value instanceof Handle) {
      return new DexValue.DexValueMethodHandle(
          DexMethodHandle.fromAsmHandle((Handle) value, application, clazz));
    } else {
      throw new Unreachable(
          "Unsupported bootstrap static argument of type " + value.getClass().getSimpleName());
    }
  }

  private static void writeHeader(DexValueKind kind, int arg, DexOutputBuffer dest) {
    dest.putByte((byte) ((arg << 5) | kind.toByte()));
  }

  public void collectIndexedItems(IndexedItemCollection indexedItems) {
    // Intentionally left empty
  }

  @Override
  void collectMixedSectionItems(MixedSectionCollection mixedItems) {
    // Should never be visited.
    throw new Unreachable();
  }

  public abstract void sort();

  public abstract void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping);

  @Override
  public abstract int hashCode();

  @Override
  public abstract boolean equals(Object other);

  @Override
  public abstract String toString();

  public static DexValue defaultForType(DexType type) {
    switch (type.toShorty()) {
      case 'Z':
        return DexValueBoolean.DEFAULT;
      case 'B':
        return DexValueByte.DEFAULT;
      case 'C':
        return DexValueChar.DEFAULT;
      case 'S':
        return DexValueShort.DEFAULT;
      case 'I':
        return DexValueInt.DEFAULT;
      case 'J':
        return DexValueLong.DEFAULT;
      case 'F':
        return DexValueFloat.DEFAULT;
      case 'D':
        return DexValueDouble.DEFAULT;
      case 'L':
        return DexValueNull.NULL;
      default:
        throw new Unreachable("No default value for unexpected type " + type);
    }
  }

  public abstract DexType getType(DexItemFactory factory);

  public abstract Object getBoxedValue();

  /** Returns an instruction that can be used to materialize this {@link DexValue} (or null). */
  public ConstInstruction asConstInstruction(
      AppView<? extends AppInfoWithClassHierarchy> appView, IRCode code, DebugLocalInfo local) {
    return null;
  }

  public boolean isDefault(DexType type) {
    return this == defaultForType(type);
  }

  /**
   * Whether creating this value as a default value for a field might trigger an allocation.
   *
   * <p>This is conservative. It also considers allocations due to class loading when referencing a
   * field or method.
   */
  public boolean mayHaveSideEffects() {
    return true;
  }

  public abstract Object asAsmEncodedObject();

  private abstract static class SimpleDexValue extends DexValue {

    @Override
    public void sort() {
      // Intentionally empty
    }

    @Override
    public boolean mayHaveSideEffects() {
      return false;
    }

    static void writeIntegerTo(DexValueKind kind, long value, int expected, DexOutputBuffer dest) {
      // Leave space for header.
      dest.forward(1);
      int length = dest.putSignedEncodedValue(value, expected);
      dest.rewind(length + 1);
      writeHeader(kind, length - 1, dest);
      dest.forward(length);
    }
  }

  public abstract static class DexValueNumber extends SimpleDexValue {

    public abstract long getRawValue();

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

    @Override
    public DexValueNumber asDexValueNumber() {
      return this;
    }

    @Override
    public AbstractValue toAbstractValue(AbstractValueFactory factory) {
      return factory.createSingleNumberValue(getRawValue());
    }
  }

  public static class DexValueByte extends DexValueNumber {

    public static final DexValueByte DEFAULT = new DexValueByte((byte) 0);

    final byte value;

    private DexValueByte(byte value) {
      this.value = value;
    }

    public static DexValueByte create(byte value) {
      return value == DEFAULT.value ? DEFAULT : new DexValueByte(value);
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      return visitor.visitInt(value, other.asDexValueByte().value);
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      visitor.visitInt(value);
    }

    public byte getValue() {
      return value;
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.BYTE;
    }

    @Override
    public DexType getType(DexItemFactory factory) {
      return factory.byteType;
    }

    @Override
    public long getRawValue() {
      return value;
    }

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

    @Override
    public DexValueByte asDexValueByte() {
      return this;
    }

    @Override
    public Object getBoxedValue() {
      return getValue();
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      writeHeader(DexValueKind.BYTE, 0, dest);
      dest.putSignedEncodedValue(value, 1);
    }

    @Override
    public Object asAsmEncodedObject() {
      return Integer.valueOf(value);
    }

    @Override
    public int hashCode() {
      return value * 3;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return other instanceof DexValueByte && value == ((DexValueByte) other).value;
    }

    @Override
    public String toString() {
      return "Byte " + value;
    }

    @Override
    public ConstInstruction asConstInstruction(
        AppView<? extends AppInfoWithClassHierarchy> appView, IRCode code, DebugLocalInfo local) {
      return code.createIntConstant(value, local);
    }
  }

  public static class DexValueShort extends DexValueNumber {

    public static final DexValueShort DEFAULT = new DexValueShort((short) 0);
    final short value;

    private DexValueShort(short value) {
      this.value = value;
    }

    public static DexValueShort create(short value) {
      return value == DEFAULT.value ? DEFAULT : new DexValueShort(value);
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      visitor.visitInt(value);
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      return visitor.visitInt(value, other.asDexValueShort().getValue());
    }

    public short getValue() {
      return value;
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.SHORT;
    }

    @Override
    public DexType getType(DexItemFactory factory) {
      return factory.shortType;
    }

    @Override
    public long getRawValue() {
      return value;
    }

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

    @Override
    public DexValueShort asDexValueShort() {
      return this;
    }

    @Override
    public Object getBoxedValue() {
      return getValue();
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      writeIntegerTo(DexValueKind.SHORT, value, Short.BYTES, dest);
    }

    @Override
    public Object asAsmEncodedObject() {
      return Integer.valueOf(value);
    }

    @Override
    public int hashCode() {
      return value * 7;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return other instanceof DexValueShort && value == ((DexValueShort) other).value;
    }

    @Override
    public String toString() {
      return "Short " + value;
    }

    @Override
    public ConstInstruction asConstInstruction(
        AppView<? extends AppInfoWithClassHierarchy> appView, IRCode code, DebugLocalInfo local) {
      return code.createIntConstant(value, local);
    }
  }

  public static class DexValueChar extends DexValueNumber {

    public static final DexValueChar DEFAULT = new DexValueChar((char) 0);
    final char value;

    private DexValueChar(char value) {
      this.value = value;
    }

    public static DexValueChar create(char value) {
      return value == DEFAULT.value ? DEFAULT : new DexValueChar(value);
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      return visitor.visitInt(value, other.asDexValueChar().value);
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      visitor.visitInt(value);
    }

    public char getValue() {
      return value;
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.CHAR;
    }

    @Override
    public DexType getType(DexItemFactory factory) {
      return factory.charType;
    }

    @Override
    public long getRawValue() {
      return value;
    }

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

    @Override
    public DexValueChar asDexValueChar() {
      return this;
    }

    @Override
    public Object getBoxedValue() {
      return getValue();
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      dest.forward(1);
      int length = dest.putUnsignedEncodedValue(value, 2);
      dest.rewind(length + 1);
      writeHeader(DexValueKind.CHAR, length - 1, dest);
      dest.forward(length);
    }

    @Override
    public Object asAsmEncodedObject() {
      return Integer.valueOf(value);
    }

    @Override
    public int hashCode() {
      return value * 5;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return other instanceof DexValueChar && value == ((DexValueChar) other).value;
    }

    @Override
    public String toString() {
      return "Char " + value;
    }

    @Override
    public ConstInstruction asConstInstruction(
        AppView<? extends AppInfoWithClassHierarchy> appView, IRCode code, DebugLocalInfo local) {
      return code.createIntConstant(value, local);
    }
  }

  public static class DexValueInt extends DexValueNumber {

    public static final DexValueInt DEFAULT = new DexValueInt(0);
    public final int value;

    private DexValueInt(int value) {
      this.value = value;
    }

    public static DexValueInt create(int value) {
      return value == DEFAULT.value ? DEFAULT : new DexValueInt(value);
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      visitor.visitInt(value);
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      return visitor.visitInt(value, other.asDexValueInt().value);
    }

    public int getValue() {
      return value;
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.INT;
    }

    @Override
    public DexType getType(DexItemFactory factory) {
      return factory.intType;
    }

    @Override
    public long getRawValue() {
      return value;
    }

    @Override
    public Object getBoxedValue() {
      return getValue();
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      writeIntegerTo(DexValueKind.INT, value, Integer.BYTES, dest);
    }

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

    @Override
    public DexValueInt asDexValueInt() {
      return this;
    }

    @Override
    public Object asAsmEncodedObject() {
      return Integer.valueOf(value);
    }

    @Override
    public int hashCode() {
      return value * 11;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return other instanceof DexValueInt && value == ((DexValueInt) other).value;
    }

    @Override
    public String toString() {
      return "Int " + value;
    }

    @Override
    public ConstInstruction asConstInstruction(
        AppView<? extends AppInfoWithClassHierarchy> appView, IRCode code, DebugLocalInfo local) {
      return code.createIntConstant(value, local);
    }
  }

  public static class DexValueLong extends DexValueNumber {

    public static final DexValueLong DEFAULT = new DexValueLong(0);
    final long value;

    private DexValueLong(long value) {
      this.value = value;
    }

    public static DexValueLong create(long value) {
      return value == DEFAULT.value ? DEFAULT : new DexValueLong(value);
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      return visitor.visitLong(value, other.asDexValueLong().value);
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      visitor.visitLong(value);
    }

    public long getValue() {
      return value;
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.LONG;
    }

    @Override
    public DexType getType(DexItemFactory factory) {
      return factory.longType;
    }

    @Override
    public long getRawValue() {
      return value;
    }

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

    @Override
    public DexValueLong asDexValueLong() {
      return this;
    }

    @Override
    public Object getBoxedValue() {
      return getValue();
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      writeIntegerTo(DexValueKind.LONG, value, Long.BYTES, dest);
    }

    @Override
    public Object asAsmEncodedObject() {
      return Long.valueOf(value);
    }

    @Override
    public int hashCode() {
      return (int) value * 13;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return other instanceof DexValueLong && value == ((DexValueLong) other).value;
    }

    @Override
    public String toString() {
      return "Long " + value;
    }

    @Override
    public ConstInstruction asConstInstruction(
        AppView<? extends AppInfoWithClassHierarchy> appView, IRCode code, DebugLocalInfo local) {
      return code.createLongConstant(value, local);
    }
  }

  public static class DexValueFloat extends DexValueNumber {

    public static final DexValueFloat DEFAULT = new DexValueFloat(0);
    final float value;

    private DexValueFloat(float value) {
      this.value = value;
    }

    public static DexValueFloat create(float value) {
      return Float.compare(value, DEFAULT.value) == 0 ? DEFAULT : new DexValueFloat(value);
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      visitor.visitFloat(value);
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      return visitor.visitFloat(value, other.asDexValueFloat().value);
    }

    public float getValue() {
      return value;
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.FLOAT;
    }

    @Override
    public DexType getType(DexItemFactory factory) {
      return factory.floatType;
    }

    @Override
    public long getRawValue() {
      return Float.floatToIntBits(value);
    }

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

    @Override
    public DexValueFloat asDexValueFloat() {
      return this;
    }

    @Override
    public Object getBoxedValue() {
      return getValue();
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      dest.forward(1);
      int length = EncodedValueUtils.putFloat(dest, value);
      dest.rewind(length + 1);
      writeHeader(DexValueKind.FLOAT, length - 1, dest);
      dest.forward(length);
    }

    @Override
    public Object asAsmEncodedObject() {
      return Float.valueOf(value);
    }

    @Override
    public ConstInstruction asConstInstruction(
        AppView<? extends AppInfoWithClassHierarchy> appView, IRCode code, DebugLocalInfo local) {
      return code.createFloatConstant(value, local);
    }

    @Override
    public int hashCode() {
      return (int) (value * 19);
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return other instanceof DexValueFloat
          && Float.compare(value, ((DexValueFloat) other).value) == 0;
    }

    @Override
    public String toString() {
      return "Float " + value;
    }
  }

  public static class DexValueDouble extends DexValueNumber {

    public static final DexValueDouble DEFAULT = new DexValueDouble(0);

    final double value;

    private DexValueDouble(double value) {
      this.value = value;
    }

    public static DexValueDouble create(double value) {
      return Double.compare(value, DEFAULT.value) == 0 ? DEFAULT : new DexValueDouble(value);
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      return visitor.visitDouble(value, other.asDexValueDouble().value);
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      visitor.visitDouble(value);
    }

    public double getValue() {
      return value;
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.DOUBLE;
    }

    @Override
    public DexType getType(DexItemFactory factory) {
      return factory.doubleType;
    }

    @Override
    public long getRawValue() {
      return Double.doubleToRawLongBits(value);
    }

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

    @Override
    public DexValueDouble asDexValueDouble() {
      return this;
    }

    @Override
    public Object getBoxedValue() {
      return getValue();
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      dest.forward(1);
      int length = EncodedValueUtils.putDouble(dest, value);
      dest.rewind(length + 1);
      writeHeader(DexValueKind.DOUBLE, length - 1, dest);
      dest.forward(length);
    }

    @Override
    public Object asAsmEncodedObject() {
      return Double.valueOf(value);
    }

    @Override
    public ConstInstruction asConstInstruction(
        AppView<? extends AppInfoWithClassHierarchy> appView, IRCode code, DebugLocalInfo local) {
      return code.createDoubleConstant(value, local);
    }

    @Override
    public int hashCode() {
      return (int) (value * 29);
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return (other instanceof DexValueDouble) &&
          (Double.compare(value, ((DexValueDouble) other).value) == 0);
    }

    @Override
    public String toString() {
      return "Double " + value;
    }
  }

  static private abstract class NestedDexValue<T extends IndexedDexItem> extends DexValue {

    public final T value;

    private NestedDexValue(T value) {
      this.value = value;
    }

    @Override
    public DexType getType(DexItemFactory factory) {
      throw new Unreachable();
    }

    public T getValue() {
      return value;
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      int offset = value.getOffset(mapping);
      dest.forward(1);
      int length = dest.putUnsignedEncodedValue(offset, 4);
      dest.rewind(length + 1);
      writeHeader(getValueKind(), length - 1, dest);
      dest.forward(length);
    }

    @Override
    public Object getBoxedValue() {
      throw new Unreachable("No boxed value for DexValue " + this.getClass().getSimpleName());
    }

    @Override
    public Object asAsmEncodedObject() {
      throw new Unreachable("No ASM conversion for DexValue " + this.getClass().getSimpleName());
    }

    @Override
    public void sort() {
      // Intentionally empty.
    }

    @Override
    public int hashCode() {
      return value.hashCode() * 7 + getValueKind().toByte();
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      if (other instanceof NestedDexValue) {
        NestedDexValue<?> that = (NestedDexValue<?>) other;
        return that.getValueKind() == getValueKind() && that.value.equals(value);
      }
      return false;
    }

    @Override
    public String toString() {
      return "Item " + getValueKind() + " " + value;
    }
  }

  static public class DexValueString extends NestedDexValue<DexString> {

    public DexValueString(DexString value) {
      super(value);
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      value.acceptHashing(visitor);
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      int order = DexItemBasedValueString.compareAndCheckValueStrings(this, other, visitor);
      if (order != 0) {
        return order;
      }
      return value.acceptCompareTo(other.asDexValueString().value, visitor);
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      value.collectIndexedItems(indexedItems);
    }

    @Override
    public DexValueString asDexValueString() {
      return this;
    }

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

    @Override
    public Object asAsmEncodedObject() {
      return value.toString();
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.STRING;
    }

    @Override
    public DexType getType(DexItemFactory factory) {
      return factory.stringType;
    }

    @Override
    public ConstInstruction asConstInstruction(
        AppView<? extends AppInfoWithClassHierarchy> appView, IRCode code, DebugLocalInfo local) {
      TypeElement type = TypeElement.stringClassType(appView, definitelyNotNull());
      Value outValue = code.createValue(type, local);
      ConstString instruction =
          new ConstString(outValue, value, ThrowingInfo.defaultForConstString(appView.options()));
      if (!instruction.instructionInstanceCanThrow()) {
        return instruction;
      }
      return null;
    }

    @Override
    public boolean mayHaveSideEffects() {
      // Assuming that strings do not have side-effects.
      return false;
    }

    @Override
    public AbstractValue toAbstractValue(AbstractValueFactory factory) {
      return factory.createSingleStringValue(value);
    }
  }

  public static class DexItemBasedValueString extends NestedDexValue<DexReference> {

    // Helper to ensure a consistent order on DexValueString and DexItemBasedValueString which are
    // both defined to have kind 'string'.
    static int compareAndCheckValueStrings(DexValue v1, DexValue v2, CompareToVisitor visitor) {
      assert v1.getValueKind() == DexValueKind.STRING;
      assert v2.getValueKind() == DexValueKind.STRING;
      int order1 = v1.isDexItemBasedValueString() ? 1 : 0;
      int order2 = v2.isDexItemBasedValueString() ? 1 : 0;
      return visitor.visitInt(order1, order2);
    }

    private final NameComputationInfo<?> nameComputationInfo;

    public DexItemBasedValueString(DexReference value, NameComputationInfo<?> nameComputationInfo) {
      super(value);
      this.nameComputationInfo = nameComputationInfo;
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      visitor.visitDexReference(value);
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      int order = compareAndCheckValueStrings(this, other, visitor);
      if (order != 0) {
        return order;
      }
      return visitor.visitDexReference(value, other.asDexItemBasedValueString().value);
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      value.collectIndexedItems(indexedItems);
    }

    public NameComputationInfo<?> getNameComputationInfo() {
      return nameComputationInfo;
    }

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

    @Override
    public DexItemBasedValueString asDexItemBasedValueString() {
      return this;
    }

    @Override
    public Object asAsmEncodedObject() {
      return value.toString();
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.STRING;
    }

    @Override
    public DexType getType(DexItemFactory factory) {
      return factory.stringType;
    }

    @Override
    public ConstInstruction asConstInstruction(
        AppView<? extends AppInfoWithClassHierarchy> appView, IRCode code, DebugLocalInfo local) {
      TypeElement type = TypeElement.stringClassType(appView, definitelyNotNull());
      Value outValue = code.createValue(type, local);
      DexItemBasedConstString instruction =
          new DexItemBasedConstString(
              outValue,
              value,
              nameComputationInfo,
              ThrowingInfo.defaultForConstString(appView.options()));
      // DexItemBasedConstString cannot throw.
      assert !instruction.instructionInstanceCanThrow();
      return instruction;
    }

    @Override
    public AbstractValue toAbstractValue(AbstractValueFactory factory) {
      // TODO(b/150835624): Update once there is an abstract value to represent dex item based
      //  strings.
      return UnknownValue.getInstance();
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      throw new Unreachable(
          "DexItemBasedValueString values should always be rewritten into DexValueString");
    }
  }

  static public class DexValueType extends NestedDexValue<DexType> {

    public DexValueType(DexType value) {
      super(value);
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      return value.acceptCompareTo(other.asDexValueType().value, visitor);
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      value.acceptHashing(visitor);
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.TYPE;
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      value.collectIndexedItems(indexedItems);
    }

    @Override
    public DexValueType asDexValueType() {
      return this;
    }

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

    @Override
    public AbstractValue toAbstractValue(AbstractValueFactory factory) {
      return UnknownValue.getInstance();
    }
  }

  static public class DexValueField extends NestedDexValue<DexField> {

    public DexValueField(DexField value) {
      super(value);
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      return value.acceptCompareTo(other.asDexValueField().value, visitor);
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      value.acceptHashing(visitor);
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.FIELD;
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      value.collectIndexedItems(indexedItems);
    }

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

    @Override
    public DexValueField asDexValueField() {
      return this;
    }

    @Override
    public AbstractValue toAbstractValue(AbstractValueFactory factory) {
      return UnknownValue.getInstance();
    }
  }

  static public class DexValueMethod extends NestedDexValue<DexMethod> {

    public DexValueMethod(DexMethod value) {
      super(value);
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      return value.acceptCompareTo(other.asDexValueMethod().value, visitor);
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      value.acceptHashing(visitor);
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.METHOD;
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      value.collectIndexedItems(indexedItems);
    }

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

    @Override
    public DexValueMethod asDexValueMethod() {
      return this;
    }

    @Override
    public AbstractValue toAbstractValue(AbstractValueFactory factory) {
      return UnknownValue.getInstance();
    }
  }

  static public class DexValueEnum extends NestedDexValue<DexField> {

    public DexValueEnum(DexField value) {
      super(value);
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      return value.acceptCompareTo(other.asDexValueEnum().value, visitor);
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      value.acceptHashing(visitor);
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.ENUM;
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      value.collectIndexedItems(indexedItems);
    }

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

    @Override
    public DexValueEnum asDexValueEnum() {
      return this;
    }

    @Override
    public AbstractValue toAbstractValue(AbstractValueFactory factory) {
      return UnknownValue.getInstance();
    }
  }

  static public class DexValueMethodType extends NestedDexValue<DexProto> {

    public DexValueMethodType(DexProto value) {
      super(value);
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      return value.acceptCompareTo(other.asDexValueMethodType().value, visitor);
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      value.acceptHashing(visitor);
    }

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

    @Override
    public DexValueMethodType asDexValueMethodType() {
      return this;
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.METHOD_TYPE;
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      value.collectIndexedItems(indexedItems);
    }

    @Override
    public AbstractValue toAbstractValue(AbstractValueFactory factory) {
      return UnknownValue.getInstance();
    }
  }

  static public class DexValueArray extends DexValue {

    final DexValue[] values;

    public DexValueArray(DexValue[] values) {
      this.values = values;
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      return visitor.visitItemArray(values, other.asDexValueArray().values);
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      visitor.visitItemArray(values);
    }

    public void forEachElement(Consumer<DexValue> consumer) {
      for (DexValue value : values) {
        consumer.accept(value);
      }
    }

    public DexValue[] getValues() {
      return values;
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.ARRAY;
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      for (DexValue value : values) {
        value.collectIndexedItems(indexedItems);
      }
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      writeHeader(DexValueKind.ARRAY, 0, dest);
      dest.putUleb128(values.length);
      for (DexValue value : values) {
        value.writeTo(dest, mapping);
      }
    }

    @Override
    public DexType getType(DexItemFactory factory) {
      throw new Unreachable();
    }

    @Override
    public Object getBoxedValue() {
      throw new Unreachable("No boxed value for DexValueArray");
    }

    @Override
    public AbstractValue toAbstractValue(AbstractValueFactory factory) {
      return UnknownValue.getInstance();
    }

    @Override
    public Object asAsmEncodedObject() {
      throw new Unreachable("No ASM conversion for DexValueArray");
    }

    @Override
    public void sort() {
      for (DexValue value : values) {
        value.sort();
      }
    }

    @Override
    public int hashCode() {
      return Arrays.hashCode(values);
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      if (other instanceof DexValueArray) {
        DexValueArray that = (DexValueArray) other;
        return Arrays.equals(that.values, values);
      }
      return false;
    }

    @Override
    public String toString() {
      return "Array " + Arrays.toString(values);
    }

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

    @Override
    public DexValueArray asDexValueArray() {
      return this;
    }
  }

  static public class DexValueAnnotation extends DexValue {

    public final DexEncodedAnnotation value;

    public DexValueAnnotation(DexEncodedAnnotation value) {
      this.value = value;
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      return value.acceptCompareTo(other.asDexValueAnnotation().value, visitor);
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      value.acceptHashing(visitor);
    }

    public DexEncodedAnnotation getValue() {
      return value;
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.ANNOTATION;
    }

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

    @Override
    public DexValueAnnotation asDexValueAnnotation() {
      return this;
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      value.collectIndexedItems(indexedItems);
    }

    @Override
    public AbstractValue toAbstractValue(AbstractValueFactory factory) {
      return UnknownValue.getInstance();
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      writeHeader(DexValueKind.ANNOTATION, 0, dest);
      FileWriter.writeEncodedAnnotation(value, dest, mapping);
    }

    @Override
    public DexType getType(DexItemFactory factory) {
      throw new Unreachable();
    }

    @Override
    public Object getBoxedValue() {
      throw new Unreachable("No boxed value for DexValueAnnotation");
    }

    @Override
    public Object asAsmEncodedObject() {
      throw new Unreachable("No ASM conversion for DexValueAnnotation");
    }

    @Override
    public void sort() {
      value.sort();
    }

    @Override
    public int hashCode() {
      return value.hashCode() * 7;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      if (other instanceof DexValueAnnotation) {
        DexValueAnnotation that = (DexValueAnnotation) other;
        return that.value.equals(value);
      }
      return false;
    }

    @Override
    public String toString() {
      return "Annotation " + value;
    }
  }

  public static class DexValueNull extends DexValueNumber {

    public static final DexValue NULL = new DexValueNull();

    // See DexValueNull.NULL
    private DexValueNull() {
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      assert this == NULL;
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      assert this == NULL;
      assert other == NULL;
      return 0;
    }

    public Object getValue() {
      return null;
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.NULL;
    }

    @Override
    public DexType getType(DexItemFactory factory) {
      throw new Unreachable();
    }

    @Override
    public long getRawValue() {
      return 0;
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      writeHeader(DexValueKind.NULL, 0, dest);
    }

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

    @Override
    public DexValueNull asDexValueNull() {
      return this;
    }

    @Override
    public Object getBoxedValue() {
      return null;
    }

    @Override
    public Object asAsmEncodedObject() {
      return null;
    }

    @Override
    public int hashCode() {
      return 42;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return other instanceof DexValueNull;
    }

    @Override
    public String toString() {
      return "Null";
    }

    @Override
    public ConstInstruction asConstInstruction(
        AppView<? extends AppInfoWithClassHierarchy> appView, IRCode code, DebugLocalInfo local) {
      return code.createConstNull(local);
    }
  }

  public static class DexValueBoolean extends DexValueNumber {

    private static final DexValueBoolean TRUE = new DexValueBoolean(true);
    private static final DexValueBoolean FALSE = new DexValueBoolean(false);
    // Use a separate instance for the default value to distinguish it from an explicit false value.
    private static final DexValueBoolean DEFAULT = new DexValueBoolean(false);

    final boolean value;

    private DexValueBoolean(boolean value) {
      this.value = value;
    }

    public static DexValueBoolean create(boolean value) {
      return value ? TRUE : FALSE;
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      return visitor.visitBool(value, other.asDexValueBoolean().value);
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      visitor.visitBool(value);
    }

    public boolean getValue() {
      return value;
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.BOOLEAN;
    }

    @Override
    public DexType getType(DexItemFactory factory) {
      return factory.booleanType;
    }

    @Override
    public long getRawValue() {
      return BooleanUtils.longValue(value);
    }

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

    @Override
    public DexValueBoolean asDexValueBoolean() {
      return this;
    }

    @Override
    public Object getBoxedValue() {
      return getValue();
    }

    @Override
    public void writeTo(DexOutputBuffer dest, ObjectToOffsetMapping mapping) {
      writeHeader(DexValueKind.BOOLEAN, value ? 1 : 0, dest);
    }

    @Override
    public Object asAsmEncodedObject() {
      return Integer.valueOf(value ? 1 : 0);
    }

    @Override
    public int hashCode() {
      return value ? 1234 : 4321;
    }

    @Override
    public boolean equals(Object other) {
      if (other == this) {
        return true;
      }
      return other instanceof DexValueBoolean && ((DexValueBoolean) other).value == value;
    }

    @Override
    public String toString() {
      return value ? "True" : "False";
    }

    @Override
    public ConstInstruction asConstInstruction(
        AppView<? extends AppInfoWithClassHierarchy> appView, IRCode code, DebugLocalInfo local) {
      return code.createIntConstant(BooleanUtils.intValue(value), local);
    }
  }

  static public class DexValueMethodHandle extends NestedDexValue<DexMethodHandle> {

    public DexValueMethodHandle(DexMethodHandle value) {
      super(value);
    }

    @Override
    int internalAcceptCompareTo(DexValue other, CompareToVisitor visitor) {
      return value.acceptCompareTo(other.asDexValueMethodHandle().value, visitor);
    }

    @Override
    void internalAcceptHashing(HashingVisitor visitor) {
      value.acceptHashing(visitor);
    }

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

    @Override
    public DexValueMethodHandle asDexValueMethodHandle() {
      return this;
    }

    @Override
    public DexValueKind getValueKind() {
      return DexValueKind.METHOD_HANDLE;
    }

    @Override
    public void collectIndexedItems(IndexedItemCollection indexedItems) {
      value.collectIndexedItems(indexedItems);
    }

    @Override
    public AbstractValue toAbstractValue(AbstractValueFactory factory) {
      return UnknownValue.getInstance();
    }
  }
}
