Version 1.0.12.
Merge: Block the receiver register always before Android M.
CL: https://r8-review.googlesource.com/c/r8/+/17201

R=sgjesse@google.com

Change-Id: Ied1f3a807c08288eeb343900c08c6aff72ba1e87
diff --git a/src/main/java/com/android/tools/r8/Version.java b/src/main/java/com/android/tools/r8/Version.java
index 96af965..9781dc5 100644
--- a/src/main/java/com/android/tools/r8/Version.java
+++ b/src/main/java/com/android/tools/r8/Version.java
@@ -11,7 +11,7 @@
 
   // This field is accessed from release scripts using simple pattern matching.
   // Therefore, changing this field could break our release scripts.
-  public static final String LABEL = "v1.0.11";
+  public static final String LABEL = "v1.0.12";
 
   private Version() {
   }
diff --git a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
index 7af0451..15c186f 100644
--- a/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
+++ b/src/main/java/com/android/tools/r8/ir/regalloc/LinearScanRegisterAllocator.java
@@ -1973,6 +1973,24 @@
 
   private void computeLiveRanges() {
     computeLiveRanges(options, code, liveAtEntrySets, liveIntervals);
+    // Art VMs before Android M assume that the register for the receiver never changes its value.
+    // This assumption is used during verification. Allowing the receiver register to be
+    // overwritten can therefore lead to verification errors. If we could be targeting one of these
+    // VMs we block the receiver register throughout the method.
+    if (options.canHaveThisTypeVerifierBug() && !code.method.accessFlags.isStatic()) {
+      for (Instruction instruction : code.blocks.get(0).getInstructions()) {
+        if (instruction.isArgument() && instruction.outValue().isThis()) {
+          Value thisValue = instruction.outValue();
+          LiveIntervals thisIntervals = thisValue.getLiveIntervals();
+          thisIntervals.getRanges().clear();
+          thisIntervals.addRange(new LiveRange(0, code.getNextInstructionNumber()));
+          for (Set<Value> values : liveAtEntrySets.values()) {
+            values.add(thisValue);
+          }
+          return;
+        }
+      }
+    }
   }
 
   /**
diff --git a/src/main/java/com/android/tools/r8/utils/InternalOptions.java b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
index 4ebe661..610d547 100644
--- a/src/main/java/com/android/tools/r8/utils/InternalOptions.java
+++ b/src/main/java/com/android/tools/r8/utils/InternalOptions.java
@@ -475,4 +475,11 @@
   public boolean canUseNotInstruction() {
     return minApiLevel >= AndroidApiLevel.L.getLevel();
   }
+
+  // Art before M has a verifier bug where the type of the contents of the receiver register is
+  // assumed to not change. If the receiver register is reused for something else the verifier
+  // will fail and the code will not run.
+  public boolean canHaveThisTypeVerifierBug() {
+    return minApiLevel < AndroidApiLevel.M.getLevel();
+  }
 }