1 /**
2 * Copyright (c) 2024 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 "libabckit/include/c/metadata_core.h"
17 #include "libabckit/include/c/ir_core.h"
18 #include "helpers/helpers.h"
19 #include "libabckit/include/c/abckit.h"
20 #include "logger.h"
21
22 #include <gtest/gtest.h>
23
24 namespace libabckit::test {
25
26 class LibAbcKitBasicBlocksTest : public ::testing::Test {};
27
28 static auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
29 static auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
30 static auto g_implM = AbckitGetModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
31 static auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
32 static auto g_statG = AbckitGetIsaApiStaticImpl(ABCKIT_VERSION_RELEASE_1_0_0);
33
VerifyGraphStart(AbckitFile * file)34 static void VerifyGraphStart(AbckitFile *file)
35 {
36 // Find transformed method
37 AbckitCoreFunction *testMethod = helpers::FindMethodByName(file, "foo");
38 ASSERT_NE(testMethod, nullptr);
39
40 // Get graph
41 AbckitGraph *graph = g_implI->createGraphFromFunction(testMethod);
42 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
43
44 AbckitBasicBlock *startBB = g_implG->gGetStartBasicBlock(graph);
45 ASSERT_NE(startBB, nullptr);
46
47 // Verify bb predecessors
48 ASSERT_EQ(helpers::BBgetPredBlocks(startBB).size(), 0);
49
50 // Verify bb successors
51 ASSERT_EQ(helpers::BBgetSuccBlocks(startBB).size(), 1);
52
53 // Verify instructions
54 auto *inst = g_implG->bbGetFirstInst(startBB);
55
56 ASSERT_EQ(g_statG->iGetOpcode(inst), ABCKIT_ISA_API_STATIC_OPCODE_PARAMETER);
57 ASSERT_EQ(g_implG->iGetId(inst), 0);
58
59 g_impl->destroyGraph(graph);
60 }
61
VerifyGraphEnd(AbckitFile * file)62 static void VerifyGraphEnd(AbckitFile *file)
63 {
64 // Find transformed method
65 AbckitCoreFunction *testMethod = helpers::FindMethodByName(file, "foo");
66 ASSERT_NE(testMethod, nullptr);
67
68 // Get graph
69 AbckitGraph *graph = g_implI->createGraphFromFunction(testMethod);
70 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
71
72 AbckitBasicBlock *endBB = g_implG->gGetEndBasicBlock(graph);
73 ASSERT_NE(endBB, nullptr);
74
75 // Verify bb predecessors
76 ASSERT_EQ(helpers::BBgetPredBlocks(endBB).size(), 1);
77
78 // Verify bb successors
79 ASSERT_EQ(helpers::BBgetSuccBlocks(endBB).size(), 0);
80
81 // Verify instructions
82 ASSERT_EQ(g_implG->bbGetFirstInst(endBB), nullptr);
83
84 g_impl->destroyGraph(graph);
85 }
86
VerifyGraphVisitBlocks(AbckitFile * file)87 static void VerifyGraphVisitBlocks(AbckitFile *file)
88 {
89 // Find transformed method
90 AbckitCoreFunction *testMethod = helpers::FindMethodByName(file, "foo");
91 ASSERT_NE(testMethod, nullptr);
92
93 // Get graph
94 AbckitGraph *graph = g_implI->createGraphFromFunction(testMethod);
95 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
96
97 std::vector<AbckitBasicBlock *> bbs;
98
99 // Collect basic blocks
100 g_implG->gVisitBlocksRpo(graph, &bbs, [](AbckitBasicBlock *bb, void *data) {
101 reinterpret_cast<std::vector<AbckitBasicBlock *> *>(data)->emplace_back(bb);
102 return true;
103 });
104
105 ASSERT_EQ(bbs.size(), 3U);
106
107 auto *startBB = bbs[0];
108
109 // Verify bb predecessors
110 ASSERT_EQ(helpers::BBgetPredBlocks(startBB).size(), 0);
111
112 // Verify bb successors
113 ASSERT_EQ(helpers::BBgetSuccBlocks(startBB).size(), 1);
114
115 // Verify instructions
116 auto *inst = g_implG->bbGetFirstInst(startBB);
117
118 ASSERT_EQ(g_statG->iGetOpcode(inst), ABCKIT_ISA_API_STATIC_OPCODE_PARAMETER);
119 ASSERT_EQ(g_implG->iGetId(inst), 0);
120
121 startBB = bbs[1];
122
123 // Verify bb predecessors
124 ASSERT_EQ(helpers::BBgetPredBlocks(startBB).size(), 1);
125
126 // Verify bb successors
127 ASSERT_EQ(helpers::BBgetSuccBlocks(startBB).size(), 1);
128
129 // Verify instructions
130 inst = g_implG->bbGetFirstInst(startBB);
131
132 ASSERT_EQ(g_statG->iGetOpcode(inst), ABCKIT_ISA_API_STATIC_OPCODE_RETURN);
133 ASSERT_EQ(g_implG->iGetId(inst), 2U);
134
135 startBB = bbs[2U];
136 ASSERT_NE(startBB, nullptr);
137
138 // Verify bb predecessors
139 ASSERT_EQ(helpers::BBgetPredBlocks(startBB).size(), 1);
140
141 // Verify bb successors
142 ASSERT_EQ(helpers::BBgetSuccBlocks(startBB).size(), 0);
143
144 // Verify instructions
145 inst = g_implG->bbGetFirstInst(startBB);
146 ASSERT_EQ(inst, nullptr);
147
148 g_impl->destroyGraph(graph);
149 }
150
151 // Test: test-kind=api, api=GraphApiImpl::gGetStartBasicBlock, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(LibAbcKitBasicBlocksTest,GgetStartBasicBlockValid)152 TEST_F(LibAbcKitBasicBlocksTest, GgetStartBasicBlockValid)
153 {
154 constexpr auto INPUT_PATH = ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block.abc";
155 AbckitFile *file = g_impl->openAbc(INPUT_PATH, strlen(INPUT_PATH));
156 LIBABCKIT_LOG(DEBUG) << "LibAbcKitTestStaticGgetStartBasicBlock: " << INPUT_PATH << std::endl;
157
158 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
159
160 VerifyGraphStart(file);
161
162 g_impl->closeFile(file);
163 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
164 }
165
166 // Test: test-kind=api, api=GraphApiImpl::gGetEndBasicBlock, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(LibAbcKitBasicBlocksTest,GgetEndBasicBlockValid)167 TEST_F(LibAbcKitBasicBlocksTest, GgetEndBasicBlockValid)
168 {
169 constexpr auto INPUT_PATH = ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block.abc";
170 AbckitFile *file = g_impl->openAbc(INPUT_PATH, strlen(INPUT_PATH));
171 LIBABCKIT_LOG(DEBUG) << "LibAbcKitTestStaticGgetEndBasicBlock: " << INPUT_PATH << std::endl;
172 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
173
174 VerifyGraphEnd(file);
175
176 g_impl->closeFile(file);
177 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
178 }
179
180 // Test: test-kind=api, api=GraphApiImpl::gVisitBlocksRpo, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(LibAbcKitBasicBlocksTest,GvisitBlocksRPO)181 TEST_F(LibAbcKitBasicBlocksTest, GvisitBlocksRPO)
182 {
183 constexpr auto INPUT_PATH = ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block.abc";
184 AbckitFile *file = g_impl->openAbc(INPUT_PATH, strlen(INPUT_PATH));
185 LIBABCKIT_LOG(DEBUG) << "LibAbcKitTestStaticGgetEndBasicBlock: " << INPUT_PATH << std::endl;
186
187 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
188
189 VerifyGraphVisitBlocks(file);
190
191 g_impl->closeFile(file);
192 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
193 }
194
195 } // namespace libabckit::test
196