blob: 4c8201e53e8ed5fe4964c094e832c7e72d887874 [file] [log] [blame]
Nicolas Geoffray818f2102014-02-18 16:43:35 +00001/*
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/stringprintf.h"
18#include "builder.h"
19#include "dex_instruction.h"
20#include "nodes.h"
21#include "pretty_printer.h"
22#include "utils/arena_allocator.h"
23
24#include "gtest/gtest.h"
25
26namespace art {
27
Nicolas Geoffray818f2102014-02-18 16:43:35 +000028class StringPrettyPrinter : public HPrettyPrinter {
29 public:
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000030 explicit StringPrettyPrinter(HGraph* graph)
31 : HPrettyPrinter(graph), str_(""), current_block_(nullptr) { }
Nicolas Geoffray818f2102014-02-18 16:43:35 +000032
33 virtual void PrintInt(int value) {
34 str_ += StringPrintf("%d", value);
35 }
36
37 virtual void PrintString(const char* value) {
38 str_ += value;
39 }
40
41 virtual void PrintNewLine() {
42 str_ += '\n';
43 }
44
45 void Clear() { str_.clear(); }
46
47 std::string str() const { return str_; }
48
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000049 virtual void VisitBasicBlock(HBasicBlock* block) {
50 current_block_ = block;
51 HPrettyPrinter::VisitBasicBlock(block);
52 }
53
54 virtual void VisitGoto(HGoto* gota) {
55 str_ += " Goto ";
56 PrintInt(current_block_->successors()->Get(0)->block_id());
57 PrintNewLine();
58 }
59
Nicolas Geoffray818f2102014-02-18 16:43:35 +000060 private:
61 std::string str_;
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000062 HBasicBlock* current_block_;
63
Nicolas Geoffray818f2102014-02-18 16:43:35 +000064 DISALLOW_COPY_AND_ASSIGN(StringPrettyPrinter);
65};
66
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000067
68static void TestCode(const uint16_t* data, int length, const char* expected) {
Nicolas Geoffray818f2102014-02-18 16:43:35 +000069 ArenaPool pool;
70 ArenaAllocator allocator(&pool);
71 HGraphBuilder builder(&allocator);
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000072 HGraph* graph = builder.BuildGraph(data, data + length);
Nicolas Geoffray818f2102014-02-18 16:43:35 +000073 ASSERT_NE(graph, nullptr);
74 StringPrettyPrinter printer(graph);
75 printer.VisitInsertionOrder();
76 ASSERT_STREQ(expected, printer.str().c_str());
Nicolas Geoffray818f2102014-02-18 16:43:35 +000077}
78
Nicolas Geoffraybe9a92a2014-02-25 14:22:56 +000079TEST(PrettyPrinterTest, ReturnVoid) {
80 const uint16_t data[] = { Instruction::RETURN_VOID };
81
82 const char* expected =
83 "BasicBlock 0, succ: 1\n"
84 " Goto 1\n"
85 "BasicBlock 1, pred: 0, succ: 2\n"
86 " ReturnVoid\n"
87 "BasicBlock 2, pred: 1\n"
88 " Exit\n";
89
90 TestCode(data, sizeof(data) / sizeof(uint16_t), expected);
91}
92
93TEST(PrettyPrinterTest, CFG1) {
94 const char* expected =
95 "BasicBlock 0, succ: 1\n"
96 " Goto 1\n"
97 "BasicBlock 1, pred: 0, succ: 2\n"
98 " Goto 2\n"
99 "BasicBlock 2, pred: 1, succ: 3\n"
100 " ReturnVoid\n"
101 "BasicBlock 3, pred: 2\n"
102 " Exit\n";
103
104 const uint16_t data[] = {
105 Instruction::GOTO | 0x100,
106 Instruction::RETURN_VOID
107 };
108
109 TestCode(data, sizeof(data) / sizeof(uint16_t), expected);
110}
111
112TEST(PrettyPrinterTest, CFG2) {
113 const char* expected =
114 "BasicBlock 0, succ: 1\n"
115 " Goto 1\n"
116 "BasicBlock 1, pred: 0, succ: 2\n"
117 " Goto 2\n"
118 "BasicBlock 2, pred: 1, succ: 3\n"
119 " Goto 3\n"
120 "BasicBlock 3, pred: 2, succ: 4\n"
121 " ReturnVoid\n"
122 "BasicBlock 4, pred: 3\n"
123 " Exit\n";
124
125 const uint16_t data[] = {
126 Instruction::GOTO | 0x100,
127 Instruction::GOTO | 0x100,
128 Instruction::RETURN_VOID
129 };
130
131 TestCode(data, sizeof(data) / sizeof(uint16_t), expected);
132}
133
134TEST(PrettyPrinterTest, CFG3) {
135 const char* expected =
136 "BasicBlock 0, succ: 1\n"
137 " Goto 1\n"
138 "BasicBlock 1, pred: 0, succ: 3\n"
139 " Goto 3\n"
140 "BasicBlock 2, pred: 3, succ: 4\n"
141 " ReturnVoid\n"
142 "BasicBlock 3, pred: 1, succ: 2\n"
143 " Goto 2\n"
144 "BasicBlock 4, pred: 2\n"
145 " Exit\n";
146
147 const uint16_t data1[] = {
148 Instruction::GOTO | 0x200,
149 Instruction::RETURN_VOID,
150 Instruction::GOTO | 0xFF00
151 };
152
153 TestCode(data1, sizeof(data1) / sizeof(uint16_t), expected);
154
155 const uint16_t data2[] = {
156 Instruction::GOTO_16, 3,
157 Instruction::RETURN_VOID,
158 Instruction::GOTO_16, 0xFFFF
159 };
160
161 TestCode(data2, sizeof(data2) / sizeof(uint16_t), expected);
162
163 const uint16_t data3[] = {
164 Instruction::GOTO_32, 4, 0,
165 Instruction::RETURN_VOID,
166 Instruction::GOTO_32, 0xFFFF, 0xFFFF
167 };
168
169 TestCode(data3, sizeof(data3) / sizeof(uint16_t), expected);
170}
171
172TEST(PrettyPrinterTest, CFG4) {
173 const char* expected =
174 "BasicBlock 0, succ: 1\n"
175 " Goto 1\n"
176 "BasicBlock 1, pred: 0, 1, succ: 1\n"
177 " Goto 1\n"
178 "BasicBlock 2\n"
179 " Exit\n";
180
181 const uint16_t data1[] = {
182 Instruction::NOP,
183 Instruction::GOTO | 0xFF00
184 };
185
186 TestCode(data1, sizeof(data1) / sizeof(uint16_t), expected);
187
188 const uint16_t data2[] = {
189 Instruction::GOTO_32, 0, 0
190 };
191
192 TestCode(data2, sizeof(data2) / sizeof(uint16_t), expected);
193}
194
195TEST(PrettyPrinterTest, CFG5) {
196 const char* expected =
197 "BasicBlock 0, succ: 1\n"
198 " Goto 1\n"
199 "BasicBlock 1, pred: 0, 2, succ: 3\n"
200 " ReturnVoid\n"
201 "BasicBlock 2, succ: 1\n"
202 " Goto 1\n"
203 "BasicBlock 3, pred: 1\n"
204 " Exit\n";
205
206 const uint16_t data[] = {
207 Instruction::RETURN_VOID,
208 Instruction::GOTO | 0x100,
209 Instruction::GOTO | 0xFE00
210 };
211
212 TestCode(data, sizeof(data) / sizeof(uint16_t), expected);
213}
214
215TEST(OptimizerTest, CFG6) {
216 const char* expected =
217 "BasicBlock 0, succ: 1\n"
218 " Goto 1\n"
219 "BasicBlock 1, pred: 0, succ: 3, 2\n"
220 " If\n"
221 "BasicBlock 2, pred: 1, succ: 3\n"
222 " Goto 3\n"
223 "BasicBlock 3, pred: 1, 2, succ: 4\n"
224 " ReturnVoid\n"
225 "BasicBlock 4, pred: 3\n"
226 " Exit\n";
227
228 const uint16_t data[] = {
229 Instruction::IF_EQ, 3,
230 Instruction::GOTO | 0x100,
231 Instruction::RETURN_VOID
232 };
233
234 TestCode(data, sizeof(data) / sizeof(uint16_t), expected);
235}
236
237TEST(OptimizerTest, CFG7) {
238 const char* expected =
239 "BasicBlock 0, succ: 1\n"
240 " Goto 1\n"
241 "BasicBlock 1, pred: 0, succ: 3, 2\n"
242 " If\n"
243 "BasicBlock 2, pred: 1, 3, succ: 3\n"
244 " Goto 3\n"
245 "BasicBlock 3, pred: 1, 2, succ: 2\n"
246 " Goto 2\n"
247 "BasicBlock 4\n"
248 " Exit\n";
249
250 const uint16_t data[] = {
251 Instruction::IF_EQ, 3,
252 Instruction::GOTO | 0x100,
253 Instruction::GOTO | 0xFF00
254 };
255
256 TestCode(data, sizeof(data) / sizeof(uint16_t), expected);
257}
Nicolas Geoffray818f2102014-02-18 16:43:35 +0000258} // namespace art