[LIR] Introduce a type for constant pool items

This refactoring is in preparation for implementing structural
comparisons on LirCode. For that having a more restrictive type
of items in the pool will help ensure completeness.

Bug: b/225838009
Change-Id: Ibbff8cbde8282685b7060e40e35de7f775a3eaa2
diff --git a/src/main/java/com/android/tools/r8/graph/DexCallSite.java b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
index f5d8cea..2f84316 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCallSite.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCallSite.java
@@ -10,6 +10,7 @@
 import com.android.tools.r8.graph.DexValue.DexValueMethodHandle;
 import com.android.tools.r8.graph.DexValue.DexValueMethodType;
 import com.android.tools.r8.graph.DexValue.DexValueString;
+import com.android.tools.r8.lightir.LirConstant;
 import com.android.tools.r8.utils.structural.StructuralItem;
 import com.android.tools.r8.utils.structural.StructuralMapping;
 import com.android.tools.r8.utils.structural.StructuralSpecification;
@@ -25,7 +26,8 @@
 import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.tree.InvokeDynamicInsnNode;
 
-public final class DexCallSite extends IndexedDexItem implements StructuralItem<DexCallSite> {
+public final class DexCallSite extends IndexedDexItem
+    implements StructuralItem<DexCallSite>, LirConstant {
 
   public final DexString methodName;
   public final DexProto methodProto;
diff --git a/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java b/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java
index 0e72940..a61182e 100644
--- a/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java
+++ b/src/main/java/com/android/tools/r8/graph/DexMethodHandle.java
@@ -7,6 +7,7 @@
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.ir.code.InvokeType;
+import com.android.tools.r8.lightir.LirConstant;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.utils.structural.StructuralMapping;
 import com.android.tools.r8.utils.structural.StructuralSpecification;
@@ -15,7 +16,7 @@
 import org.objectweb.asm.Opcodes;
 
 public class DexMethodHandle extends IndexedDexItem
-    implements NamingLensComparable<DexMethodHandle> {
+    implements NamingLensComparable<DexMethodHandle>, LirConstant {
 
   public enum MethodHandleType {
     STATIC_PUT((short) 0x00),
diff --git a/src/main/java/com/android/tools/r8/graph/DexProto.java b/src/main/java/com/android/tools/r8/graph/DexProto.java
index b85f0da..3e9d428 100644
--- a/src/main/java/com/android/tools/r8/graph/DexProto.java
+++ b/src/main/java/com/android/tools/r8/graph/DexProto.java
@@ -4,6 +4,7 @@
 package com.android.tools.r8.graph;
 
 import com.android.tools.r8.dex.IndexedItemCollection;
+import com.android.tools.r8.lightir.LirConstant;
 import com.android.tools.r8.naming.NamingLens;
 import com.android.tools.r8.utils.structural.StructuralMapping;
 import com.android.tools.r8.utils.structural.StructuralSpecification;
@@ -11,7 +12,8 @@
 import java.util.Collections;
 import java.util.function.Consumer;
 
-public class DexProto extends IndexedDexItem implements NamingLensComparable<DexProto> {
+public class DexProto extends IndexedDexItem
+    implements NamingLensComparable<DexProto>, LirConstant {
 
   public static final DexProto SENTINEL = new DexProto(null, null, null);
 
diff --git a/src/main/java/com/android/tools/r8/graph/DexReference.java b/src/main/java/com/android/tools/r8/graph/DexReference.java
index 1e84335..c8e374d 100644
--- a/src/main/java/com/android/tools/r8/graph/DexReference.java
+++ b/src/main/java/com/android/tools/r8/graph/DexReference.java
@@ -5,13 +5,14 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.lightir.LirConstant;
 import java.util.function.BiConsumer;
 import java.util.function.BiFunction;
 import java.util.function.Consumer;
 import java.util.function.Function;
 
 /** A common interface for {@link DexType}, {@link DexField}, and {@link DexMethod}. */
-public abstract class DexReference extends IndexedDexItem {
+public abstract class DexReference extends IndexedDexItem implements LirConstant {
 
   public abstract <T> T apply(
       Function<DexType, T> classConsumer,
diff --git a/src/main/java/com/android/tools/r8/graph/DexString.java b/src/main/java/com/android/tools/r8/graph/DexString.java
index 0399618..f8f9132 100644
--- a/src/main/java/com/android/tools/r8/graph/DexString.java
+++ b/src/main/java/com/android/tools/r8/graph/DexString.java
@@ -5,6 +5,7 @@
 
 import com.android.tools.r8.dex.IndexedItemCollection;
 import com.android.tools.r8.errors.Unreachable;
+import com.android.tools.r8.lightir.LirConstant;
 import com.android.tools.r8.utils.AndroidApiLevel;
 import com.android.tools.r8.utils.DescriptorUtils;
 import com.android.tools.r8.utils.IdentifierUtils;
@@ -17,7 +18,8 @@
 import java.util.Arrays;
 import java.util.NoSuchElementException;
 
-public class DexString extends IndexedDexItem implements NamingLensComparable<DexString> {
+public class DexString extends IndexedDexItem
+    implements NamingLensComparable<DexString>, LirConstant {
 
   public static final DexString[] EMPTY_ARRAY = {};
   private static final int ARRAY_CHARACTER = '[';
diff --git a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
index 73a842f..cc457a3 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirBuilder.java
@@ -7,12 +7,10 @@
 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.dex.MixedSectionCollection;
 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.DexItem;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexMethodHandle;
@@ -68,7 +66,7 @@
   private final DexItemFactory factory;
   private final ByteArrayWriter byteWriter = new ByteArrayWriter();
   private final LirWriter writer = new LirWriter(byteWriter);
-  private final Reference2IntMap<DexItem> constants;
+  private final Reference2IntMap<LirConstant> constants;
   private final List<PositionEntry> positionTable;
   private int argumentCount = 0;
   private int instructionCount = 0;
@@ -91,17 +89,12 @@
   private final Int2ReferenceMap<int[]> debugLocalEnds = new Int2ReferenceOpenHashMap<>();
 
   /**
-   * Internal "DexItem" for the instruction payloads such that they can be put in the pool.
+   * Internal "LirConstant" for the instruction payloads such that they can be put in the pool.
    *
-   * <p>The instruction encoding assumes the instruction operand payload size is u1, so this allows
-   * the data payload to be stored in the constant pool instead.
+   * <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 extends DexItem {
-    @Override
-    protected final void collectMixedSectionItems(MixedSectionCollection collection) {
-      throw new Unreachable();
-    }
-  }
+  public abstract static class InstructionPayload implements LirConstant {}
 
   /**
    * Internal "DexItem" for the fill-array payloads such that they can be put in the pool.
@@ -246,17 +239,17 @@
     return true;
   }
 
-  private int getConstantIndex(DexItem item) {
+  private int getConstantIndex(LirConstant item) {
     int nextIndex = constants.size();
     Integer oldIndex = constants.putIfAbsent(item, nextIndex);
     return oldIndex != null ? oldIndex : nextIndex;
   }
 
-  private int constantIndexSize(DexItem item) {
+  private int constantIndexSize(LirConstant item) {
     return 4;
   }
 
-  private void writeConstantIndex(DexItem item) {
+  private void writeConstantIndex(LirConstant item) {
     int index = getConstantIndex(item);
     assert constantIndexSize(item) == ByteUtils.intEncodingSize(index);
     ByteUtils.writeEncodedInt(index, writer::writeOperand);
@@ -341,7 +334,7 @@
     return this;
   }
 
-  private LirBuilder<V, EV> addOneItemInstruction(int opcode, DexItem item) {
+  private LirBuilder<V, EV> addOneItemInstruction(int opcode, LirConstant item) {
     return addInstructionTemplate(opcode, Collections.singletonList(item), Collections.emptyList());
   }
 
@@ -356,10 +349,10 @@
   }
 
   private LirBuilder<V, EV> addInstructionTemplate(
-      int opcode, List<DexItem> items, List<V> values) {
+      int opcode, List<LirConstant> items, List<V> values) {
     int instructionIndex = advanceInstructionState();
     int operandSize = 0;
-    for (DexItem item : items) {
+    for (LirConstant item : items) {
       operandSize += constantIndexSize(item);
     }
     for (int i = 0; i < values.size(); i++) {
@@ -368,7 +361,7 @@
       operandSize += encodedValueIndexSize(encodedValueIndex);
     }
     writer.writeInstruction(opcode, operandSize);
-    for (DexItem item : items) {
+    for (LirConstant item : items) {
       writeConstantIndex(item);
     }
     for (int i = 0; i < values.size(); i++) {
@@ -587,10 +580,15 @@
         LirOpcodes.PUTFIELD, Collections.singletonList(field), ImmutableList.of(object, value));
   }
 
-  public LirBuilder<V, EV> addInvokeInstruction(int opcode, DexItem method, List<V> arguments) {
+  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;
@@ -788,7 +786,7 @@
   public LirCode<EV> build() {
     assert metadata != null;
     int constantsCount = constants.size();
-    DexItem[] constantTable = new DexItem[constantsCount];
+    LirConstant[] constantTable = new LirConstant[constantsCount];
     constants.forEach((item, index) -> constantTable[index] = item);
     DebugLocalInfoTable<EV> debugTable =
         debugLocals.isEmpty() ? null : new DebugLocalInfoTable<>(debugLocals, debugLocalEnds);
diff --git a/src/main/java/com/android/tools/r8/lightir/LirCode.java b/src/main/java/com/android/tools/r8/lightir/LirCode.java
index a55ab1d..00930a8 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirCode.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirCode.java
@@ -12,7 +12,6 @@
 import com.android.tools.r8.graph.Code;
 import com.android.tools.r8.graph.DebugLocalInfo;
 import com.android.tools.r8.graph.DexEncodedMethod;
-import com.android.tools.r8.graph.DexItem;
 import com.android.tools.r8.graph.DexItemFactory;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexType;
@@ -145,7 +144,7 @@
   private final IRMetadata irMetadata;
 
   /** Constant pool of items. */
-  private final DexItem[] constants;
+  private final LirConstant[] constants;
 
   private final PositionEntry[] positionTable;
 
@@ -175,7 +174,7 @@
   /** Should be constructed using {@link LirBuilder}. */
   LirCode(
       IRMetadata irMetadata,
-      DexItem[] constants,
+      LirConstant[] constants,
       PositionEntry[] positions,
       int argumentCount,
       byte[] instructions,
@@ -241,11 +240,11 @@
     return irMetadata;
   }
 
-  public DexItem getConstantItem(int index) {
+  public LirConstant getConstantItem(int index) {
     return constants[index];
   }
 
-  public DexItem[] getConstantPool() {
+  public LirConstant[] getConstantPool() {
     return constants;
   }
 
@@ -463,8 +462,8 @@
     }
   }
 
-  public LirCode<EV> newCodeWithRewrittenConstantPool(Function<DexItem, DexItem> rewriter) {
-    DexItem[] rewrittenConstants = ArrayUtils.map(constants, rewriter, new DexItem[0]);
+  public LirCode<EV> newCodeWithRewrittenConstantPool(Function<LirConstant, LirConstant> rewriter) {
+    LirConstant[] rewrittenConstants = ArrayUtils.map(constants, rewriter, new LirConstant[0]);
     if (constants == rewrittenConstants) {
       return this;
     }
@@ -497,7 +496,7 @@
   }
 
   public LirCode<EV> copyWithNewConstantsAndInstructions(
-      IRMetadata irMetadata, DexItem[] constants, byte[] instructions) {
+      IRMetadata irMetadata, LirConstant[] constants, byte[] instructions) {
     return new LirCode<>(
         irMetadata,
         constants,
diff --git a/src/main/java/com/android/tools/r8/lightir/LirConstant.java b/src/main/java/com/android/tools/r8/lightir/LirConstant.java
new file mode 100644
index 0000000..6c3dc4d
--- /dev/null
+++ b/src/main/java/com/android/tools/r8/lightir/LirConstant.java
@@ -0,0 +1,8 @@
+// Copyright (c) 2023, 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;
+
+/** Interface for items that can be put in the LIR constant pool. */
+public interface LirConstant {}
diff --git a/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java b/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
index 18125bd..cdd50cc 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
@@ -8,7 +8,6 @@
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexCallSite;
 import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexItem;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexMethodHandle;
 import com.android.tools.r8.graph.DexProto;
@@ -523,7 +522,7 @@
     onInstruction();
   }
 
-  private DexItem getConstantItem(int index) {
+  private LirConstant getConstantItem(int index) {
     return code.getConstantItem(index);
   }
 
@@ -538,7 +537,7 @@
         }
       case LirOpcodes.LDC:
         {
-          DexItem item = getConstantItem(view.getNextConstantOperand());
+          LirConstant item = getConstantItem(view.getNextConstantOperand());
           if (item instanceof DexString) {
             onConstString((DexString) item);
             return;
@@ -559,7 +558,7 @@
         }
       case LirOpcodes.CONSTCLASS_IGNORE_COMPAT:
         {
-          DexItem item = getConstantItem(view.getNextConstantOperand());
+          LirConstant item = getConstantItem(view.getNextConstantOperand());
           onConstClass((DexType) item, true);
           return;
         }
@@ -1070,7 +1069,7 @@
         }
       case LirOpcodes.NEW:
         {
-          DexItem item = getConstantItem(view.getNextConstantOperand());
+          LirConstant item = getConstantItem(view.getNextConstantOperand());
           if (item instanceof DexType) {
             onNewInstance((DexType) item);
             return;
diff --git a/src/main/java/com/android/tools/r8/lightir/SimpleLensLirRewriter.java b/src/main/java/com/android/tools/r8/lightir/SimpleLensLirRewriter.java
index 9bf133a..d093823 100644
--- a/src/main/java/com/android/tools/r8/lightir/SimpleLensLirRewriter.java
+++ b/src/main/java/com/android/tools/r8/lightir/SimpleLensLirRewriter.java
@@ -7,7 +7,6 @@
 import com.android.tools.r8.errors.Unreachable;
 import com.android.tools.r8.graph.DexCallSite;
 import com.android.tools.r8.graph.DexField;
-import com.android.tools.r8.graph.DexItem;
 import com.android.tools.r8.graph.DexMethod;
 import com.android.tools.r8.graph.DexProto;
 import com.android.tools.r8.graph.DexType;
@@ -35,7 +34,7 @@
   private final LensCodeRewriterUtils helper;
 
   private int numberOfInvokeTypeChanges = 0;
-  private Map<DexItem, DexItem> constantPoolMapping = null;
+  private Map<LirConstant, LirConstant> constantPoolMapping = null;
 
   public SimpleLensLirRewriter(
       LirCode<EV> code,
@@ -85,7 +84,7 @@
     }
   }
 
-  private void addRewrittenMapping(DexItem item, DexItem rewrittenItem) {
+  private void addRewrittenMapping(LirConstant item, LirConstant rewrittenItem) {
     if (item == rewrittenItem) {
       return;
     }
@@ -95,7 +94,7 @@
               // Avoid using initial capacity larger than the number of actual constants.
               Math.min(getCode().getConstantPool().length, 32));
     }
-    DexItem old = constantPoolMapping.put(item, rewrittenItem);
+    LirConstant old = constantPoolMapping.put(item, rewrittenItem);
     if (old != null && old != rewrittenItem) {
       throw new Unreachable(
           "Unexpected rewriting of item: "
@@ -152,7 +151,7 @@
     // First pass scans just the constant pool to see if any types change or if there are any
     // fields/methods that need to be examined.
     boolean hasPotentialRewrittenMethod = false;
-    for (DexItem constant : code.getConstantPool()) {
+    for (LirConstant constant : code.getConstantPool()) {
       if (constant instanceof DexType) {
         onTypeReference((DexType) constant);
       } else if (constant instanceof DexField) {
@@ -191,9 +190,9 @@
     // Build a small map from method refs to index in case the type-dependent methods are already
     // in the constant pool.
     Reference2IntMap<DexMethod> methodIndices = new Reference2IntOpenHashMap<>();
-    DexItem[] rewrittenConstants = code.getConstantPool();
-    for (int i = 0, dexItemsLength = rewrittenConstants.length; i < dexItemsLength; i++) {
-      DexItem constant = rewrittenConstants[i];
+    LirConstant[] rewrittenConstants = code.getConstantPool();
+    for (int i = 0, length = rewrittenConstants.length; i < length; i++) {
+      LirConstant constant = rewrittenConstants[i];
       if (constant instanceof DexMethod) {
         methodIndices.put((DexMethod) constant, i);
       }
@@ -202,7 +201,7 @@
     IRMetadata irMetadata = code.getMetadataForIR();
     ByteArrayWriter byteWriter = new ByteArrayWriter();
     LirWriter lirWriter = new LirWriter(byteWriter);
-    List<DexItem> methodsToAppend = new ArrayList<>(numberOfInvokeTypeChanges);
+    List<LirConstant> methodsToAppend = new ArrayList<>(numberOfInvokeTypeChanges);
     for (LirInstructionView view : code) {
       int opcode = view.getOpcode();
       // Instructions that do not have an invoke-type change are just mapped via identity.