[LIR] Add support for operand payloads larger than 255.

Bug: b/225838009
Change-Id: I14a71e790ca5e6bd09e7638b877ad948e90a6c6f
diff --git a/src/main/java/com/android/tools/r8/lightir/ByteUtils.java b/src/main/java/com/android/tools/r8/lightir/ByteUtils.java
index dc174ff..559685a 100644
--- a/src/main/java/com/android/tools/r8/lightir/ByteUtils.java
+++ b/src/main/java/com/android/tools/r8/lightir/ByteUtils.java
@@ -8,17 +8,20 @@
 /** Simple utilities for byte encodings. */
 public class ByteUtils {
 
+  public static final int MAX_U1 = 0xFF;
+  public static final int MAX_U2 = 0xFFFF;
+
   public static boolean isU1(int value) {
-    return (0 <= value) && (value <= 0xFF);
+    return (0 <= value) && (value <= MAX_U1);
   }
 
   // Lossy truncation of an integer value to its lowest byte.
   private static int truncateToU1(int value) {
-    return value & 0xFF;
+    return value & MAX_U1;
   }
 
   private static int truncateToU1(long value) {
-    return (int) value & 0xFF;
+    return (int) value & MAX_U1;
   }
 
   public static int ensureU1(int value) {
@@ -27,7 +30,7 @@
   }
 
   public static int fromU1(byte value) {
-    return value & 0xFF;
+    return value & MAX_U1;
   }
 
   public static int intEncodingSize(int value) {
@@ -81,11 +84,11 @@
   }
 
   public static boolean isU2(int value) {
-    return (value >= 0) && (value <= 0xFFFF);
+    return (value >= 0) && (value <= MAX_U2);
   }
 
   private static int truncateToU2(int value) {
-    return value & 0xFFFF;
+    return value & MAX_U2;
   }
 
   public static int ensureU2(int value) {
diff --git a/src/main/java/com/android/tools/r8/lightir/LirIterator.java b/src/main/java/com/android/tools/r8/lightir/LirIterator.java
index 84eaee6..0d9ccbd 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirIterator.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirIterator.java
@@ -51,6 +51,10 @@
       // Any instruction that is not a single byte has a two-byte header. The second byte is the
       // size of the variable width operand payload.
       int operandSize = u1();
+      if (operandSize == 0) {
+        // Zero is used to indicate the operand size is larger than a u1 encoded value.
+        operandSize = u4();
+      }
       endOfCurrentInstruction = currentByteIndex + operandSize;
     }
     return this;
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 c999baf..9761ef4 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirParsedInstructionCallback.java
@@ -821,7 +821,11 @@
           return;
         }
       case LirOpcodes.DNEG:
-        throw new Unimplemented("missing opcode: " + LirOpcodes.toString(opcode));
+        {
+          EV value = getNextValueOperand(view);
+          onNeg(NumericType.DOUBLE, value);
+          return;
+        }
       case LirOpcodes.ISHL:
       case LirOpcodes.LSHL:
       case LirOpcodes.ISHR:
diff --git a/src/main/java/com/android/tools/r8/lightir/LirWriter.java b/src/main/java/com/android/tools/r8/lightir/LirWriter.java
index 3f9e6b4..b7e4565 100644
--- a/src/main/java/com/android/tools/r8/lightir/LirWriter.java
+++ b/src/main/java/com/android/tools/r8/lightir/LirWriter.java
@@ -25,9 +25,15 @@
   }
 
   public void writeInstruction(int opcode, int operandsSizeInBytes) {
+    assert operandsSizeInBytes > 0;
     assert pendingOperandBytes == 0;
     writer.put(ByteUtils.ensureU1(opcode));
-    writer.put(ByteUtils.ensureU1(operandsSizeInBytes));
+    if (operandsSizeInBytes <= ByteUtils.MAX_U1) {
+      writer.put(ByteUtils.ensureU1(operandsSizeInBytes));
+    } else {
+      writer.put(0);
+      ByteUtils.writeEncodedInt(operandsSizeInBytes, writer);
+    }
     pendingOperandBytes = operandsSizeInBytes;
   }