Fix bad debug info due to 64-bit registers alignment

- Registers of LocalStart and LocalSnapshot must also be shift when it is required.

Bug: 16344305

Change-Id: I015409abd41ca7f03f5e6718b37f558cd3be79ad
diff --git a/dx/src/com/android/dx/dex/code/DalvInsn.java b/dx/src/com/android/dx/dex/code/DalvInsn.java
index 41fcbdc..49a2f30 100644
--- a/dx/src/com/android/dx/dex/code/DalvInsn.java
+++ b/dx/src/com/android/dx/dex/code/DalvInsn.java
@@ -19,9 +19,11 @@
 import com.android.dx.rop.code.RegisterSpec;
 import com.android.dx.rop.code.RegisterSpecList;
 import com.android.dx.rop.code.SourcePosition;
+import com.android.dx.ssa.RegisterMapper;
 import com.android.dx.util.AnnotatedOutput;
 import com.android.dx.util.Hex;
 import com.android.dx.util.TwoColumnOutput;
+
 import java.util.BitSet;
 
 /**
@@ -381,6 +383,17 @@
     }
 
     /**
+     * Returns an instance that is just like this one, except that the
+     * register list is mapped by using {@code mapper}.
+     *
+     * @param mapper {@code non-null;} used to map registers
+     * @return {@code non-null;} an appropriately-constructed instance
+     */
+    public DalvInsn withMapper(RegisterMapper mapper) {
+      return withRegisters(mapper.map(getRegisters()));
+    }
+
+    /**
      * Gets the size of this instruction, in 16-bit code units.
      *
      * @return {@code >= 0;} the code size of this instruction
diff --git a/dx/src/com/android/dx/dex/code/LocalSnapshot.java b/dx/src/com/android/dx/dex/code/LocalSnapshot.java
index baeab4c..863a0ef 100644
--- a/dx/src/com/android/dx/dex/code/LocalSnapshot.java
+++ b/dx/src/com/android/dx/dex/code/LocalSnapshot.java
@@ -20,6 +20,7 @@
 import com.android.dx.rop.code.RegisterSpecList;
 import com.android.dx.rop.code.RegisterSpecSet;
 import com.android.dx.rop.code.SourcePosition;
+import com.android.dx.ssa.RegisterMapper;
 
 /**
  * Pseudo-instruction which is used to hold a snapshot of the
@@ -93,4 +94,10 @@
 
         return sb.toString();
     }
+
+    /** {@inheritDoc} */
+    @Override
+    public DalvInsn withMapper(RegisterMapper mapper) {
+      return new LocalSnapshot(getPosition(), mapper.map(locals));
+    }
 }
diff --git a/dx/src/com/android/dx/dex/code/LocalStart.java b/dx/src/com/android/dx/dex/code/LocalStart.java
index 9a17c5b..0566cb5 100644
--- a/dx/src/com/android/dx/dex/code/LocalStart.java
+++ b/dx/src/com/android/dx/dex/code/LocalStart.java
@@ -19,6 +19,7 @@
 import com.android.dx.rop.code.RegisterSpec;
 import com.android.dx.rop.code.RegisterSpecList;
 import com.android.dx.rop.code.SourcePosition;
+import com.android.dx.ssa.RegisterMapper;
 
 /**
  * Pseudo-instruction which is used to introduce a new local variable. That
@@ -95,4 +96,10 @@
     protected String listingString0(boolean noteIndices) {
         return "local-start " + localString(local);
     }
+
+    /** {@inheritDoc} */
+    @Override
+    public DalvInsn withMapper(RegisterMapper mapper) {
+      return new LocalStart(getPosition(), mapper.map(local));
+    }
 }
diff --git a/dx/src/com/android/dx/dex/code/OutputFinisher.java b/dx/src/com/android/dx/dex/code/OutputFinisher.java
index a1fc721..b2eb43f 100644
--- a/dx/src/com/android/dx/dex/code/OutputFinisher.java
+++ b/dx/src/com/android/dx/dex/code/OutputFinisher.java
@@ -870,6 +870,8 @@
 
       for (int i = 0; i < insnSize; i++) {
         DalvInsn insn = insns.get(i);
+        // Since there is no need to replace CodeAddress since it does not use registers, skips it to
+        // avoid to update all TargetInsn that contain a reference to CodeAddress
         if (!(insn instanceof CodeAddress)) {
           insns.set(i, insn.withRegisterOffset(delta));
         }
@@ -892,8 +894,10 @@
 
       for (int i = 0; i < insnSize; i++) {
         DalvInsn insn = insns.get(i);
+        // Since there is no need to replace CodeAddress since it does not use registers, skips it to
+        // avoid to update all TargetInsn that contain a reference to CodeAddress
         if (!(insn instanceof CodeAddress)) {
-          insns.set(i, insn.withRegisters(mapper.map(insn.getRegisters())));
+          insns.set(i, insn.withMapper(mapper));
         }
       }
     }
diff --git a/dx/src/com/android/dx/ssa/RegisterMapper.java b/dx/src/com/android/dx/ssa/RegisterMapper.java
index 3099000..c105f1c 100644
--- a/dx/src/com/android/dx/ssa/RegisterMapper.java
+++ b/dx/src/com/android/dx/ssa/RegisterMapper.java
@@ -18,6 +18,7 @@
 
 import com.android.dx.rop.code.RegisterSpec;
 import com.android.dx.rop.code.RegisterSpecList;
+import com.android.dx.rop.code.RegisterSpecSet;
 
 /**
  * Represents a mapping between two register numbering schemes.
@@ -57,4 +58,26 @@
         // Return the old sources if nothing has changed.
         return newSources.equals(sources) ? sources : newSources;
     }
+
+    /**
+     *
+     * @param sources old register set
+     * @return new mapped register set, or old if nothing has changed.
+     */
+    public final RegisterSpecSet map(RegisterSpecSet sources) {
+        int sz = sources.getMaxSize();
+        RegisterSpecSet newSources = new RegisterSpecSet(getNewRegisterCount());
+
+        for (int i = 0; i < sz; i++) {
+            RegisterSpec registerSpec = sources.get(i);
+            if (registerSpec != null) {
+                newSources.put(map(registerSpec));
+            }
+        }
+
+        newSources.setImmutable();
+
+        // Return the old sources if nothing has changed.
+        return newSources.equals(sources) ? sources : newSources;
+    }
 }