Merge "Improve the printing of dex switch instructions"
diff --git a/src/main/java/com/android/tools/r8/code/Instruction.java b/src/main/java/com/android/tools/r8/code/Instruction.java
index 617642c..a87217b 100644
--- a/src/main/java/com/android/tools/r8/code/Instruction.java
+++ b/src/main/java/com/android/tools/r8/code/Instruction.java
@@ -146,9 +146,12 @@
     return StringUtils.hexString(offset, 2);
   }
 
+  static String formatDecimalOffset(int offset) {
+    return offset >= 0 ? ("+" + offset) : Integer.toString(offset);
+  }
+
   String formatRelativeOffset(int offset) {
-    String relativeString = offset >= 0 ? ("+" + offset) : Integer.toString(offset);
-    return formatOffset(getOffset() + offset) + " (" + relativeString + ")";
+    return formatOffset(getOffset() + offset) + " (" + formatDecimalOffset(offset) + ")";
   }
 
   String formatString(String left) {
@@ -220,6 +223,10 @@
 
   public abstract String toString(ClassNameMapper naming);
 
+  public String toString(ClassNameMapper naming, Instruction payloadUser) {
+    throw new InternalCompilerError("Instruction " + payloadUser + " is not a payload user");
+  }
+
   public String toString() {
     return toString(null);
   }
diff --git a/src/main/java/com/android/tools/r8/code/PackedSwitchPayload.java b/src/main/java/com/android/tools/r8/code/PackedSwitchPayload.java
index 5032ab0..66c54c3 100644
--- a/src/main/java/com/android/tools/r8/code/PackedSwitchPayload.java
+++ b/src/main/java/com/android/tools/r8/code/PackedSwitchPayload.java
@@ -83,9 +83,24 @@
   }
 
   public String toString(ClassNameMapper naming) {
-    StringBuilder builder = new StringBuilder("[PackedSwitchPayload]\n");
+    return toString(naming, null);
+  }
+
+  public String toString(ClassNameMapper naming, Instruction payloadUser) {
+    StringBuilder builder = new StringBuilder("[PackedSwitchPayload");
+    if (payloadUser == null) {
+      builder.append(" offsets relative to associated PackedSwitch");
+    }
+    builder.append("]\n");
     for (int i = 0; i < size; i++) {
-      StringUtils.appendLeftPadded(builder, (first_key + i) + " -> " + targets[i] + "\n", 20);
+      String offsetString;
+      if (payloadUser != null) {
+        // Don't show the decimal offset, as these are relative to the associated switch.
+        offsetString = formatOffset(targets[i] + payloadUser.getOffset());
+      } else {
+        offsetString = formatDecimalOffset(targets[i]);
+      }
+      StringUtils.appendLeftPadded(builder, (first_key + i) + " -> " + offsetString + "\n", 20);
     }
     return super.toString(naming) + builder.toString();
   }
diff --git a/src/main/java/com/android/tools/r8/code/SparseSwitchPayload.java b/src/main/java/com/android/tools/r8/code/SparseSwitchPayload.java
index e0e1280..c1ad480 100644
--- a/src/main/java/com/android/tools/r8/code/SparseSwitchPayload.java
+++ b/src/main/java/com/android/tools/r8/code/SparseSwitchPayload.java
@@ -89,9 +89,24 @@
   }
 
   public String toString(ClassNameMapper naming) {
-    StringBuilder builder = new StringBuilder("[SparseSwitchPayload]\n");
+    return toString(naming, null);
+  }
+
+  public String toString(ClassNameMapper naming, Instruction payloadUser) {
+    StringBuilder builder = new StringBuilder("[SparseSwitchPayload");
+    if (payloadUser == null) {
+      builder.append(" offsets relative to associated SparseSwitch");
+    }
+    builder.append("]\n");
     for (int i = 0; i < size; i++) {
-      StringUtils.appendLeftPadded(builder, keys[i] + " -> " + targets[i] + "\n", 20);
+      String offsetString;
+      if (payloadUser != null) {
+        // Don't show the decimal offset, as these are relative to the associated switch.
+        offsetString = StringUtils.hexString(targets[i] + payloadUser.getOffset(), 2);
+      } else {
+        offsetString = targets[i] >= 0 ? ("+" + targets[i]) : Integer.toString(targets[i]);
+      }
+      StringUtils.appendLeftPadded(builder, keys[i] + " -> " + offsetString + "\n", 20);
     }
     return super.toString(naming) + builder.toString();
   }
diff --git a/src/main/java/com/android/tools/r8/graph/DexCode.java b/src/main/java/com/android/tools/r8/graph/DexCode.java
index 8bd13f0..f62dda0 100644
--- a/src/main/java/com/android/tools/r8/graph/DexCode.java
+++ b/src/main/java/com/android/tools/r8/graph/DexCode.java
@@ -184,6 +184,15 @@
     builder.append("------------------------------------------------------------\n");
     builder.append("inst#  offset  instruction         arguments\n");
     builder.append("------------------------------------------------------------\n");
+
+    // Collect payload users.
+    Map<Integer, Instruction> payloadUsers = new HashMap<>();
+    for (Instruction dex : instructions) {
+      if (dex.hasPayload()) {
+        payloadUsers.put(dex.getOffset() + dex.getPayloadOffset(), dex);
+      }
+    }
+
     DexDebugEntry debugInfo = null;
     Iterator<DexDebugEntry> debugInfoIterator = Collections.emptyIterator();
     if (getDebugInfo() != null && method != null) {
@@ -197,7 +206,14 @@
         debugInfo = debugInfoIterator.hasNext() ? debugInfoIterator.next() : null;
       }
       StringUtils.appendLeftPadded(builder, Integer.toString(instructionNumber++), 5);
-      builder.append(": ").append(insn.toString(naming)).append('\n');
+      builder.append(": ");
+      if (insn.isSwitchPayload()) {
+        Instruction payloadUser = payloadUsers.get(insn.getOffset());
+        builder.append(insn.toString(naming, payloadUser));
+      } else {
+        builder.append(insn.toString(naming));
+      }
+      builder.append('\n');
     }
     if (debugInfoIterator.hasNext()) {
       throw new Unreachable("Could not print all debug information.");