• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "helpers/helpers_runtime.h"
20 #include "libabckit/include/c/abckit.h"
21 #include "logger.h"
22 
23 #include <gtest/gtest.h>
24 
25 // NOLINTBEGIN(readability-magic-numbers)
26 
27 namespace libabckit::test {
28 
29 class LibAbcKitBasicBlocksDynTest : public ::testing::Test {};
30 
31 namespace {
32 
33 auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
34 auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
35 auto g_implM = AbckitGetModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
36 auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
37 auto g_statG = AbckitGetIsaApiStaticImpl(ABCKIT_VERSION_RELEASE_1_0_0);
38 auto g_dynG = AbckitGetIsaApiDynamicImpl(ABCKIT_VERSION_RELEASE_1_0_0);
39 
40 }  // namespace
41 
VerifyBbSchem1(AbckitGraph * graph)42 static void VerifyBbSchem1(AbckitGraph *graph)
43 {
44     std::vector<helpers::BBSchema<AbckitIsaApiDynamicOpcode>> bbSchemas = {
45         {{},
46          {1},
47          {{0, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
48           {1, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
49           {2, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
50           {3, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
51           {5, ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT, {}},
52           {9, ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT, {}},
53           {10, ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT, {}}}},
54         {{0},
55          {3, 2},
56          {{6, ABCKIT_ISA_API_DYNAMIC_OPCODE_GREATER, {5, 3}}, {8, ABCKIT_ISA_API_DYNAMIC_OPCODE_IF, {6, 9}}}},
57         {{1},
58          {4},
59          {{11, ABCKIT_ISA_API_DYNAMIC_OPCODE_LESS, {10, 3}},
60           {12, ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, {}},
61           {13, ABCKIT_ISA_API_DYNAMIC_OPCODE_ADD2, {10, 3}},
62           {14, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, {12, 13}}}},
63         {{1},
64          {4},
65          {{15, ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, {}},
66           {16, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, {15, 3}}}},
67         {{2, 3}, {5}, {{20, ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURNUNDEFINED, {}}}},
68         {{4}, {}, {}}};
69     helpers::VerifyGraph(graph, bbSchemas);
70 }
71 
72 // Test: test-kind=api, api=GraphApiImpl::gRunPassRemoveUnreachableBlocks, abc-kind=ArkTS1, category=positive,
73 // extension=c
TEST_F(LibAbcKitBasicBlocksDynTest,GrunPassRemoveUnreachableBlocks_1)74 TEST_F(LibAbcKitBasicBlocksDynTest, GrunPassRemoveUnreachableBlocks_1)
75 {
76     auto output = helpers::ExecuteDynamicAbc(
77         ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block_dynamic.abc", "graph_basic_block_dynamic");
78     EXPECT_TRUE(helpers::Match(output, "31\n51\n9\n"));
79 
80     helpers::TransformMethod(
81         ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block_dynamic.abc",
82         ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block_dynamic_modified.abc", "test",
83         [&](AbckitFile * /*file*/, AbckitCoreFunction * /*method*/, AbckitGraph *graph) {
84             auto *bb2 = g_implG->gGetBasicBlock(graph, 2);
85             g_implG->iRemove(g_implG->bbGetLastInst(bb2));
86             g_implG->bbDisconnectSuccBlock(bb2, 0x0);
87             g_implG->gRunPassRemoveUnreachableBlocks(graph);
88             ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
89         },
90         [&](AbckitGraph *graph) { VerifyBbSchem1(graph); });
91 
92     output =
93         helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block_dynamic_modified.abc",
94                                    "graph_basic_block_dynamic");
95     EXPECT_TRUE(helpers::Match(output, "31\n41\n9\n"));
96 }
97 
VerifyBbSchem2(AbckitGraph * graph)98 static void VerifyBbSchem2(AbckitGraph *graph)
99 {
100     std::vector<helpers::BBSchema<AbckitIsaApiDynamicOpcode>> bbSchemas = {
101         {{},
102          {1},
103          {{0, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
104           {1, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
105           {2, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
106           {3, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
107           {4, ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT, {}},
108           {8, ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT, {}},
109           {9, ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT, {}},
110           {12, ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT, {}}}},
111         {{0},
112          {3, 2},
113          {{5, ABCKIT_ISA_API_DYNAMIC_OPCODE_GREATER, {4, 3}}, {7, ABCKIT_ISA_API_DYNAMIC_OPCODE_IF, {5, 8}}}},
114         {{1},
115          {4},
116          {{10, ABCKIT_ISA_API_DYNAMIC_OPCODE_LESS, {9, 3}},
117           {11, ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, {}},
118           {13, ABCKIT_ISA_API_DYNAMIC_OPCODE_ADD2, {12, 3}},
119           {14, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, {11, 13}}}},
120         {{1},
121          {4},
122          {{15, ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, {}},
123           {16, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, {15, 3}}}},
124         {{2, 3}, {5}, {{20, ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURNUNDEFINED, {}}}},
125         {{4}, {}, {}}};
126     helpers::VerifyGraph(graph, bbSchemas);
127 }
128 
129 // Test: test-kind=api, api=GraphApiImpl::gRunPassRemoveUnreachableBlocks, abc-kind=ArkTS1, category=positive,
130 // extension=c
TEST_F(LibAbcKitBasicBlocksDynTest,GrunPassRemoveUnreachableBlocks_2)131 TEST_F(LibAbcKitBasicBlocksDynTest, GrunPassRemoveUnreachableBlocks_2)
132 {
133     auto output = helpers::ExecuteDynamicAbc(
134         ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block_dynamic.abc", "graph_basic_block_dynamic");
135     EXPECT_TRUE(helpers::Match(output, "31\n51\n9\n"));
136 
137     helpers::TransformMethod(
138         ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block_dynamic.abc",
139         ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block_dynamic_modified.abc", "test",
140         [&](AbckitFile * /*file*/, AbckitCoreFunction * /*method*/, AbckitGraph *graph) {
141             auto *bb2 = g_implG->gGetBasicBlock(graph, 2);
142             g_implG->iRemove(g_implG->bbGetLastInst(bb2));
143             g_implG->bbDisconnectSuccBlock(bb2, 0x1);
144             g_implG->gRunPassRemoveUnreachableBlocks(graph);
145             ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
146         },
147         [&](AbckitGraph *graph) { VerifyBbSchem2(graph); });
148 
149     output =
150         helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block_dynamic_modified.abc",
151                                    "graph_basic_block_dynamic");
152     EXPECT_TRUE(helpers::Match(output, "41\n51\n9\n"));
153 }
154 
VerifyBbSchem3(AbckitGraph * graph)155 static void VerifyBbSchem3(AbckitGraph *graph)
156 {
157     std::vector<helpers::BBSchema<AbckitIsaApiDynamicOpcode>> bbSchemas = {
158         {{},
159          {1},
160          {{0, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
161           {1, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
162           {2, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
163           {3, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
164           {4, ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT, {}},
165           {6, ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT, {}},
166           {10, ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT, {}},
167           {15, ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT, {}}}},
168         {{0},
169          {3, 2},
170          {{5, ABCKIT_ISA_API_DYNAMIC_OPCODE_GREATER, {4, 3}},
171           {7, ABCKIT_ISA_API_DYNAMIC_OPCODE_LESS, {6, 3}},
172           {9, ABCKIT_ISA_API_DYNAMIC_OPCODE_IF, {7, 10}}}},
173         {{1},
174          {4},
175          {{11, ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, {}},
176           {12, ABCKIT_ISA_API_DYNAMIC_OPCODE_ADD2, {6, 3}},
177           {13, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, {11, 12}}}},
178         {{1},
179          {4},
180          {{14, ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, {}},
181           {16, ABCKIT_ISA_API_DYNAMIC_OPCODE_ADD2, {15, 3}},
182           {17, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, {14, 16}}}},
183         {{2, 3}, {5}, {{21, ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURNUNDEFINED, {}}}},
184         {{4}, {}, {}}};
185     helpers::VerifyGraph(graph, bbSchemas);
186 }
187 
188 // Test: test-kind=api, api=GraphApiImpl::gRunPassRemoveUnreachableBlocks, abc-kind=ArkTS1, category=positive,
189 // extension=c
TEST_F(LibAbcKitBasicBlocksDynTest,GrunPassRemoveUnreachableBlocks_3)190 TEST_F(LibAbcKitBasicBlocksDynTest, GrunPassRemoveUnreachableBlocks_3)
191 {
192     auto output = helpers::ExecuteDynamicAbc(
193         ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block_dynamic.abc", "graph_basic_block_dynamic");
194     EXPECT_TRUE(helpers::Match(output, "31\n51\n9\n"));
195 
196     helpers::TransformMethod(
197         ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block_dynamic.abc",
198         ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block_dynamic_modified.abc", "test",
199         [&](AbckitFile * /*file*/, AbckitCoreFunction * /*method*/, AbckitGraph *graph) {
200             auto *bb0 = g_implG->gGetBasicBlock(graph, 0);
201             g_implG->iRemove(g_implG->bbGetLastInst(bb0));
202             g_implG->bbDisconnectSuccBlock(bb0, 0x0);
203             g_implG->gRunPassRemoveUnreachableBlocks(graph);
204             ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
205         },
206         [&](AbckitGraph *graph) { VerifyBbSchem3(graph); });
207 
208     output =
209         helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block_dynamic_modified.abc",
210                                    "graph_basic_block_dynamic");
211     EXPECT_TRUE(helpers::Match(output, "31\n51\n29\n"));
212 }
213 
VerifyGraphStart(AbckitFile * file)214 static void VerifyGraphStart(AbckitFile *file)
215 {
216     // Find transformed method
217     AbckitCoreFunction *testMethod = helpers::FindMethodByName(file, "foo");
218     ASSERT_NE(testMethod, nullptr);
219 
220     // Get graph
221     AbckitGraph *graph = g_implI->createGraphFromFunction(testMethod);
222     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
223 
224     AbckitBasicBlock *startBB = g_implG->gGetStartBasicBlock(graph);
225     ASSERT_NE(startBB, nullptr);
226 
227     // Verify bb predecessors
228     ASSERT_EQ(helpers::BBgetPredBlocks(startBB).size(), 0);
229 
230     // Verify bb successors
231     ASSERT_EQ(helpers::BBgetSuccBlocks(startBB).size(), 1);
232 
233     // Verify instructions
234     auto *inst = g_implG->bbGetFirstInst(startBB);
235 
236     ASSERT_EQ(g_dynG->iGetOpcode(inst), ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER);
237     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
238     ASSERT_EQ(g_implG->iGetId(inst), 0);
239     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
240 
241     g_impl->destroyGraph(graph);
242 }
243 
244 // Test: test-kind=api, api=GraphApiImpl::gGetStartBasicBlock, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitBasicBlocksDynTest,GgetStartBasicBlockValid)245 TEST_F(LibAbcKitBasicBlocksDynTest, GgetStartBasicBlockValid)
246 {
247     constexpr auto INPUT_PATH = ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block_simple.abc";
248     AbckitFile *file = g_impl->openAbc(INPUT_PATH, strlen(INPUT_PATH));
249     LIBABCKIT_LOG(DEBUG) << "LibAbcKitBasicBlocksDynTest: " << INPUT_PATH << std::endl;
250 
251     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
252 
253     VerifyGraphStart(file);
254 
255     g_impl->closeFile(file);
256     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
257 }
258 
VerifyGraphEnd(AbckitFile * file)259 static void VerifyGraphEnd(AbckitFile *file)
260 {
261     // Find transformed method
262     AbckitCoreFunction *testMethod = helpers::FindMethodByName(file, "foo");
263     ASSERT_NE(testMethod, nullptr);
264 
265     // Get graph
266     AbckitGraph *graph = g_implI->createGraphFromFunction(testMethod);
267     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
268 
269     AbckitBasicBlock *endBB = g_implG->gGetEndBasicBlock(graph);
270     ASSERT_NE(endBB, nullptr);
271 
272     // Verify bb predecessors
273     ASSERT_EQ(helpers::BBgetPredBlocks(endBB).size(), 1);
274 
275     // Verify bb successors
276     ASSERT_EQ(helpers::BBgetSuccBlocks(endBB).size(), 0);
277 
278     // Verify instructions
279     ASSERT_EQ(g_implG->bbGetFirstInst(endBB), nullptr);
280 
281     g_impl->destroyGraph(graph);
282 }
283 
284 // Test: test-kind=api, api=GraphApiImpl::gGetEndBasicBlock, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitBasicBlocksDynTest,GgetEndBasicBlockValid)285 TEST_F(LibAbcKitBasicBlocksDynTest, GgetEndBasicBlockValid)
286 {
287     constexpr auto INPUT_PATH = ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block_simple.abc";
288     AbckitFile *file = g_impl->openAbc(INPUT_PATH, strlen(INPUT_PATH));
289     LIBABCKIT_LOG(DEBUG) << "LibAbcKitBasicBlocksDynTest: " << INPUT_PATH << std::endl;
290     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
291 
292     VerifyGraphEnd(file);
293 
294     g_impl->closeFile(file);
295     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
296 }
297 
VerifyGraphVisitBlocks(AbckitFile * file)298 static void VerifyGraphVisitBlocks(AbckitFile *file)
299 {
300     // Find transformed method
301     AbckitCoreFunction *testMethod = helpers::FindMethodByName(file, "foo");
302     ASSERT_NE(testMethod, nullptr);
303 
304     // Get graph
305     AbckitGraph *graph = g_implI->createGraphFromFunction(testMethod);
306     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
307 
308     std::vector<AbckitBasicBlock *> bbs;
309 
310     // Collect basic blocks
311     g_implG->gVisitBlocksRpo(graph, &bbs, [](AbckitBasicBlock *bb, void *data) {
312         reinterpret_cast<std::vector<AbckitBasicBlock *> *>(data)->emplace_back(bb);
313         return true;
314     });
315 
316     ASSERT_EQ(bbs.size(), 3U);
317 
318     auto *startBB = bbs[0];
319 
320     // Verify bb predecessors
321     ASSERT_EQ(helpers::BBgetPredBlocks(startBB).size(), 0);
322 
323     // Verify bb successors
324     ASSERT_EQ(helpers::BBgetSuccBlocks(startBB).size(), 1);
325 
326     // Verify instructions
327     auto *inst = g_implG->bbGetFirstInst(startBB);
328 
329     ASSERT_EQ(g_dynG->iGetOpcode(inst), ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER);
330     ASSERT_EQ(g_implG->iGetId(inst), 0);
331 
332     startBB = bbs[1];
333 
334     // Verify bb predecessors
335     ASSERT_EQ(helpers::BBgetPredBlocks(startBB).size(), 1);
336 
337     // Verify bb successors
338     ASSERT_EQ(helpers::BBgetSuccBlocks(startBB).size(), 1);
339 
340     // Verify instructions
341     inst = g_implG->bbGetFirstInst(startBB);
342 
343     ASSERT_EQ(g_dynG->iGetOpcode(inst), ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURN);
344     ASSERT_EQ(g_implG->iGetId(inst), 4U);
345 
346     startBB = bbs[2U];
347     ASSERT_NE(startBB, nullptr);
348 
349     // Verify bb predecessors
350     ASSERT_EQ(helpers::BBgetPredBlocks(startBB).size(), 1);
351 
352     // Verify bb successors
353     ASSERT_EQ(helpers::BBgetSuccBlocks(startBB).size(), 0);
354 
355     // Verify instructions
356     inst = g_implG->bbGetFirstInst(startBB);
357     ASSERT_EQ(inst, nullptr);
358 
359     g_impl->destroyGraph(graph);
360 }
361 
362 // Test: test-kind=api, api=GraphApiImpl::gVisitBlocksRpo, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitBasicBlocksDynTest,GvisitBlocksRPO)363 TEST_F(LibAbcKitBasicBlocksDynTest, GvisitBlocksRPO)
364 {
365     constexpr auto INPUT_PATH = ABCKIT_ABC_DIR "ut/ir_core/graph_basic_block/graph_basic_block_simple.abc";
366     AbckitFile *file = g_impl->openAbc(INPUT_PATH, strlen(INPUT_PATH));
367     LIBABCKIT_LOG(DEBUG) << "LibAbcKitBasicBlocksDynTest: " << INPUT_PATH << std::endl;
368 
369     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
370 
371     VerifyGraphVisitBlocks(file);
372 
373     g_impl->closeFile(file);
374     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
375 }
376 
377 }  // namespace libabckit::test
378 
379 // NOLINTEND(readability-magic-numbers)
380