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/abckit.h"
17 #include "ir_impl.h"
18 #include "libabckit/include/c/metadata_core.h"
19 #include "libabckit/include/c/ir_core.h"
20 #include "libabckit/include/c/isa/isa_dynamic.h"
21
22 #include "helpers/helpers.h"
23 #include "helpers/helpers_runtime.h"
24
25 #include <gtest/gtest.h>
26
27 namespace libabckit::test {
28
29 class AbckitScenarioTest : public ::testing::Test {};
30
31 static auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
32 static auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
33 static auto g_implM = AbckitGetModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
34 static auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
35 static auto g_dynG = AbckitGetIsaApiDynamicImpl(ABCKIT_VERSION_RELEASE_1_0_0);
36
37 struct UserData {
38 AbckitString *print = nullptr;
39 AbckitString *date = nullptr;
40 AbckitString *getTime = nullptr;
41 AbckitString *str = nullptr;
42 AbckitString *consume = nullptr;
43 };
44
45 struct VisitData {
46 UserData *ud = nullptr;
47 AbckitInst *time = nullptr;
48 };
49
CreateEpilog(AbckitInst * inst,AbckitBasicBlock * bb,UserData * userData,AbckitInst * time)50 static void CreateEpilog(AbckitInst *inst, AbckitBasicBlock *bb, UserData *userData, AbckitInst *time)
51 {
52 auto *graph = g_implG->bbGetGraph(bb);
53 while (inst != nullptr) {
54 if (g_dynG->iGetOpcode(inst) == ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURNUNDEFINED) {
55 // Epilog
56 auto *dateClass2 = g_dynG->iCreateTryldglobalbyname(graph, userData->date);
57 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
58 g_implG->iInsertBefore(dateClass2, inst);
59 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
60 auto *dateObj2 = g_dynG->iCreateNewobjrange(graph, 1, dateClass2);
61 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
62 g_implG->iInsertAfter(dateObj2, dateClass2);
63 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
64 auto *getTime2 = g_dynG->iCreateLdobjbyname(graph, dateObj2, userData->getTime);
65 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
66 g_implG->iInsertAfter(getTime2, dateObj2);
67 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
68 auto *time2 = g_dynG->iCreateCallthis0(graph, getTime2, dateObj2);
69 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
70 g_implG->iInsertAfter(time2, getTime2);
71 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
72 auto *consume = g_dynG->iCreateLoadString(graph, userData->consume);
73 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
74 g_implG->iInsertAfter(consume, time2);
75 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
76
77 auto *print2 = g_dynG->iCreateTryldglobalbyname(graph, userData->print);
78 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
79 g_implG->iInsertAfter(print2, consume);
80 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
81 auto *callArg2 = g_dynG->iCreateCallarg1(graph, print2, consume);
82 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
83 g_implG->iInsertAfter(callArg2, print2);
84 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
85 auto *sub = g_dynG->iCreateSub2(graph, time, time2);
86 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
87 g_implG->iInsertAfter(sub, callArg2);
88 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
89
90 auto *print3 = g_dynG->iCreateTryldglobalbyname(graph, userData->print);
91 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
92 g_implG->iInsertAfter(print3, sub);
93 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
94 auto *callArg3 = g_dynG->iCreateCallarg1(graph, print3, sub);
95 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
96 g_implG->iInsertAfter(callArg3, print3);
97 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
98 }
99 inst = g_implG->iGetNext(inst);
100 }
101 }
102
TransformIr(AbckitGraph * graph,UserData * userData)103 static void TransformIr(AbckitGraph *graph, UserData *userData)
104 {
105 AbckitBasicBlock *startBB = g_implG->gGetStartBasicBlock(graph);
106 std::vector<AbckitBasicBlock *> succBBs = helpers::BBgetSuccBlocks(startBB);
107 auto *bb = succBBs[0];
108
109 // Prolog
110 auto *str = g_dynG->iCreateLoadString(graph, userData->str);
111 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
112 g_implG->bbAddInstFront(bb, str);
113 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
114 auto *print = g_dynG->iCreateTryldglobalbyname(graph, userData->print);
115 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
116 g_implG->iInsertAfter(print, str);
117 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
118 auto *callArg = g_dynG->iCreateCallarg1(graph, print, str);
119 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
120 g_implG->iInsertAfter(callArg, print);
121 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
122
123 auto *dateClass = g_dynG->iCreateTryldglobalbyname(graph, userData->date);
124 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
125 g_implG->iInsertAfter(dateClass, callArg);
126 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
127 auto *dateObj = g_dynG->iCreateNewobjrange(graph, 1, dateClass);
128 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
129 g_implG->iInsertAfter(dateObj, dateClass);
130 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
131 auto *getTime = g_dynG->iCreateLdobjbyname(graph, dateObj, userData->getTime);
132 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
133 g_implG->iInsertAfter(getTime, dateObj);
134 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
135 auto *time = g_dynG->iCreateCallthis0(graph, getTime, dateObj);
136 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
137 g_implG->iInsertAfter(time, getTime);
138 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
139
140 VisitData vd;
141 vd.ud = userData;
142 vd.time = time;
143
144 g_implG->gVisitBlocksRpo(graph, &vd, [](AbckitBasicBlock *bb, void *data) {
145 auto *inst = g_implG->bbGetFirstInst(bb);
146
147 auto *visitData = reinterpret_cast<VisitData *>(data);
148 CreateEpilog(inst, bb, visitData->ud, visitData->time);
149 return true;
150 });
151 }
152
153 // CC-OFFNXT(G.FUN.01-CPP) test function
GetCorrectBBSchema()154 static std::vector<helpers::BBSchema<AbckitIsaApiDynamicOpcode>> GetCorrectBBSchema()
155 {
156 // NOLINTBEGIN(readability-magic-numbers)
157 std::vector<helpers::BBSchema<AbckitIsaApiDynamicOpcode>> bbSchemas(
158 {{{},
159 {1},
160 {
161 {0, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
162 {1, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
163 {2, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
164 {10, ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT, {}},
165 {11, ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT, {}},
166 {14, ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT, {}},
167 }},
168 {{0},
169 {3, 2},
170 {
171 {3, ABCKIT_ISA_API_DYNAMIC_OPCODE_LOADSTRING, {}},
172 {4, ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, {}},
173 {5, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, {4, 3}},
174 {6, ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, {}},
175 {7, ABCKIT_ISA_API_DYNAMIC_OPCODE_NEWOBJRANGE, {6}},
176 {8, ABCKIT_ISA_API_DYNAMIC_OPCODE_LDOBJBYNAME, {7}},
177 {9, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLTHIS0, {8, 7}},
178 {12, ABCKIT_ISA_API_DYNAMIC_OPCODE_LESS, {11, 10}},
179 {13, ABCKIT_ISA_API_DYNAMIC_OPCODE_IF, {12, 14}},
180 }},
181 {{1},
182 {4},
183 {
184 {15, ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, {}},
185 {16, ABCKIT_ISA_API_DYNAMIC_OPCODE_LOADSTRING, {}},
186 {17, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, {15, 16}},
187 }},
188 {{1},
189 {4},
190 {
191 {18, ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, {}},
192 {19, ABCKIT_ISA_API_DYNAMIC_OPCODE_LOADSTRING, {}},
193 {20, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, {18, 19}},
194 }},
195 {{2, 3},
196 {5},
197 {
198 {24, ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, {}},
199 {25, ABCKIT_ISA_API_DYNAMIC_OPCODE_NEWOBJRANGE, {24}},
200 {26, ABCKIT_ISA_API_DYNAMIC_OPCODE_LDOBJBYNAME, {25}},
201 {27, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLTHIS0, {26, 25}},
202 {28, ABCKIT_ISA_API_DYNAMIC_OPCODE_LOADSTRING, {}},
203 {29, ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, {}},
204 {30, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, {29, 28}},
205 {31, ABCKIT_ISA_API_DYNAMIC_OPCODE_SUB2, {9, 27}},
206 {32, ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, {}},
207 {33, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, {32, 31}},
208 {34, ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURNUNDEFINED, {}},
209 }},
210 {{4}, {}, {}}});
211 return bbSchemas;
212 }
213 // CC-OFFNXT(huge_method, C_RULE_ID_FUNCTION_SIZE) test, solid logic
214 // Test: test-kind=scenario, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(AbckitScenarioTest,LibAbcKitTestDynamicAddLog)215 TEST_F(AbckitScenarioTest, LibAbcKitTestDynamicAddLog)
216 {
217 auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "scenarios/add_log/add_log_dynamic.abc", "add_log_dynamic");
218 EXPECT_TRUE(helpers::Match(output, "abckit\n"));
219
220 helpers::TransformMethod(
221 ABCKIT_ABC_DIR "scenarios/add_log/add_log_dynamic.abc",
222 ABCKIT_ABC_DIR "scenarios/add_log/add_log_dynamic_modified.abc", "handle",
223 [](AbckitFile *file, AbckitCoreFunction *, AbckitGraph *graph) {
224 UserData data = {};
225 data.print = g_implM->createString(file, "print", strlen("print"));
226 data.date = g_implM->createString(file, "Date", strlen("Date"));
227 data.getTime = g_implM->createString(file, "getTime", strlen("getTime"));
228 data.str = g_implM->createString(file, "file: src/MyClass, function: MyClass.handle",
229 strlen("file: src/MyClass, function: MyClass.handle"));
230 data.consume = g_implM->createString(file, "Ellapsed time:", strlen("Ellapsed time:"));
231
232 TransformIr(graph, &data);
233 },
234 [](AbckitGraph *graph) {
235 // NOLINTEND(readability-magic-numbers)
236 helpers::VerifyGraph(graph, GetCorrectBBSchema());
237 });
238
239 output =
240 helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "scenarios/add_log/add_log_dynamic_modified.abc", "add_log_dynamic");
241 EXPECT_TRUE(helpers::Match(output,
242 "file: src/MyClass, function: MyClass.handle\n"
243 "abckit\n"
244 "Ellapsed time:\n"
245 "\\d+\n"));
246 }
247
248 } // namespace libabckit::test
249