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 <regex>
18 #include <string>
19
20 #include <gtest/gtest.h>
21 #include "disassembler.h"
22 #include "assembly-parser.h"
23
ExtractFuncBody(const std::string & text,const std::string & header)24 static inline std::string ExtractFuncBody(const std::string &text, const std::string &header)
25 {
26 auto beg = text.find(header);
27 auto end = text.find('}', beg);
28
29 ASSERT(beg != std::string::npos);
30 ASSERT(end != std::string::npos);
31
32 return text.substr(beg + header.length(), end - (beg + header.length()));
33 }
34
TEST(TestDebugInfo,TestDebugInfo)35 TEST(TestDebugInfo, TestDebugInfo)
36 {
37 auto program = panda::pandasm::Parser().Parse(R"(
38 .record A {
39 u1 fld
40 }
41
42 .function A A.init() {
43 newobj v0, A
44 lda.obj v0
45
46 return.obj
47 }
48
49 .function u1 g() {
50 mov v0, v1
51 mov.64 v2, v3
52 mov.obj v4, v5
53
54 movi v0, -1
55 movi.64 v0, 2
56 fmovi.64 v0, 3.01
57
58 lda v1
59 lda.64 v0
60 lda.obj v1
61 }
62 )");
63 ASSERT(program);
64 auto pf = panda::pandasm::AsmEmitter::Emit(program.Value());
65 ASSERT(pf);
66
67 panda::disasm::Disassembler d {};
68 std::stringstream ss {};
69
70 d.Disassemble(pf);
71 d.CollectInfo();
72 d.Serialize(ss, true, true);
73
74 std::string bodyG = ExtractFuncBody(ss.str(), "g() <static> {");
75
76 ASSERT_NE(bodyG.find("# LINE_NUMBER_TABLE:"), std::string::npos);
77 ASSERT_NE(bodyG.find("#\tline 14: 0\n"), std::string::npos);
78
79 size_t codeStart = bodyG.find("# CODE:\n");
80 ASSERT_NE(codeStart, std::string::npos) << "Code section in function g not found";
81 size_t codeEnd = bodyG.find("\n\n"); // First gap in function body is code section end
82 ASSERT_NE(codeEnd, std::string::npos) << "Gap after code section in function g not found";
83 ASSERT_LT(codeStart, codeEnd);
84 std::string instructions =
85 bodyG.substr(codeStart + strlen("# CODE:\n"), codeEnd + 1 - (codeStart + strlen("# CODE:\n")));
86
87 std::regex const instRegex("# offset: ");
88 std::ptrdiff_t const instructionCount(std::distance(
89 std::sregex_iterator(instructions.begin(), instructions.end(), instRegex), std::sregex_iterator()));
90
91 const panda::disasm::ProgInfo &progInfo = d.GetProgInfo();
92 auto gIt = progInfo.methodsInfo.find("g:()");
93 ASSERT_NE(gIt, progInfo.methodsInfo.end());
94 // In case of pandasm the table should contain entry on each instruction
95 ASSERT_EQ(gIt->second.lineNumberTable.size(), instructionCount);
96
97 // There should be no local variables for panda assembler
98 ASSERT_EQ(bodyG.find("# LOCAL_VARIABLE_TABLE:"), std::string::npos);
99 }
100