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 
17 #include "base/arena_allocator.h"
18 #include "base/stringprintf.h"
19 #include "builder.h"
20 #include "dex_file.h"
21 #include "dex_instruction.h"
22 #include "nodes.h"
23 #include "optimizing_unit_test.h"
24 #include "pretty_printer.h"
25 
26 #include "gtest/gtest.h"
27 
28 namespace art {
29 
TestCode(const uint16_t * data,const char * expected)30 static void TestCode(const uint16_t* data, const char* expected) {
31   ArenaPool pool;
32   ArenaAllocator allocator(&pool);
33   HGraph* graph = CreateGraph(&allocator);
34   HGraphBuilder builder(graph);
35   const DexFile::CodeItem* item = reinterpret_cast<const DexFile::CodeItem*>(data);
36   bool graph_built = builder.BuildGraph(*item);
37   ASSERT_TRUE(graph_built);
38   StringPrettyPrinter printer(graph);
39   printer.VisitInsertionOrder();
40   ASSERT_STREQ(expected, printer.str().c_str());
41 }
42 
TEST(PrettyPrinterTest,ReturnVoid)43 TEST(PrettyPrinterTest, ReturnVoid) {
44   const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
45       Instruction::RETURN_VOID);
46 
47   const char* expected =
48       "BasicBlock 0, succ: 1\n"
49       "  2: SuspendCheck\n"
50       "  3: Goto 1\n"
51       "BasicBlock 1, pred: 0, succ: 2\n"
52       "  0: ReturnVoid\n"
53       "BasicBlock 2, pred: 1\n"
54       "  1: Exit\n";
55 
56   TestCode(data, expected);
57 }
58 
TEST(PrettyPrinterTest,CFG1)59 TEST(PrettyPrinterTest, CFG1) {
60   const char* expected =
61     "BasicBlock 0, succ: 1\n"
62     "  3: SuspendCheck\n"
63     "  4: Goto 1\n"
64     "BasicBlock 1, pred: 0, succ: 2\n"
65     "  0: Goto 2\n"
66     "BasicBlock 2, pred: 1, succ: 3\n"
67     "  1: ReturnVoid\n"
68     "BasicBlock 3, pred: 2\n"
69     "  2: Exit\n";
70 
71   const uint16_t data[] =
72     ZERO_REGISTER_CODE_ITEM(
73       Instruction::GOTO | 0x100,
74       Instruction::RETURN_VOID);
75 
76   TestCode(data, expected);
77 }
78 
TEST(PrettyPrinterTest,CFG2)79 TEST(PrettyPrinterTest, CFG2) {
80   const char* expected =
81     "BasicBlock 0, succ: 1\n"
82     "  4: SuspendCheck\n"
83     "  5: Goto 1\n"
84     "BasicBlock 1, pred: 0, succ: 2\n"
85     "  0: Goto 2\n"
86     "BasicBlock 2, pred: 1, succ: 3\n"
87     "  1: Goto 3\n"
88     "BasicBlock 3, pred: 2, succ: 4\n"
89     "  2: ReturnVoid\n"
90     "BasicBlock 4, pred: 3\n"
91     "  3: Exit\n";
92 
93   const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
94     Instruction::GOTO | 0x100,
95     Instruction::GOTO | 0x100,
96     Instruction::RETURN_VOID);
97 
98   TestCode(data, expected);
99 }
100 
TEST(PrettyPrinterTest,CFG3)101 TEST(PrettyPrinterTest, CFG3) {
102   const char* expected =
103     "BasicBlock 0, succ: 1\n"
104     "  4: SuspendCheck\n"
105     "  5: Goto 1\n"
106     "BasicBlock 1, pred: 0, succ: 3\n"
107     "  0: Goto 3\n"
108     "BasicBlock 2, pred: 3, succ: 4\n"
109     "  1: ReturnVoid\n"
110     "BasicBlock 3, pred: 1, succ: 2\n"
111     "  2: Goto 2\n"
112     "BasicBlock 4, pred: 2\n"
113     "  3: Exit\n";
114 
115   const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
116     Instruction::GOTO | 0x200,
117     Instruction::RETURN_VOID,
118     Instruction::GOTO | 0xFF00);
119 
120   TestCode(data1, expected);
121 
122   const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
123     Instruction::GOTO_16, 3,
124     Instruction::RETURN_VOID,
125     Instruction::GOTO_16, 0xFFFF);
126 
127   TestCode(data2, expected);
128 
129   const uint16_t data3[] = ZERO_REGISTER_CODE_ITEM(
130     Instruction::GOTO_32, 4, 0,
131     Instruction::RETURN_VOID,
132     Instruction::GOTO_32, 0xFFFF, 0xFFFF);
133 
134   TestCode(data3, expected);
135 }
136 
TEST(PrettyPrinterTest,CFG4)137 TEST(PrettyPrinterTest, CFG4) {
138   const char* expected =
139     "BasicBlock 0, succ: 1\n"
140     "  3: SuspendCheck\n"
141     "  4: Goto 1\n"
142     "BasicBlock 1, pred: 0, 1, succ: 1\n"
143     "  0: SuspendCheck\n"
144     "  1: Goto 1\n"
145     "BasicBlock 2\n"
146     "  2: Exit\n";
147 
148   const uint16_t data1[] = ZERO_REGISTER_CODE_ITEM(
149     Instruction::NOP,
150     Instruction::GOTO | 0xFF00);
151 
152   TestCode(data1, expected);
153 
154   const uint16_t data2[] = ZERO_REGISTER_CODE_ITEM(
155     Instruction::GOTO_32, 0, 0);
156 
157   TestCode(data2, expected);
158 }
159 
TEST(PrettyPrinterTest,CFG5)160 TEST(PrettyPrinterTest, CFG5) {
161   const char* expected =
162     "BasicBlock 0, succ: 1\n"
163     "  3: SuspendCheck\n"
164     "  4: Goto 1\n"
165     "BasicBlock 1, pred: 0, 2, succ: 3\n"
166     "  0: ReturnVoid\n"
167     "BasicBlock 2, succ: 1\n"
168     "  1: Goto 1\n"
169     "BasicBlock 3, pred: 1\n"
170     "  2: Exit\n";
171 
172   const uint16_t data[] = ZERO_REGISTER_CODE_ITEM(
173     Instruction::RETURN_VOID,
174     Instruction::GOTO | 0x100,
175     Instruction::GOTO | 0xFE00);
176 
177   TestCode(data, expected);
178 }
179 
TEST(PrettyPrinterTest,CFG6)180 TEST(PrettyPrinterTest, CFG6) {
181   const char* expected =
182     "BasicBlock 0, succ: 1\n"
183     "  0: Local [4, 3, 2]\n"
184     "  1: IntConstant [2]\n"
185     "  10: SuspendCheck\n"
186     "  11: Goto 1\n"
187     "BasicBlock 1, pred: 0, succ: 3, 2\n"
188     "  2: StoreLocal(0, 1)\n"
189     "  3: LoadLocal(0) [5]\n"
190     "  4: LoadLocal(0) [5]\n"
191     "  5: Equal(3, 4) [6]\n"
192     "  6: If(5)\n"
193     "BasicBlock 2, pred: 1, succ: 3\n"
194     "  7: Goto 3\n"
195     "BasicBlock 3, pred: 1, 2, succ: 4\n"
196     "  8: ReturnVoid\n"
197     "BasicBlock 4, pred: 3\n"
198     "  9: Exit\n";
199 
200   const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
201     Instruction::CONST_4 | 0 | 0,
202     Instruction::IF_EQ, 3,
203     Instruction::GOTO | 0x100,
204     Instruction::RETURN_VOID);
205 
206   TestCode(data, expected);
207 }
208 
TEST(PrettyPrinterTest,CFG7)209 TEST(PrettyPrinterTest, CFG7) {
210   const char* expected =
211     "BasicBlock 0, succ: 1\n"
212     "  0: Local [4, 3, 2]\n"
213     "  1: IntConstant [2]\n"
214     "  11: SuspendCheck\n"
215     "  12: Goto 1\n"
216     "BasicBlock 1, pred: 0, succ: 3, 2\n"
217     "  2: StoreLocal(0, 1)\n"
218     "  3: LoadLocal(0) [5]\n"
219     "  4: LoadLocal(0) [5]\n"
220     "  5: Equal(3, 4) [6]\n"
221     "  6: If(5)\n"
222     "BasicBlock 2, pred: 1, 3, succ: 3\n"
223     "  7: Goto 3\n"
224     "BasicBlock 3, pred: 1, 2, succ: 2\n"
225     "  8: SuspendCheck\n"
226     "  9: Goto 2\n"
227     "BasicBlock 4\n"
228     "  10: Exit\n";
229 
230   const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
231     Instruction::CONST_4 | 0 | 0,
232     Instruction::IF_EQ, 3,
233     Instruction::GOTO | 0x100,
234     Instruction::GOTO | 0xFF00);
235 
236   TestCode(data, expected);
237 }
238 
TEST(PrettyPrinterTest,IntConstant)239 TEST(PrettyPrinterTest, IntConstant) {
240   const char* expected =
241     "BasicBlock 0, succ: 1\n"
242     "  0: Local [2]\n"
243     "  1: IntConstant [2]\n"
244     "  5: SuspendCheck\n"
245     "  6: Goto 1\n"
246     "BasicBlock 1, pred: 0, succ: 2\n"
247     "  2: StoreLocal(0, 1)\n"
248     "  3: ReturnVoid\n"
249     "BasicBlock 2, pred: 1\n"
250     "  4: Exit\n";
251 
252   const uint16_t data[] = ONE_REGISTER_CODE_ITEM(
253     Instruction::CONST_4 | 0 | 0,
254     Instruction::RETURN_VOID);
255 
256   TestCode(data, expected);
257 }
258 }  // namespace art
259