1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 public class Main {
18 
assertIntEquals(int expected, int result)19   public static void assertIntEquals(int expected, int result) {
20     if (expected != result) {
21       throw new Error("Expected: " + expected + ", found: " + result);
22     }
23   }
24 
assertStringEquals(String expected, String result)25   public static void assertStringEquals(String expected, String result) {
26     if (expected != null ? !expected.equals(result) : result != null) {
27       throw new Error("Expected: " + expected + ", found: " + result);
28     }
29   }
30 
assertClassEquals(Class<?> expected, Class<?> result)31   public static void assertClassEquals(Class<?> expected, Class<?> result) {
32     if (expected != result) {
33       throw new Error("Expected: " + expected + ", found: " + result);
34     }
35   }
36 
$noinline$foo(int x)37   private static int $noinline$foo(int x) {
38     return x;
39   }
40 
41   /// CHECK-START-{ARM,ARM64,X86,X86_64}: int Main.testSimple(int) builder (after)
42   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
43 
44   /// CHECK-START-X86: int Main.testSimple(int) pc_relative_fixups_x86 (before)
45   /// CHECK-NOT:            X86ComputeBaseMethodAddress
46 
47   /// CHECK-START-X86: int Main.testSimple(int) pc_relative_fixups_x86 (after)
48   /// CHECK:                X86ComputeBaseMethodAddress
49   /// CHECK-NOT:            X86ComputeBaseMethodAddress
50 
testSimple(int x)51   public static int testSimple(int x) {
52     // This call should use PC-relative .bss array load to retrieve the target method.
53     return $noinline$foo(x);
54   }
55 
56   /// CHECK-START-{ARM,ARM64,X86,X86_64}: int Main.testDiamond(boolean, int) builder (after)
57   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
58   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
59 
60   /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (before)
61   /// CHECK-NOT:            X86ComputeBaseMethodAddress
62 
63   /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (after)
64   /// CHECK:                X86ComputeBaseMethodAddress
65   /// CHECK-NOT:            X86ComputeBaseMethodAddress
66 
67   /// CHECK-START-X86: int Main.testDiamond(boolean, int) pc_relative_fixups_x86 (after)
68   /// CHECK:                X86ComputeBaseMethodAddress
69   /// CHECK-NEXT:           If
70 
testDiamond(boolean negate, int x)71   public static int testDiamond(boolean negate, int x) {
72     // These calls should use PC-relative loads to retrieve the target method.
73     // PC-relative bases used by X86 should be pulled before the If.
74     if (negate) {
75       return $noinline$foo(-x);
76     } else {
77       return $noinline$foo(x);
78     }
79   }
80 
81   /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (before)
82   /// CHECK-NOT:            X86ComputeBaseMethodAddress
83 
84   /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after)
85   /// CHECK:                X86ComputeBaseMethodAddress
86   /// CHECK-NOT:            X86ComputeBaseMethodAddress
87 
88   /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after)
89   /// CHECK:                InvokeStaticOrDirect
90   /// CHECK-NOT:            InvokeStaticOrDirect
91 
92   /// CHECK-START-X86: int Main.testLoop(int[], int) pc_relative_fixups_x86 (after)
93   /// CHECK:                ArrayLength
94   /// CHECK-NEXT:           X86ComputeBaseMethodAddress
95   /// CHECK-NEXT:           Goto
96   /// CHECK:                begin_block
97   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
98 
testLoop(int[] array, int x)99   public static int testLoop(int[] array, int x) {
100     // PC-relative bases used by X86 should be pulled before the loop.
101     for (int i : array) {
102       x += $noinline$foo(i);
103     }
104     return x;
105   }
106 
107   /// CHECK-START-X86: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_x86 (before)
108   /// CHECK-NOT:            X86ComputeBaseMethodAddress
109 
110   /// CHECK-START-X86: int Main.testLoopWithDiamond(int[], boolean, int) pc_relative_fixups_x86 (after)
111   /// CHECK:                If
112   /// CHECK:                begin_block
113   /// CHECK:                ArrayLength
114   /// CHECK-NEXT:           X86ComputeBaseMethodAddress
115   /// CHECK-NEXT:           Goto
116 
testLoopWithDiamond(int[] array, boolean negate, int x)117   public static int testLoopWithDiamond(int[] array, boolean negate, int x) {
118     // PC-relative bases used by X86 should be pulled before the loop but not outside the if.
119     if (array != null) {
120       for (int i : array) {
121         if (negate) {
122           x += $noinline$foo(-i);
123         } else {
124           x += $noinline$foo(i);
125         }
126       }
127     }
128     return x;
129   }
130 
131   /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.String Main.$noinline$getBootImageString() builder (after)
132   /// CHECK:                LoadString load_kind:BootImageRelRo
133 
$noinline$getBootImageString()134   public static String $noinline$getBootImageString() {
135     // Empty string is known to be in the boot image.
136     return "";
137   }
138 
139   /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.String Main.$noinline$getNonBootImageString() builder (after)
140   /// CHECK:                LoadString load_kind:BssEntry
141 
142   /// CHECK-START-X86: java.lang.String Main.$noinline$getNonBootImageString() pc_relative_fixups_x86 (before)
143   /// CHECK-NOT:            X86ComputeBaseMethodAddress
144 
145   /// CHECK-START-X86: java.lang.String Main.$noinline$getNonBootImageString() pc_relative_fixups_x86 (after)
146   /// CHECK-DAG:            X86ComputeBaseMethodAddress
147   /// CHECK-DAG:            LoadString load_kind:BssEntry
148 
$noinline$getNonBootImageString()149   public static String $noinline$getNonBootImageString() {
150     // This string is not in the boot image.
151     return "non-boot-image-string";
152   }
153 
154   /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.Class Main.$noinline$getStringClass() builder (after)
155   /// CHECK:                LoadClass load_kind:BootImageRelRo class_name:java.lang.String
156 
$noinline$getStringClass()157   public static Class<?> $noinline$getStringClass() {
158     // String class is known to be in the boot image.
159     return String.class;
160   }
161 
162   /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.Class Main.$noinline$getOtherClass() builder (after)
163   /// CHECK:                LoadClass load_kind:BssEntry class_name:Other
164 
165   /// CHECK-START-X86: java.lang.Class Main.$noinline$getOtherClass() pc_relative_fixups_x86 (before)
166   /// CHECK-NOT:            X86ComputeBaseMethodAddress
167 
168   /// CHECK-START-X86: java.lang.Class Main.$noinline$getOtherClass() pc_relative_fixups_x86 (after)
169   /// CHECK-DAG:            X86ComputeBaseMethodAddress
170   /// CHECK-DAG:            LoadClass load_kind:BssEntry class_name:Other
171 
$noinline$getOtherClass()172   public static Class<?> $noinline$getOtherClass() {
173     // Other class is not in the boot image.
174     return Other.class;
175   }
176 
177   /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.String Main.$noinline$toHexString(int) builder (after)
178   /// CHECK:                InvokeStaticOrDirect method_load_kind:BootImageRelRo
$noinline$toHexString(int value)179   public static String $noinline$toHexString(int value) {
180     return Integer.toString(value, 16);
181   }
182 
183   /// CHECK-START-{ARM,ARM64,X86,X86_64}: java.lang.String Main.$noinline$toHexStringIndirect(int) builder (after)
184   /// CHECK:                InvokeStaticOrDirect method_load_kind:BssEntry
185 
186   /// CHECK-START-X86: java.lang.String Main.$noinline$toHexStringIndirect(int) pc_relative_fixups_x86 (before)
187   /// CHECK-NOT:            X86ComputeBaseMethodAddress
188 
189   /// CHECK-START-X86: java.lang.String Main.$noinline$toHexStringIndirect(int) pc_relative_fixups_x86 (after)
190   /// CHECK-DAG:            X86ComputeBaseMethodAddress
191   /// CHECK-DAG:            InvokeStaticOrDirect method_load_kind:BssEntry
$noinline$toHexStringIndirect(int value)192   public static String $noinline$toHexStringIndirect(int value) {
193     return $noinline$toHexString(value);
194   }
195 
main(String[] args)196   public static void main(String[] args) {
197     assertIntEquals(1, testSimple(1));
198     assertIntEquals(1, testDiamond(false, 1));
199     assertIntEquals(-1, testDiamond(true, 1));
200     assertIntEquals(3, testLoop(new int[]{ 2 }, 1));
201     assertIntEquals(8, testLoop(new int[]{ 3, 4 }, 1));
202     assertIntEquals(1, testLoopWithDiamond(null, false, 1));
203     assertIntEquals(3, testLoopWithDiamond(new int[]{ 2 }, false, 1));
204     assertIntEquals(-6, testLoopWithDiamond(new int[]{ 3, 4 }, true, 1));
205     assertStringEquals("", $noinline$getBootImageString());
206     assertStringEquals("non-boot-image-string", $noinline$getNonBootImageString());
207     assertClassEquals(String.class, $noinline$getStringClass());
208     assertClassEquals(Other.class, $noinline$getOtherClass());
209     assertStringEquals("12345678", $noinline$toHexString(0x12345678));
210     assertStringEquals("76543210", $noinline$toHexStringIndirect(0x76543210));
211   }
212 }
213 
214 class Other {
215 }
216 
217 class MainExtension extends Main {
218 }
219