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