dx: Fix result information on invoke-{polymorphic,custom}

Changes the annotation on invoke-custom and invoke-polymorphic
instructions to signify no result generated. This was problematic for
methods using lots of registers and led to missing move instructions
ahead of the invoke.

Test: dalvik/dx/tests/run-test 138
Bug: b/62722425

Change-Id: If8c02b7601cabf39272b862c89f6ecf1748f855a
diff --git a/dx/src/com/android/dx/dex/code/Dops.java b/dx/src/com/android/dx/dex/code/Dops.java
index cc87695..b70911e 100644
--- a/dx/src/com/android/dx/dex/code/Dops.java
+++ b/dx/src/com/android/dx/dex/code/Dops.java
@@ -939,19 +939,19 @@
 
     public static final Dop INVOKE_POLYMORPHIC =
         new Dop(Opcodes.INVOKE_POLYMORPHIC, Opcodes.INVOKE_POLYMORPHIC,
-            Opcodes.INVOKE_POLYMORPHIC_RANGE, Form45cc.THE_ONE, true);
+            Opcodes.INVOKE_POLYMORPHIC_RANGE, Form45cc.THE_ONE, false);
 
     public static final Dop INVOKE_POLYMORPHIC_RANGE =
         new Dop(Opcodes.INVOKE_POLYMORPHIC_RANGE, Opcodes.INVOKE_POLYMORPHIC,
-            Opcodes.NO_NEXT, Form4rcc.THE_ONE, true);
+            Opcodes.NO_NEXT, Form4rcc.THE_ONE, false);
 
     public static final Dop INVOKE_CUSTOM =
         new Dop(Opcodes.INVOKE_CUSTOM, Opcodes.INVOKE_CUSTOM,
-            Opcodes.INVOKE_CUSTOM_RANGE, Form35c.THE_ONE, true);
+            Opcodes.INVOKE_CUSTOM_RANGE, Form35c.THE_ONE, false);
 
     public static final Dop INVOKE_CUSTOM_RANGE =
         new Dop(Opcodes.INVOKE_CUSTOM_RANGE, Opcodes.INVOKE_CUSTOM,
-            Opcodes.NO_NEXT, Form3rc.THE_ONE, true);
+            Opcodes.NO_NEXT, Form3rc.THE_ONE, false);
 
     // END(dops)
 
