IRBuilder: Distinguish incoming and outgoing locals for instructions

Split SourceCode.getCurrentLocal() into getIncomingLocal() and
getOutgoingLocal().  Similarly, split IRBuilder.getLocalValue() into
getIncomingLocalValue() and getOutgoingLocalValue() (which defer to the
SourceCode methods).

Allow calling IRBuilder.addDebugLocalStart(register, local) in the no-op
case when the most recent instruction introduced the local to start.
This makes it easier for JarSourceCode since it can just start all
locals, even those that were just written with new local info.

Make JarState transactional around each instruction: Before building an
instruction, JarState.beginTransaction() is called which reads the local
variable table to find locals that start/end right after the instruction
to build. JarState.writeLocal() doesn't update local information until
JarState.endTransaction() is called, at which point JarState verifies
that the updated local information matches the register writes.

Other small changes:

* CodeRewriter.simplifyDebugLocals(): Don't simplify if the local being
  simplified changes in-between.

* CodeRewriter.simplifyDebugLocals(): Move unrelated debug uses to
  previous instruction instead of inValue.definition.

* DexType.isInterface(): More helpful assertion error.

* JarState.pop(): More helpful assertion error.

* CfRegisterAllocator: Assert that unhandled does not contain Argument.

* Add more checks in IRCode.consistentBlockInstructions().

* JumpInstruction.toString(): Catch AssertionError in getNumber().

* Value.replaceDebugUser(): Remove DebugUse.START when moving it to its
  definition

Bug: 77522100
Change-Id: I808ca8c07135538f5764a70d197f4b54301d7743
diff --git a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
index 24e6eb5..fb75931 100644
--- a/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
+++ b/src/main/java/com/android/tools/r8/ir/code/BasicBlock.java
@@ -42,6 +42,22 @@
 
   private Int2ReferenceMap<DebugLocalInfo> localsAtEntry;
 
+  public boolean consistentBlockInstructions(boolean argumentsAllowed) {
+    for (Instruction instruction : getInstructions()) {
+      assert instruction.getPosition() != null;
+      assert instruction.getBlock() == this;
+      assert !instruction.isArgument() || argumentsAllowed;
+      assert !instruction.isDebugLocalRead() || !instruction.getDebugValues().isEmpty();
+      // TODO(b/79186787): Ensure DEX backend inserts Move *after* arguments.
+      if (!(instruction.isArgument()
+          || instruction.isMove()
+          || instruction.isDebugLocalsChange())) {
+        argumentsAllowed = false;
+      }
+    }
+    return true;
+  }
+
   public void setLocalsAtEntry(Int2ReferenceMap<DebugLocalInfo> localsAtEntry) {
     this.localsAtEntry = localsAtEntry;
   }