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