Fixed a problem with handling MOVE_WIDE instruction in the type checker.
Fixed a problem with handling MOVE_WIDE instruction in the type checker.

Summary:
We have recently modified our build infrastructure (to use d8 as a dexer among other things) and started seeing a problem with ReDex's type checker that prevents our apps from being correctly processed by the tool. I have created a fairly simple example that should make it possible to reproduce the problem with instructions provided. I have also proposed a fix, but it needs vetting as it may or may not be generally applicable (works for us!). Here are the details.

The gist of the problem is that type checker's handling of MOVE_WIDE instruction does not correctly  account for the case when for a given source register vN, the destination register is vN+1. For example:
```
move-wide/from16 v24, v23
```

Here is the relevant code fragment from IRTypeChecker.cpp:
```
      set_type(current_state, insn->dest(), current_state->get(insn->src(0)));
      set_type(current_state,
               insn->dest() + 1,
               current_state->get(insn->src(0) + 1));
```

As the wide register's type information is stored at indexes N and N+1, in the case described above, we start with the following type information for source register:
```
current_state->get(23) == DOUBLE1
current_state->get(23+1) == DOUBLE2
```
Unfortunately `current_state->get(23+1)` (higher part of the source register) is the same as current_state->get(24) (lower part of the destination register) and the first call to `set_type` writes `DOUBLE1` value to this slot which is subsequently picked up (as the higher part for the source register) by the second call to `set_type`, resulting in the destination register having the following incorrect information (which triggers an assertion further in the analysis):
```
current_state->get(24) == DOUBLE1
current_state->get(24+1) == DOUBLE1
```

I initially thought that perhaps there is some underlying assumption about register allocation that would prevent this kind of situation from happening (and thus making it d8's bug, but dalvik bytecode spec for move-wide operation (https://source.android.com/devices/tech/dalvik/dalvik-bytecode) implies that this is not the case: "Note: It is legal to move from vN to either vN-1 or vN+1, so implementations must arrange for both halves of a register pair to be read before anything is written."

My proposed fix does exactly what the spec proposes but it still leaves source register in an invalid state. This would be fine if the move-wide instruction marked the end of the source register's lifetime, but I am not sure if this holds in general despite it being the case for the example I am presenting:
```
    move-wide/from16 v24, v23

    move-wide/from16 v22, p9

    .line 29
    .end local v23    # "ep1x":D
```

I am attaching the test file ([Test.txt](https://github.com/facebook/redex/files/1728809/Test.txt) renamed from Text.java to be attachable) that can be used to reproduce the problem. The test file is extracted from android.support.v4.graphics.PathParser (Android API version 27) - it contains the `arcToBezier` method of this class with additional stubbed out methods to simplify compilation.

I used the most recent version of ReDex (commit sha 2ac7121b1aa0a5ff3b88042c6e471924b3013995), the most recent version of d8 (commit sha 7658c212a391a2dcb565dbb18d8e99dfae0eda23), and javac version 1.8.0_144. Assuming that the test file is in `~/test` directory, r8 has been built in the `~/r8` directory, and Android SDK (including files for API 27) is located in the `android-sdk` directory, here are the steps to reproduce the problem (please note that it's important to enable debugging info generation for javac):

```
cd ~/test
javac -g Test.java
jar cvf test.jar Test.class Test\$Path.class
mkdir out_d8
java -jar ~/r8/build/libs/d8.jar --classpath ~/android-sdk/platforms/android-27/android.jar --output out_d8/ test.jar
cd out_d8/
zip classes.apk classes.dex
redex classes.apk
```
Closes https://github.com/facebook/redex/pull/297

Reviewed By: justinjhendrick

Differential Revision: D7003303

Pulled By: arnaudvenet

fbshipit-source-id: fb48fb3d8ef986ce114c67b095f4b0cd0d4d70ae

facebook/redex,facebook/redex,facebook/redex,facebook/redex,facebook/redex,facebook/redex,facebook/redex,facebook/redex,facebook/redex