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