[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;
}