1 /*
2  * Copyright (C) 2014 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 import java.lang.reflect.Method;
17 
18 public class Main {
19 
20   /// CHECK-START: void Main.InlineVoid() inliner (before)
21   /// CHECK-DAG:     <<Const42:i\d+>> IntConstant 42
22   /// CHECK-DAG:                      InvokeStaticOrDirect
23   /// CHECK-DAG:                      InvokeStaticOrDirect [<<Const42>>{{(,[ij]\d+)?}}]
24 
25   /// CHECK-START: void Main.InlineVoid() inliner (after)
26   /// CHECK-NOT:                      InvokeStaticOrDirect
27 
InlineVoid()28   public static void InlineVoid() {
29     returnVoid();
30     returnVoidWithOneParameter(42);
31   }
32 
33   /// CHECK-START: int Main.InlineParameter(int) inliner (before)
34   /// CHECK-DAG:     <<Param:i\d+>>  ParameterValue
35   /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect [<<Param>>{{(,[ij]\d+)?}}]
36   /// CHECK-DAG:                     Return [<<Result>>]
37 
38   /// CHECK-START: int Main.InlineParameter(int) inliner (after)
39   /// CHECK-DAG:     <<Param:i\d+>>  ParameterValue
40   /// CHECK-DAG:                     Return [<<Param>>]
41 
InlineParameter(int a)42   public static int InlineParameter(int a) {
43     return returnParameter(a);
44   }
45 
46   /// CHECK-START: long Main.InlineWideParameter(long) inliner (before)
47   /// CHECK-DAG:     <<Param:j\d+>>  ParameterValue
48   /// CHECK-DAG:     <<Result:j\d+>> InvokeStaticOrDirect [<<Param>>{{(,[ij]\d+)?}}]
49   /// CHECK-DAG:                     Return [<<Result>>]
50 
51   /// CHECK-START: long Main.InlineWideParameter(long) inliner (after)
52   /// CHECK-DAG:     <<Param:j\d+>>  ParameterValue
53   /// CHECK-DAG:                     Return [<<Param>>]
54 
InlineWideParameter(long a)55   public static long InlineWideParameter(long a) {
56     return returnWideParameter(a);
57   }
58 
59   /// CHECK-START: java.lang.Object Main.InlineReferenceParameter(java.lang.Object) inliner (before)
60   /// CHECK-DAG:     <<Param:l\d+>>  ParameterValue
61   /// CHECK-DAG:     <<Result:l\d+>> InvokeStaticOrDirect [<<Param>>{{(,[ij]\d+)?}}]
62   /// CHECK-DAG:                     Return [<<Result>>]
63 
64   /// CHECK-START: java.lang.Object Main.InlineReferenceParameter(java.lang.Object) inliner (after)
65   /// CHECK-DAG:     <<Param:l\d+>>  ParameterValue
66   /// CHECK-DAG:                     Return [<<Param>>]
67 
InlineReferenceParameter(Object o)68   public static Object InlineReferenceParameter(Object o) {
69     return returnReferenceParameter(o);
70   }
71 
72   /// CHECK-START: int Main.InlineInt() inliner (before)
73   /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect
74   /// CHECK-DAG:                     Return [<<Result>>]
75 
76   /// CHECK-START: int Main.InlineInt() inliner (after)
77   /// CHECK-DAG:     <<Const4:i\d+>> IntConstant 4
78   /// CHECK-DAG:                     Return [<<Const4>>]
79 
InlineInt()80   public static int InlineInt() {
81     return returnInt();
82   }
83 
84   /// CHECK-START: long Main.InlineWide() inliner (before)
85   /// CHECK-DAG:     <<Result:j\d+>> InvokeStaticOrDirect
86   /// CHECK-DAG:                     Return [<<Result>>]
87 
88   /// CHECK-START: long Main.InlineWide() inliner (after)
89   /// CHECK-DAG:     <<Const8:j\d+>> LongConstant 8
90   /// CHECK-DAG:                     Return [<<Const8>>]
91 
InlineWide()92   public static long InlineWide() {
93     return returnWide();
94   }
95 
96   /// CHECK-START: int Main.InlineAdd() inliner (before)
97   /// CHECK-DAG:     <<Const3:i\d+>> IntConstant 3
98   /// CHECK-DAG:     <<Const5:i\d+>> IntConstant 5
99   /// CHECK-DAG:     <<Result:i\d+>> InvokeStaticOrDirect
100   /// CHECK-DAG:                     Return [<<Result>>]
101 
102   /// CHECK-START: int Main.InlineAdd() inliner (after)
103   /// CHECK-DAG:     <<Const8:i\d+>> IntConstant 8
104   /// CHECK-DAG:                     Return [<<Const8>>]
105 
InlineAdd()106   public static int InlineAdd() {
107     return returnAdd(3, 5);
108   }
109 
110   /// CHECK-START: int Main.InlineFieldAccess() inliner (before)
111   /// CHECK-DAG:     <<After:i\d+>>  InvokeStaticOrDirect
112   /// CHECK-DAG:                     Return [<<After>>]
113 
114   /// CHECK-START: int Main.InlineFieldAccess() inliner (after)
115   /// CHECK-DAG:     <<Const1:i\d+>> IntConstant 1
116   /// CHECK-DAG:     <<Before:i\d+>> StaticFieldGet
117   /// CHECK-DAG:     <<After:i\d+>>  Add [<<Before>>,<<Const1>>]
118   /// CHECK-DAG:                     StaticFieldSet [{{l\d+}},<<After>>]
119   /// CHECK-DAG:                     Return [<<After>>]
120 
121   /// CHECK-START: int Main.InlineFieldAccess() inliner (after)
122   /// CHECK-NOT:                     InvokeStaticOrDirect
123 
InlineFieldAccess()124   public static int InlineFieldAccess() {
125     return incCounter();
126   }
127 
InlineWithControlFlow(boolean cond)128   public static int InlineWithControlFlow(boolean cond) {
129     try {
130       Class<?> c = Class.forName("Smali");
131       Method m = c.getMethod("InlineWithControlFlow", boolean.class);
132       return (Integer) m.invoke(null, cond);
133     } catch (Throwable t) {
134       throw new RuntimeException(t);
135     }
136   }
137 
138   /// CHECK-START: int Main.returnAbs(int) builder (after)
139   /// CHECK-DAG:     <<Result:i\d+>>      InvokeStaticOrDirect intrinsic:MathAbsInt
140   /// CHECK-DAG:                          Return [<<Result>>]
141 
returnAbs(int i)142   private static int returnAbs(int i) {
143     return Math.abs(i);
144   }
145 
146   /// CHECK-START: int Main.InlinedIntrinsicsAreStillIntrinsic() inliner (before)
147   /// CHECK-DAG:     <<ConstMinus1:i\d+>> IntConstant -1
148   /// CHECK-DAG:     <<Result:i\d+>>      InvokeStaticOrDirect
149   /// CHECK-DAG:                          Return [<<Result>>]
150 
151   //
152   // Intrinsic directly simplified into Abs and evaluated!
153   //
154   /// CHECK-START: int Main.InlinedIntrinsicsAreStillIntrinsic() inliner (after)
155   /// CHECK-DAG:     <<Const1:i\d+>>      IntConstant 1
156   /// CHECK-DAG:                          Return [<<Const1>>]
157 
InlinedIntrinsicsAreStillIntrinsic()158   public static int InlinedIntrinsicsAreStillIntrinsic() {
159     return returnAbs(-1);
160   }
161 
returnVoid()162   private static void returnVoid() {
163     return;
164   }
165 
returnVoidWithOneParameter(int a)166   private static void returnVoidWithOneParameter(int a) {
167     return;
168   }
169 
returnParameter(int a)170   private static int returnParameter(int a) {
171     return a;
172   }
173 
returnWideParameter(long a)174   private static long returnWideParameter(long a) {
175     return a;
176   }
177 
returnReferenceParameter(Object o)178   private static Object returnReferenceParameter(Object o) {
179     return o;
180   }
181 
returnInt()182   private static int returnInt() {
183     return 4;
184   }
185 
returnWide()186   private static long returnWide() {
187     return 8L;
188   }
189 
returnAdd(int a, int b)190   private static int returnAdd(int a, int b) {
191     return a + b;
192   }
193 
returnSub(int a, int b)194   private static int returnSub(int a, int b) {
195     return a - b;
196   }
197 
198   private static int counter = 42;
199 
incCounter()200   private static int incCounter() {
201     return ++counter;
202   }
203 
main(String[] args)204   public static void main(String[] args) {
205     InlineVoid();
206 
207     if (InlineInt() != 4) {
208       throw new Error();
209     }
210 
211     if (InlineWide() != 8L) {
212       throw new Error();
213     }
214 
215     if (InlineParameter(42) != 42) {
216       throw new Error();
217     }
218 
219     if (InlineWideParameter(0x100000001L) != 0x100000001L) {
220       throw new Error();
221     }
222 
223     if (InlineReferenceParameter(Main.class) != Main.class) {
224       throw new Error();
225     }
226 
227     if (InlineAdd() != 8) {
228       throw new Error();
229     }
230 
231     if (InlineFieldAccess() != 43 || InlineFieldAccess() != 44) {
232       throw new Error();
233     }
234 
235     if (InlineWithControlFlow(true) != 4) {
236       throw new Error();
237     }
238 
239     if (InlineWithControlFlow(false) != 2) {
240       throw new Error();
241     }
242 
243     if (InlinedIntrinsicsAreStillIntrinsic() != 1) {
244       throw new Error();
245     }
246 
247     if (returnAbs(-1) != 1) {
248       throw new Error();
249     }
250   }
251 }
252