diff --git a/dx/tests/138-invoke-polymorphic-again/Main.java b/dx/tests/138-invoke-polymorphic-again/Main.java
new file mode 100644
index 0000000..48de64d
--- /dev/null
+++ b/dx/tests/138-invoke-polymorphic-again/Main.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodHandles.Lookup;
+import java.lang.invoke.MethodType;
+
+public class Main {
+  public static void assertEquals(int i1, int i2) {
+  }
+
+  public int foof(int a, int b, int c, int d,
+                  int e, int f, int g, int h,
+                  int i, int j, int k, int l,
+                  int m, int n, int o) {
+    return a;
+  }
+
+  public static void $opt$BasicTest() throws Throwable {
+    Main m = null;
+    // OTH: >= 15 arguments to invokeExact tickles this bug. Fewer, no repro.
+    assertEquals(42, -42);
+    m.foof(0, 1, 2, 3,
+           4, 5, 6, 7,
+           8, 9, 10, 11,
+           12, 13, 14);
+    MethodHandle mh0 = null;
+    mh0.invokeExact("bad");
+  }
+
+  public static int $opt$BasicTest2() throws Throwable {
+    Main m = null;
+    // OTH: >= 15 arguments to invokeExact tickles this bug. Fewer, no repro.
+    assertEquals(42, -42);
+    m.foof(0, 1, 2, 3,
+           4, 5, 6, 7,
+           8, 9, 10, 11,
+           12, 13, 14);
+    MethodHandle mh0 = null;
+    return (int) mh0.invokeExact("bad");
+  }
+
+  public static void main(String[] args) throws Throwable {
+    $opt$BasicTest();
+  }
+}
diff --git a/dx/tests/138-invoke-polymorphic-again/expected.txt b/dx/tests/138-invoke-polymorphic-again/expected.txt
new file mode 100644
index 0000000..7c3fb77
--- /dev/null
+++ b/dx/tests/138-invoke-polymorphic-again/expected.txt
@@ -0,0 +1,88 @@
+Main.$opt$BasicTest:()V:
+regs: 0012; ins: 0000; outs: 0010
+  0000: const/4 v1, #null // #0
+  0001: const/16 v2, #int 42 // #002a
+  0003: const/16 v3, #int -42 // #ffd6
+  0005: invoke-static {v2, v3}, Main.assertEquals:(II)V
+  0008: const/4 v2, #int 0 // #0
+  0009: const/4 v3, #int 1 // #1
+  000a: const/4 v4, #int 2 // #2
+  000b: const/4 v5, #int 3 // #3
+  000c: const/4 v6, #int 4 // #4
+  000d: const/4 v7, #int 5 // #5
+  000e: const/4 v8, #int 6 // #6
+  000f: const/4 v9, #int 7 // #7
+  0010: const/16 v10, #int 8 // #0008
+  0012: const/16 v11, #int 9 // #0009
+  0014: const/16 v12, #int 10 // #000a
+  0016: const/16 v13, #int 11 // #000b
+  0018: const/16 v14, #int 12 // #000c
+  001a: const/16 v15, #int 13 // #000d
+  001c: const/16 v16, #int 14 // #000e
+  001e: invoke-virtual/range {v1..v16}, Main.foof:(IIIIIIIIIIIIIII)I
+  0021: const/16 v17, #null // #0000
+  0023: const-string v2, "bad"
+  0025: move-object/from16 v0, v17
+  0027: invoke-polymorphic {v0, v2}, java.lang.invoke.MethodHandle.invokeExact:([Ljava/lang/Object;)Ljava/lang/Object;, (Ljava/lang/String;)V
+  002b: return-void
+  debug info
+    line_start: 34
+    parameters_size: 0000
+    0000: prologue end
+    0000: line 34
+    0001: line 36
+    0001: +local v1 m Main
+    0008: line 37
+    0021: advance pc
+    0021: line 41
+    0023: line 42
+    0023: +local v17 mh0 java.lang.invoke.MethodHandle
+    002b: line 43
+    end sequence
+  source file: "Main.java"
+  method annotations:
+    system-annotation dalvik.annotation.Throws {value: {java.lang.Throwable}}
+Main.$opt$BasicTest2:()I:
+regs: 0012; ins: 0000; outs: 0010
+  0000: const/4 v1, #null // #0
+  0001: const/16 v2, #int 42 // #002a
+  0003: const/16 v3, #int -42 // #ffd6
+  0005: invoke-static {v2, v3}, Main.assertEquals:(II)V
+  0008: const/4 v2, #int 0 // #0
+  0009: const/4 v3, #int 1 // #1
+  000a: const/4 v4, #int 2 // #2
+  000b: const/4 v5, #int 3 // #3
+  000c: const/4 v6, #int 4 // #4
+  000d: const/4 v7, #int 5 // #5
+  000e: const/4 v8, #int 6 // #6
+  000f: const/4 v9, #int 7 // #7
+  0010: const/16 v10, #int 8 // #0008
+  0012: const/16 v11, #int 9 // #0009
+  0014: const/16 v12, #int 10 // #000a
+  0016: const/16 v13, #int 11 // #000b
+  0018: const/16 v14, #int 12 // #000c
+  001a: const/16 v15, #int 13 // #000d
+  001c: const/16 v16, #int 14 // #000e
+  001e: invoke-virtual/range {v1..v16}, Main.foof:(IIIIIIIIIIIIIII)I
+  0021: const/16 v17, #null // #0000
+  0023: const-string v2, "bad"
+  0025: move-object/from16 v0, v17
+  0027: invoke-polymorphic {v0, v2}, java.lang.invoke.MethodHandle.invokeExact:([Ljava/lang/Object;)Ljava/lang/Object;, (Ljava/lang/String;)I
+  002b: move-result v2
+  002c: return v2
+  debug info
+    line_start: 46
+    parameters_size: 0000
+    0000: prologue end
+    0000: line 46
+    0001: line 48
+    0001: +local v1 m Main
+    0008: line 49
+    0021: advance pc
+    0021: line 53
+    0023: line 54
+    0023: +local v17 mh0 java.lang.invoke.MethodHandle
+    end sequence
+  source file: "Main.java"
+  method annotations:
+    system-annotation dalvik.annotation.Throws {value: {java.lang.Throwable}}
diff --git a/dx/tests/138-invoke-polymorphic-again/info.txt b/dx/tests/138-invoke-polymorphic-again/info.txt
new file mode 100644
index 0000000..98a8f78
--- /dev/null
+++ b/dx/tests/138-invoke-polymorphic-again/info.txt
@@ -0,0 +1,7 @@
+This tests the proper register preparation for invoke-polymorphic
+instructions. The test was written as the invoke-polymorphic bytecodes
+were mis-annotated in dx as having a return result. This led to a path
+that did not emit the necessary move instructions and the generated
+DEX file was rejected by ART. The issue was only visible when dx
+optimization was enabled, but the problem lay in the OutputFinisher
+register selection.
diff --git a/dx/tests/138-invoke-polymorphic-again/run b/dx/tests/138-invoke-polymorphic-again/run
new file mode 100755
index 0000000..2ee0ad6
--- /dev/null
+++ b/dx/tests/138-invoke-polymorphic-again/run
@@ -0,0 +1,22 @@
+#!/bin/bash
+#
+# Copyright (C) 2017 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+SDK_VERSION=26
+
+JAVAC_FLAGS="-g -Xlint:-options -source 1.8 -target 1.8 -implicit:none"
+$JAVAC $JAVAC_FLAGS -d . Main.java
+dx --debug --dex --min-sdk-version=${SDK_VERSION} --output="classes.dex" \
+   --dump-method=Main.\$opt\$BasicTest* --dump-width=1000 --dump-to=- Main.class 2>&1