• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <iostream>
17#include <string>
18
19#include <gtest/gtest.h>
20#include "disassembler.h"
21
22using namespace panda::disasm;
23
24#cmakedefine DISASM_BIN_DIR "@DISASM_BIN_DIR@/"
25
26TEST(instructions_test, test_language_panda_assembly)
27{
28    Disassembler d {};
29
30    std::stringstream ss {};
31    d.Disassemble(std::string(DISASM_BIN_DIR) + "empty_record.bc");
32    d.Serialize(ss);
33
34    EXPECT_TRUE(ss.str().find(".language PandaAssembly") != std::string::npos);
35}
36
37TEST(instructions_test, test_ins)
38{
39    Disassembler d {};
40
41    std::stringstream ss {};
42    d.Disassemble(std::string(DISASM_BIN_DIR) + "instructions.bc");
43    d.Serialize(ss);
44
45    size_t beg_g = ss.str().find("g() <static> {");
46    size_t end_g = ss.str().find('}', beg_g);
47
48    ASSERT_TRUE(beg_g != std::string::npos && end_g != std::string::npos) << "function g not found";
49
50    std::string body_g = ss.str().substr(beg_g + strlen("g() {"), end_g - (beg_g + strlen("g() {")));
51
52    EXPECT_TRUE(body_g.find("\tmov v0, v1") != std::string::npos);
53    EXPECT_TRUE(body_g.find("\tmov.64 v2, v3") != std::string::npos);
54    EXPECT_TRUE(body_g.find("\tmov.obj v4, v5") != std::string::npos);
55
56    EXPECT_TRUE(body_g.find("\tmovi v0, 0xffffffffffffffff") != std::string::npos);
57    EXPECT_TRUE(body_g.find("\tmovi.64 v0, 0x2") != std::string::npos);
58    EXPECT_TRUE(body_g.find("\tfmovi.64 v0, 0x4008147ae147ae14") != std::string::npos);
59
60    EXPECT_TRUE(body_g.find("\tlda v1") != std::string::npos);
61    EXPECT_TRUE(body_g.find("\tlda.64 v0") != std::string::npos);
62    EXPECT_TRUE(body_g.find("\tlda.obj v1") != std::string::npos);
63
64    EXPECT_TRUE(body_g.find("\tldai 0x1") != std::string::npos);
65    EXPECT_TRUE(body_g.find("\tldai.64 0x2") != std::string::npos);
66    EXPECT_TRUE(body_g.find("\tfldai.64 0x4008147ae147ae14") != std::string::npos);
67    EXPECT_TRUE(body_g.find("\tlda.str \"kek\"") != std::string::npos);
68    EXPECT_TRUE(body_g.find("\tlda.type A") != std::string::npos);
69    EXPECT_TRUE(body_g.find("\tlda.null") != std::string::npos);
70
71    EXPECT_TRUE(body_g.find("\tsta v0") != std::string::npos);
72    EXPECT_TRUE(body_g.find("\tsta.64 v1") != std::string::npos);
73    EXPECT_TRUE(body_g.find("\tsta.obj v2") != std::string::npos);
74
75    EXPECT_TRUE(body_g.find("jump_label_0:\n\tjmp jump_label_0") != std::string::npos);
76    EXPECT_TRUE(body_g.find("\tjeq v1, jump_label_1") != std::string::npos);
77    EXPECT_TRUE(body_g.find("\tldai 0x1") != std::string::npos);
78    EXPECT_TRUE(body_g.find("\tjmp jump_label_2") != std::string::npos);
79    EXPECT_TRUE(body_g.find("jump_label_1:\n\tldai 0x0") != std::string::npos);
80    EXPECT_TRUE(body_g.find("jump_label_2:\n\tcmp.64 v1") != std::string::npos);
81    EXPECT_TRUE(body_g.find("\tucmp v2") != std::string::npos);
82    EXPECT_TRUE(body_g.find("\tucmp.64 v3") != std::string::npos);
83
84    EXPECT_TRUE(body_g.find("\tfcmpl.64 v1") != std::string::npos);
85    EXPECT_TRUE(body_g.find("\tfcmpg.64 v1") != std::string::npos);
86
87    EXPECT_TRUE(body_g.find("\tjeqz jump_label_0") != std::string::npos);
88    EXPECT_TRUE(body_g.find("\tjnez jump_label_0") != std::string::npos);
89    EXPECT_TRUE(body_g.find("\tjltz jump_label_0") != std::string::npos);
90    EXPECT_TRUE(body_g.find("\tjgtz jump_label_0") != std::string::npos);
91    EXPECT_TRUE(body_g.find("\tjlez jump_label_0") != std::string::npos);
92    EXPECT_TRUE(body_g.find("\tjgez jump_label_0") != std::string::npos);
93
94    EXPECT_TRUE(body_g.find("\tjeq v2, jump_label_0") != std::string::npos);
95    EXPECT_TRUE(body_g.find("\tjne v2, jump_label_0") != std::string::npos);
96    EXPECT_TRUE(body_g.find("\tjlt v2, jump_label_0") != std::string::npos);
97    EXPECT_TRUE(body_g.find("\tjgt v2, jump_label_0") != std::string::npos);
98    EXPECT_TRUE(body_g.find("\tjle v2, jump_label_0") != std::string::npos);
99    EXPECT_TRUE(body_g.find("\tjge v2, jump_label_0") != std::string::npos);
100
101    EXPECT_TRUE(body_g.find("\tfadd2.64 v1") != std::string::npos);
102    EXPECT_TRUE(body_g.find("\tfsub2.64 v1") != std::string::npos);
103    EXPECT_TRUE(body_g.find("\tfmul2.64 v1") != std::string::npos);
104    EXPECT_TRUE(body_g.find("\tfdiv2.64 v1") != std::string::npos);
105    EXPECT_TRUE(body_g.find("\tfmod2.64 v1") != std::string::npos);
106
107    EXPECT_TRUE(body_g.find("\tadd2 v2") != std::string::npos);
108    EXPECT_TRUE(body_g.find("\tadd2.64 v2") != std::string::npos);
109    EXPECT_TRUE(body_g.find("\tsub2 v2") != std::string::npos);
110    EXPECT_TRUE(body_g.find("\tsub2.64 v2") != std::string::npos);
111    EXPECT_TRUE(body_g.find("\tmul2 v2") != std::string::npos);
112    EXPECT_TRUE(body_g.find("\tmul2.64 v2") != std::string::npos);
113    EXPECT_TRUE(body_g.find("\tand2 v2") != std::string::npos);
114    EXPECT_TRUE(body_g.find("\tand2.64 v2") != std::string::npos);
115    EXPECT_TRUE(body_g.find("\tor2 v2") != std::string::npos);
116    EXPECT_TRUE(body_g.find("\tor2.64 v2") != std::string::npos);
117    EXPECT_TRUE(body_g.find("\txor2 v2") != std::string::npos);
118    EXPECT_TRUE(body_g.find("\txor2.64 v2") != std::string::npos);
119    EXPECT_TRUE(body_g.find("\tshl2 v2") != std::string::npos);
120    EXPECT_TRUE(body_g.find("\tshl2.64 v2") != std::string::npos);
121    EXPECT_TRUE(body_g.find("\tshr2 v2") != std::string::npos);
122    EXPECT_TRUE(body_g.find("\tshr2.64 v2") != std::string::npos);
123    EXPECT_TRUE(body_g.find("\tashr2 v2") != std::string::npos);
124    EXPECT_TRUE(body_g.find("\tashr2.64 v2") != std::string::npos);
125    EXPECT_TRUE(body_g.find("\tdiv2 v2") != std::string::npos);
126    EXPECT_TRUE(body_g.find("\tdiv2.64 v2") != std::string::npos);
127    EXPECT_TRUE(body_g.find("\tmod2 v2") != std::string::npos);
128    EXPECT_TRUE(body_g.find("\tmod2.64 v2") != std::string::npos);
129    EXPECT_TRUE(body_g.find("\tdivu2 v2") != std::string::npos);
130    EXPECT_TRUE(body_g.find("\tdivu2.64 v2") != std::string::npos);
131    EXPECT_TRUE(body_g.find("\tmodu2 v2") != std::string::npos);
132    EXPECT_TRUE(body_g.find("\tmodu2.64 v2") != std::string::npos);
133
134    EXPECT_TRUE(body_g.find("\tadd v1, v2") != std::string::npos);
135    EXPECT_TRUE(body_g.find("\tsub v1, v2") != std::string::npos);
136    EXPECT_TRUE(body_g.find("\tmul v1, v2") != std::string::npos);
137    EXPECT_TRUE(body_g.find("\tand v1, v2") != std::string::npos);
138    EXPECT_TRUE(body_g.find("\tor v1, v2") != std::string::npos);
139    EXPECT_TRUE(body_g.find("\txor v1, v2") != std::string::npos);
140    EXPECT_TRUE(body_g.find("\tshl v1, v2") != std::string::npos);
141    EXPECT_TRUE(body_g.find("\tshr v1, v2") != std::string::npos);
142    EXPECT_TRUE(body_g.find("\tashr v1, v2") != std::string::npos);
143    EXPECT_TRUE(body_g.find("\tdiv v1, v2") != std::string::npos);
144    EXPECT_TRUE(body_g.find("\tmod v1, v2") != std::string::npos);
145
146    EXPECT_TRUE(body_g.find("\taddi 0x1") != std::string::npos);
147    EXPECT_TRUE(body_g.find("\tsubi 0x1") != std::string::npos);
148    EXPECT_TRUE(body_g.find("\tmuli 0x1") != std::string::npos);
149    EXPECT_TRUE(body_g.find("\tandi 0x1") != std::string::npos);
150    EXPECT_TRUE(body_g.find("\tori 0x1") != std::string::npos);
151    EXPECT_TRUE(body_g.find("\txori 0x1") != std::string::npos);
152    EXPECT_TRUE(body_g.find("\tshli 0x1") != std::string::npos);
153    EXPECT_TRUE(body_g.find("\tshri 0x1") != std::string::npos);
154    EXPECT_TRUE(body_g.find("\tashri 0x1") != std::string::npos);
155    EXPECT_TRUE(body_g.find("\tdivi 0x1") != std::string::npos);
156    EXPECT_TRUE(body_g.find("\tmodi 0x1") != std::string::npos);
157
158    EXPECT_TRUE(body_g.find("\tneg") != std::string::npos);
159    EXPECT_TRUE(body_g.find("\tneg.64") != std::string::npos);
160    EXPECT_TRUE(body_g.find("\tnot") != std::string::npos);
161    EXPECT_TRUE(body_g.find("\tnot.64") != std::string::npos);
162
163    EXPECT_TRUE(body_g.find("\ti32tof64") != std::string::npos);
164    EXPECT_TRUE(body_g.find("\tu32tof64") != std::string::npos);
165    EXPECT_TRUE(body_g.find("\ti64tof64") != std::string::npos);
166    EXPECT_TRUE(body_g.find("\tu64tof64") != std::string::npos);
167    EXPECT_TRUE(body_g.find("\tf64toi32") != std::string::npos);
168    EXPECT_TRUE(body_g.find("\tf64toi64") != std::string::npos);
169    EXPECT_TRUE(body_g.find("\tf64tou32") != std::string::npos);
170    EXPECT_TRUE(body_g.find("\tf64tou64") != std::string::npos);
171    EXPECT_TRUE(body_g.find("\ti32toi64") != std::string::npos);
172    EXPECT_TRUE(body_g.find("\ti64toi32") != std::string::npos);
173    EXPECT_TRUE(body_g.find("\tu32toi64") != std::string::npos);
174
175    EXPECT_TRUE(body_g.find("\tldarr.8 v1") != std::string::npos);
176    EXPECT_TRUE(body_g.find("\tldarru.8 v2") != std::string::npos);
177    EXPECT_TRUE(body_g.find("\tldarr.16 v1") != std::string::npos);
178    EXPECT_TRUE(body_g.find("\tldarru.16 v1") != std::string::npos);
179    EXPECT_TRUE(body_g.find("\tldarr v1") != std::string::npos);
180    EXPECT_TRUE(body_g.find("\tldarr.64 v1") != std::string::npos);
181    EXPECT_TRUE(body_g.find("\tfldarr.32 v1") != std::string::npos);
182    EXPECT_TRUE(body_g.find("\tfldarr.64 v1") != std::string::npos);
183    EXPECT_TRUE(body_g.find("\tldarr.obj v1") != std::string::npos);
184
185    EXPECT_TRUE(body_g.find("\tstarr.8 v1, v2") != std::string::npos);
186    EXPECT_TRUE(body_g.find("\tstarr.16 v1, v2") != std::string::npos);
187    EXPECT_TRUE(body_g.find("\tstarr v1, v2") != std::string::npos);
188    EXPECT_TRUE(body_g.find("\tstarr.64 v1, v2") != std::string::npos);
189    EXPECT_TRUE(body_g.find("\tfstarr.32 v1, v2") != std::string::npos);
190    EXPECT_TRUE(body_g.find("\tfstarr.64 v1, v2") != std::string::npos);
191    EXPECT_TRUE(body_g.find("\tstarr.obj v1, v2") != std::string::npos);
192
193    EXPECT_TRUE(body_g.find("\tnewobj v6, A") != std::string::npos);
194
195    EXPECT_TRUE(body_g.find("\tinitobj.short A.init:()") != std::string::npos);
196
197    EXPECT_TRUE(body_g.find("\tldobj v0, A.kek") != std::string::npos);
198    EXPECT_TRUE(body_g.find("\tldobj.64 v0, A.kek") != std::string::npos);
199    EXPECT_TRUE(body_g.find("\tldobj.obj v0, A.kek") != std::string::npos);
200
201    EXPECT_TRUE(body_g.find("\tstobj v1, A.kek") != std::string::npos);
202    EXPECT_TRUE(body_g.find("\tstobj.64 v1, A.kek") != std::string::npos);
203    EXPECT_TRUE(body_g.find("\tstobj.obj v1, A.kek") != std::string::npos);
204
205    EXPECT_TRUE(body_g.find("\tldstatic A.kek") != std::string::npos);
206    EXPECT_TRUE(body_g.find("\tldstatic.64 A.kek") != std::string::npos);
207    EXPECT_TRUE(body_g.find("\tldstatic.obj A.kek") != std::string::npos);
208
209    EXPECT_TRUE(body_g.find("\tststatic A.kek") != std::string::npos);
210    EXPECT_TRUE(body_g.find("\tststatic.64 A.kek") != std::string::npos);
211    EXPECT_TRUE(body_g.find("\tststatic.obj A.kek") != std::string::npos);
212
213    EXPECT_TRUE(body_g.find("\tcheckcast A") != std::string::npos);
214    EXPECT_TRUE(body_g.find("\tisinstance A") != std::string::npos);
215}
216
217TEST(instructions_test, test_calls)
218{
219    Disassembler d {};
220
221    std::stringstream ss {};
222    d.Disassemble(std::string(DISASM_BIN_DIR) + "calls.bc");
223    d.Serialize(ss);
224
225    size_t beg_g = ss.str().find("g(u1 a0) <static> {");
226    size_t end_g = ss.str().find('}', beg_g);
227
228    ASSERT_TRUE(beg_g != std::string::npos && end_g != std::string::npos) << "function g not found";
229
230    std::string body_g =
231        ss.str().substr(beg_g + strlen("g(u1 a0) <static> {"), end_g - (beg_g + strlen("g(u1 a0) <static> {")));
232
233    EXPECT_TRUE(body_g.find("\tcall.virt.short B.Bhandler_unspec:(B), v4") != std::string::npos);
234    EXPECT_TRUE(body_g.find("\tcall.virt.short B.Bhandler_short:(B,u1), v4, v1") != std::string::npos);
235    EXPECT_TRUE(body_g.find("\tcall.virt B.Bhandler_short2:(B,u1[],i64), v4, v1, v2") != std::string::npos);
236    EXPECT_TRUE(body_g.find("\tcall.virt B.Bhandler_long:(B,i8,i16,i32), v4, v0, v1, v2") != std::string::npos);
237    EXPECT_TRUE(body_g.find("\tcall.virt.range B.Bhandler_range:(B,i8,i16,i32,i8,i16,i32), v4") != std::string::npos);
238
239    EXPECT_TRUE(body_g.find("\tcall.short handler_unspec:()") != std::string::npos);
240    EXPECT_TRUE(body_g.find("\tcall.short handler_short:(u1), v1") != std::string::npos);
241    EXPECT_TRUE(body_g.find("\tcall.short handler_short2:(u1,i64), v1, v2") != std::string::npos);
242    EXPECT_TRUE(body_g.find("\tcall handler_long:(i8,i16,i32), v0, v1, v2") != std::string::npos);
243    EXPECT_TRUE(body_g.find("\tcall handler_long2:(i8,i16,i32,f64), v0, v1, v2, v3") != std::string::npos);
244    EXPECT_TRUE(body_g.find("\tcall.range handler_range:(i8,i16,i32,i8,i16,i32), v0") != std::string::npos);
245
246    EXPECT_TRUE(body_g.find("\tinitobj.short B.Bhandler_unspec:(B)") != std::string::npos);
247    EXPECT_TRUE(body_g.find("\tinitobj.short B.Bhandler_short:(B,u1), v1") != std::string::npos);
248    EXPECT_TRUE(body_g.find("\tinitobj.short B.Bhandler_short2:(B,u1[],i64), v1, v2") != std::string::npos);
249    EXPECT_TRUE(body_g.find("\tinitobj B.Bhandler_long:(B,i8,i16,i32), v0, v1, v2") != std::string::npos);
250    EXPECT_TRUE(body_g.find("\tinitobj B.Bhandler_long2:(B,i8,i16,i32,i64), v0, v1, v2, v3") != std::string::npos);
251    EXPECT_TRUE(body_g.find("\tinitobj.range B.Bhandler_range:(B,i8,i16,i32,i8,i16,i32), v0") != std::string::npos);
252
253    EXPECT_TRUE(body_g.find("\tcall.acc.short handler_short:(u1), v0, 0x0") != std::string::npos);
254    EXPECT_TRUE(body_g.find("\tcall.acc.short handler_short2:(u1,i64), a0, 0x1") != std::string::npos);
255
256    EXPECT_TRUE(
257        ss.str().find(".function u16 long_function(i8 a0, i16 a1, i32 a2, i8 a3, i16 a4, i32 a5, i64 a6, f32 a7)") !=
258        std::string::npos);
259
260    EXPECT_TRUE(body_g.find("\tcalli.dyn.short 0x1, v0") != std::string::npos);
261}
262
263TEST(instructions_test, test_returns)
264{
265    Disassembler d {};
266
267    std::stringstream ss {};
268    d.Disassemble(std::string(DISASM_BIN_DIR) + "returns.bc");
269    d.Serialize(ss);
270
271    EXPECT_TRUE(ss.str().find("\treturn") != std::string::npos);
272    EXPECT_TRUE(ss.str().find("\treturn.64") != std::string::npos);
273    EXPECT_TRUE(ss.str().find("\treturn.obj") != std::string::npos);
274    EXPECT_TRUE(ss.str().find("\treturn.void") != std::string::npos);
275}
276
277TEST(instructions_test, test_newarr)
278{
279    Disassembler d {};
280
281    std::stringstream ss {};
282    d.Disassemble(std::string(DISASM_BIN_DIR) + "newarrs.bc");
283    d.Serialize(ss);
284
285    size_t beg_g = ss.str().find("g(u1 a0) <static> {");
286    size_t end_g = ss.str().find('}', beg_g);
287
288    ASSERT_TRUE(beg_g != std::string::npos && end_g != std::string::npos) << "function g not found";
289
290    std::string body_g = ss.str().substr(beg_g + strlen("g() {"), end_g - (beg_g + strlen("g() {")));
291
292    EXPECT_TRUE(body_g.find("\tnewarr v0, a0, u1[]") != std::string::npos);
293    EXPECT_TRUE(body_g.find("\tnewarr v0, a0, i8[]") != std::string::npos);
294    EXPECT_TRUE(body_g.find("\tnewarr v0, a0, u8[]") != std::string::npos);
295    EXPECT_TRUE(body_g.find("\tnewarr v0, a0, i16[]") != std::string::npos);
296    EXPECT_TRUE(body_g.find("\tnewarr v0, a0, u16[]") != std::string::npos);
297    EXPECT_TRUE(body_g.find("\tnewarr v0, a0, i32[]") != std::string::npos);
298    EXPECT_TRUE(body_g.find("\tnewarr v0, a0, u32[]") != std::string::npos);
299    EXPECT_TRUE(body_g.find("\tnewarr v0, a0, f32[]") != std::string::npos);
300    EXPECT_TRUE(body_g.find("\tnewarr v0, a0, f64[]") != std::string::npos);
301    EXPECT_TRUE(body_g.find("\tnewarr v0, a0, i64[]") != std::string::npos);
302    EXPECT_TRUE(body_g.find("\tnewarr v0, a0, u64[]") != std::string::npos);
303}
304
305TEST(instructions_test, test_debug_info)
306{
307    Disassembler d;
308
309    std::stringstream ss;
310    d.Disassemble(std::string(DISASM_BIN_DIR) + "instructions.bc");
311    d.CollectInfo();
312    d.Serialize(ss, true, true);
313
314    size_t beg_g = ss.str().find("g() <static> {");
315    size_t end_g = ss.str().find('}', beg_g);
316
317    ASSERT_TRUE(beg_g != std::string::npos && end_g != std::string::npos) << "function g not found";
318
319    std::string body_g = ss.str().substr(beg_g + strlen("g() {"), end_g - (beg_g + strlen("g() {")));
320
321    ASSERT_NE(body_g.find("#   LINE_NUMBER_TABLE:"), std::string::npos);
322    ASSERT_NE(body_g.find("#\tline 26: 0\n"), std::string::npos);
323
324    size_t code_start = body_g.find("#   CODE:\n");
325    ASSERT_NE(code_start, std::string::npos) << "Code section in function g not found";
326    size_t code_end = body_g.find("\n\n");  // First gap in function body is code section end
327    ASSERT_NE(code_end, std::string::npos) << "Gap after code section in function g not found";
328    ASSERT_LT(code_start, code_end);
329    std::string instructions =
330        body_g.substr(code_start + strlen("#   CODE:\n"), code_end + 1 - (code_start + strlen("#   CODE:\n")));
331    size_t instruction_count = std::count(instructions.begin(), instructions.end(), '\n');
332
333    const ProgInfo &prog_info = d.GetProgInfo();
334    auto g_it = prog_info.methods_info.find("g:()");
335    ASSERT_NE(g_it, prog_info.methods_info.end());
336    // In case of pandasm the table should contain entry on each instruction
337    ASSERT_EQ(g_it->second.line_number_table.size(), instruction_count);
338
339    // There should be no local variables for panda assembler
340    ASSERT_EQ(body_g.find("#   LOCAL_VARIABLE_TABLE:"), std::string::npos);
341}
342
343#undef DISASM_BIN_DIR
344