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