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 <gtest/gtest.h>
17
18 #include "libabckit/include/c/abckit.h"
19 #include "libabckit/include/c/metadata_core.h"
20 #include "libabckit/include/c/ir_core.h"
21
22 #include "helpers/helpers.h"
23 #include "helpers/helpers_runtime.h"
24
25 namespace libabckit::test {
26
27 class LibAbcKitInternalTest : public ::testing::Test {};
28
29 static auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
30 static auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
31 static auto g_implM = AbckitGetModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
32 static auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
33 static auto g_dynG = AbckitGetIsaApiDynamicImpl(ABCKIT_VERSION_RELEASE_1_0_0);
34
35 struct UserData {
36 AbckitString *print = nullptr;
37 AbckitString *date = nullptr;
38 AbckitString *getTime = nullptr;
39 AbckitString *str = nullptr;
40 AbckitString *consume = nullptr;
41 };
42
43 struct ICSlotDescription {
44 AbckitIsaApiDynamicOpcode op = AbckitIsaApiDynamicOpcode::ABCKIT_ISA_API_DYNAMIC_OPCODE_INVALID;
45 int32_t icSlot = -1;
46 };
47
CheckICSlots(AbckitBasicBlock * bb,std::vector<ICSlotDescription> icSlotDescr)48 static void CheckICSlots(AbckitBasicBlock *bb, std::vector<ICSlotDescription> icSlotDescr)
49 {
50 ASSERT_EQ(g_implG->bbGetNumberOfInstructions(bb), icSlotDescr.size());
51
52 uint32_t counter = 0;
53 for (AbckitInst *inst = g_implG->bbGetFirstInst(bb); inst != nullptr; inst = g_implG->iGetNext(inst), ++counter) {
54 if (icSlotDescr[counter].icSlot == -1) {
55 continue;
56 }
57
58 ASSERT_EQ(g_dynG->iGetOpcode(inst), icSlotDescr[counter].op);
59 ASSERT_NE(g_implG->iGetImmediateCount(inst), 0);
60 ASSERT_EQ(g_implG->iGetImmediate(inst, 0), icSlotDescr[counter].icSlot);
61 }
62 }
63
TransformIrEpilog(AbckitGraph * graph,UserData * userData,AbckitInst * time,AbckitInst * callInst)64 static void TransformIrEpilog(AbckitGraph *graph, UserData *userData, AbckitInst *time, AbckitInst *callInst)
65 {
66 auto *dateClass2 = g_dynG->iCreateTryldglobalbyname(graph, userData->date);
67 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
68 g_implG->iInsertAfter(dateClass2, callInst);
69 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
70 auto *dateObj2 = g_dynG->iCreateNewobjrange(graph, 1, dateClass2);
71 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
72 g_implG->iInsertAfter(dateObj2, dateClass2);
73 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
74 auto *getTime2 = g_dynG->iCreateLdobjbyname(graph, dateObj2, userData->getTime);
75 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
76 g_implG->iInsertAfter(getTime2, dateObj2);
77 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
78 auto *time2 = g_dynG->iCreateCallthis0(graph, getTime2, dateObj2);
79 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
80 g_implG->iInsertAfter(time2, getTime2);
81 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
82 auto *consume = g_dynG->iCreateLoadString(graph, userData->consume);
83 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
84 g_implG->iInsertAfter(consume, time2);
85 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
86
87 auto *print2 = g_dynG->iCreateTryldglobalbyname(graph, userData->print);
88 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
89 g_implG->iInsertAfter(print2, consume);
90 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
91 auto *callArg2 = g_dynG->iCreateCallarg1(graph, print2, consume);
92 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
93 g_implG->iInsertAfter(callArg2, print2);
94 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
95 auto *sub = g_dynG->iCreateSub2(graph, time, time2);
96 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
97 g_implG->iInsertAfter(sub, callArg2);
98 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
99
100 auto *print3 = g_dynG->iCreateTryldglobalbyname(graph, userData->print);
101 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
102 g_implG->iInsertAfter(print3, sub);
103 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
104 auto *callArg3 = g_dynG->iCreateCallarg1(graph, print3, sub);
105 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
106 g_implG->iInsertAfter(callArg3, print3);
107 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
108 }
109
TransformIr(AbckitGraph * graph,UserData * userData)110 static void TransformIr(AbckitGraph *graph, UserData *userData)
111 {
112 AbckitBasicBlock *startBB = g_implG->gGetStartBasicBlock(graph);
113 std::vector<AbckitBasicBlock *> succBBs = helpers::BBgetSuccBlocks(startBB);
114 auto *bb = succBBs[0];
115 auto *callInst = helpers::FindFirstInst(graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1);
116
117 // Prolog
118 auto *str = g_dynG->iCreateLoadString(graph, userData->str);
119 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
120 g_implG->bbAddInstFront(bb, str);
121 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
122 auto *print = g_dynG->iCreateTryldglobalbyname(graph, userData->print);
123 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
124 g_implG->iInsertAfter(print, str);
125 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
126 auto *callArg = g_dynG->iCreateCallarg1(graph, print, str);
127 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
128 g_implG->iInsertAfter(callArg, print);
129 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
130
131 auto *dateClass = g_dynG->iCreateTryldglobalbyname(graph, userData->date);
132 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
133 g_implG->iInsertAfter(dateClass, callArg);
134 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
135 auto *dateObj = g_dynG->iCreateNewobjrange(graph, 1, dateClass);
136 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
137 g_implG->iInsertAfter(dateObj, dateClass);
138 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
139 auto *getTime = g_dynG->iCreateLdobjbyname(graph, dateObj, userData->getTime);
140 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
141 g_implG->iInsertAfter(getTime, dateObj);
142 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
143 auto *time = g_dynG->iCreateCallthis0(graph, getTime, dateObj);
144 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
145 g_implG->iInsertAfter(time, getTime);
146 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
147
148 TransformIrEpilog(graph, userData, time, callInst);
149 }
150
151 // Test: test-kind=internal, abc-kind=ArkTS1, category=internal, extension=c
TEST_F(LibAbcKitInternalTest,LibAbcKitTestICSlotAllocator)152 TEST_F(LibAbcKitInternalTest, LibAbcKitTestICSlotAllocator)
153 {
154 auto output =
155 helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "internal/ICSlotAllocator/ICSlotAllocator.abc", "ICSlotAllocator");
156 EXPECT_TRUE(helpers::Match(output, "abckit\n"));
157
158 helpers::TransformMethod(
159 ABCKIT_ABC_DIR "internal/ICSlotAllocator/ICSlotAllocator.abc",
160 ABCKIT_ABC_DIR "internal/ICSlotAllocator/ICSlotAllocator_modified.abc", "handle",
161 [](AbckitFile *file, AbckitCoreFunction *, AbckitGraph *graph) {
162 UserData data = {};
163 data.print = g_implM->createString(file, "print", strlen("print"));
164 data.date = g_implM->createString(file, "Date", strlen("Date"));
165 data.getTime = g_implM->createString(file, "getTime", strlen("getTime"));
166 data.str = g_implM->createString(file, "file: src/MyClass, function: MyClass.handle",
167 strlen("file: src/MyClass, function: MyClass.handle"));
168 data.consume = g_implM->createString(file, "Ellapsed time:", strlen("Ellapsed time:"));
169 TransformIr(graph, &data);
170 },
171 [](AbckitGraph *graph) {
172 AbckitBasicBlock *startBB = g_implG->gGetStartBasicBlock(graph);
173 // NOLINTBEGIN(readability-magic-numbers)
174 CheckICSlots(g_implG->bbGetTrueBranch(startBB), {{ABCKIT_ISA_API_DYNAMIC_OPCODE_LOADSTRING, -1},
175 {ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, 0XD},
176 {ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, 0X0},
177 {ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, 0XE},
178 {ABCKIT_ISA_API_DYNAMIC_OPCODE_NEWOBJRANGE, 0XF},
179 {ABCKIT_ISA_API_DYNAMIC_OPCODE_LDOBJBYNAME, 0X11},
180 {ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLTHIS0, 0X2},
181 {ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, 0X13},
182 {ABCKIT_ISA_API_DYNAMIC_OPCODE_LOADSTRING, -1},
183 {ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, 0X4},
184 {ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, 0X14},
185 {ABCKIT_ISA_API_DYNAMIC_OPCODE_NEWOBJRANGE, 0X15},
186 {ABCKIT_ISA_API_DYNAMIC_OPCODE_LDOBJBYNAME, 0X17},
187 {ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLTHIS0, 0X6},
188 {ABCKIT_ISA_API_DYNAMIC_OPCODE_LOADSTRING, -1},
189 {ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, 0X19},
190 {ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, 0X8},
191 {ABCKIT_ISA_API_DYNAMIC_OPCODE_SUB2, 0XA},
192 {ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, 0X1A},
193 {ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, 0XB},
194 {ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURNUNDEFINED, -1}});
195 // NOLINTEND(readability-magic-numbers)
196 });
197
198 output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "internal/ICSlotAllocator/ICSlotAllocator_modified.abc",
199 "ICSlotAllocator");
200 EXPECT_TRUE(helpers::Match(output,
201 "file: src/MyClass, function: MyClass.handle\n"
202 "abckit\n"
203 "Ellapsed time:\n"
204 "\\d+\n"));
205 }
206
207 } // namespace libabckit::test
208