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 "libabckit/include/c/abckit.h"
19
20 #include "helpers/helpers.h"
21 #include "helpers/helpers_runtime.h"
22
23 #include <gtest/gtest.h>
24
25 // NOLINTBEGIN(readability-magic-numbers)
26 namespace libabckit::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_dynG = AbckitGetIsaApiDynamicImpl(ABCKIT_VERSION_RELEASE_1_0_0);
33
34 class LibAbcKitCreateDynCallThis : public ::testing::Test {};
35
CreateBBSchemaForDynCallThisImpl(std::vector<helpers::InstSchema<AbckitIsaApiDynamicOpcode>> & params,helpers::InstSchema<AbckitIsaApiDynamicOpcode> & callInstSchema)36 static std::vector<helpers::BBSchema<AbckitIsaApiDynamicOpcode>> CreateBBSchemaForDynCallThisImpl(
37 std::vector<helpers::InstSchema<AbckitIsaApiDynamicOpcode>> ¶ms,
38 helpers::InstSchema<AbckitIsaApiDynamicOpcode> &callInstSchema)
39 {
40 return {{{}, {1}, params},
41 {{0},
42 {2},
43 {
44 {3, ABCKIT_ISA_API_DYNAMIC_OPCODE_LDHOLE, {}},
45 {4, ABCKIT_ISA_API_DYNAMIC_OPCODE_DEFINECLASSWITHBUFFER, {3}},
46 {5, ABCKIT_ISA_API_DYNAMIC_OPCODE_LDOBJBYNAME, {4}},
47 {6, ABCKIT_ISA_API_DYNAMIC_OPCODE_NEWOBJRANGE, {4}},
48 {9, ABCKIT_ISA_API_DYNAMIC_OPCODE_LDOBJBYNAME, {6}},
49 callInstSchema,
50 {7, ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURNUNDEFINED, {}},
51 }},
52 {{1}, {}, {}}};
53 }
54
55 // CC-OFFNXT(huge_method, C_RULE_ID_FUNCTION_SIZE) test helper
CreateBBSchemaForDynCallThis(AbckitIsaApiDynamicOpcode opcode)56 static std::vector<helpers::BBSchema<AbckitIsaApiDynamicOpcode>> CreateBBSchemaForDynCallThis(
57 AbckitIsaApiDynamicOpcode opcode)
58 {
59 auto paramOp = ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER;
60 auto constOp = ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT;
61 helpers::InstSchema<AbckitIsaApiDynamicOpcode> callInstSchema {0, ABCKIT_ISA_API_DYNAMIC_OPCODE_INVALID, {}};
62 std::vector<helpers::InstSchema<AbckitIsaApiDynamicOpcode>> params {
63 {0, paramOp, {}}, {1, paramOp, {}}, {2, paramOp, {}}};
64 switch (opcode) {
65 case ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLTHIS0:
66 callInstSchema = {10, opcode, {9, 6}};
67 break;
68 case ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLTHIS1:
69 params = {{0, paramOp, {}}, {1, paramOp, {}}, {2, paramOp, {}}, {10, constOp, {}}};
70 callInstSchema = {11, opcode, {9, 6, 10}};
71 break;
72 case ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLTHIS2:
73 params = {
74 {0, paramOp, {}}, {1, paramOp, {}}, {2, paramOp, {}}, {10, constOp, {}}, {11, constOp, {}},
75 };
76 callInstSchema = {12, opcode, {9, 6, 10, 11}};
77 break;
78 case ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLTHIS3:
79 params = {
80 {0, paramOp, {}}, {1, paramOp, {}}, {2, paramOp, {}},
81 {10, constOp, {}}, {11, constOp, {}}, {12, constOp, {}},
82 };
83 callInstSchema = {13, opcode, {9, 6, 10, 11, 12}};
84 break;
85 case ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLTHISRANGE:
86 case ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_CALLTHISRANGE:
87 params = {
88 {0, paramOp, {}}, {1, paramOp, {}}, {2, paramOp, {}}, {10, constOp, {}},
89 {11, constOp, {}}, {12, constOp, {}}, {13, constOp, {}},
90 };
91 callInstSchema = {14, opcode, {9, 6, 10, 11, 12, 13}};
92 break;
93 case ABCKIT_ISA_API_DYNAMIC_OPCODE_INVALID:
94 break;
95 default:
96 LIBABCKIT_UNREACHABLE_TEST(DEBUG);
97 }
98 return CreateBBSchemaForDynCallThisImpl(params, callInstSchema);
99 }
100
TestHelper(void (* transformIrCall)(AbckitGraph * graph,AbckitInst * obj,AbckitInst * func),AbckitIsaApiDynamicOpcode opcode,const std::string & expectedOutput)101 static void TestHelper(void (*transformIrCall)(AbckitGraph *graph, AbckitInst *obj, AbckitInst *func),
102 AbckitIsaApiDynamicOpcode opcode, const std::string &expectedOutput)
103 {
104 auto output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ut/isa/isa_dynamic/dyn_call_this/call_this_dynamic.abc",
105 "call_this_dynamic");
106 EXPECT_TRUE(helpers::Match(output, ""));
107
108 helpers::TransformMethod(
109 ABCKIT_ABC_DIR "ut/isa/isa_dynamic/dyn_call_this/call_this_dynamic.abc",
110 ABCKIT_ABC_DIR "ut/isa/isa_dynamic/dyn_call_this/call_this_dynamic_modified.abc",
111 "call_this_dynamic.func_main_0",
112 [&](AbckitFile *file, AbckitCoreFunction * /*method*/, AbckitGraph *graph) {
113 auto obj = helpers::FindFirstInst(graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_NEWOBJRANGE);
114 ASSERT_NE(obj, nullptr);
115 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
116
117 auto func = g_dynG->iCreateLdobjbyname(graph, obj, g_implM->createString(file, "func", strlen("func")));
118 ASSERT_NE(func, nullptr);
119 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
120
121 g_implG->iInsertAfter(func, obj);
122 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
123
124 transformIrCall(graph, obj, func);
125 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
126 },
127 [&](AbckitGraph *graph) {
128 std::vector<helpers::BBSchema<AbckitIsaApiDynamicOpcode>> bbSchemas(CreateBBSchemaForDynCallThis(opcode));
129 helpers::VerifyGraph(graph, bbSchemas);
130 });
131
132 output = helpers::ExecuteDynamicAbc(
133 ABCKIT_ABC_DIR "ut/isa/isa_dynamic/dyn_call_this/call_this_dynamic_modified.abc", "call_this_dynamic");
134 EXPECT_TRUE(helpers::Match(output, expectedOutput));
135 }
136
TransformIrCallThisarg0(AbckitGraph * graph,AbckitInst * obj,AbckitInst * func)137 static void TransformIrCallThisarg0(AbckitGraph *graph, AbckitInst *obj, AbckitInst *func)
138 {
139 auto call0 = g_dynG->iCreateCallthis0(graph, func, obj);
140 ASSERT_NE(call0, nullptr);
141 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
142
143 g_implG->iInsertAfter(call0, func);
144 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
145 }
146
TransformIrCallThisarg1(AbckitGraph * graph,AbckitInst * obj,AbckitInst * func)147 static void TransformIrCallThisarg1(AbckitGraph *graph, AbckitInst *obj, AbckitInst *func)
148 {
149 auto param0 = g_implG->gFindOrCreateConstantI64(graph, 1);
150 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
151
152 auto call1 = g_dynG->iCreateCallthis1(graph, func, obj, param0);
153 ASSERT_NE(call1, nullptr);
154 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
155
156 g_implG->iInsertAfter(call1, func);
157 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
158 }
159
TransformIrCallThisargs2(AbckitGraph * graph,AbckitInst * obj,AbckitInst * func)160 static void TransformIrCallThisargs2(AbckitGraph *graph, AbckitInst *obj, AbckitInst *func)
161 {
162 auto param0 = g_implG->gFindOrCreateConstantI64(graph, 1);
163 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
164 auto param1 = g_implG->gFindOrCreateConstantI64(graph, 2);
165 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
166
167 auto call2 = g_dynG->iCreateCallthis2(graph, func, obj, param0, param1);
168 ASSERT_NE(call2, nullptr);
169 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
170
171 g_implG->iInsertAfter(call2, func);
172 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
173 }
174
TransformIrCallThisargs3(AbckitGraph * graph,AbckitInst * obj,AbckitInst * func)175 static void TransformIrCallThisargs3(AbckitGraph *graph, AbckitInst *obj, AbckitInst *func)
176 {
177 auto param0 = g_implG->gFindOrCreateConstantI64(graph, 1);
178 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
179 auto param1 = g_implG->gFindOrCreateConstantI64(graph, 2);
180 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
181 auto param2 = g_implG->gFindOrCreateConstantI64(graph, 3);
182 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
183
184 auto call3 = g_dynG->iCreateCallthis3(graph, func, obj, param0, param1, param2);
185 ASSERT_NE(call3, nullptr);
186 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
187
188 g_implG->iInsertAfter(call3, func);
189 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
190 }
191
TransformIrCallThisrange(AbckitGraph * graph,AbckitInst * obj,AbckitInst * func)192 static void TransformIrCallThisrange(AbckitGraph *graph, AbckitInst *obj, AbckitInst *func)
193 {
194 auto param0 = g_implG->gFindOrCreateConstantI64(graph, 1);
195 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
196 auto param1 = g_implG->gFindOrCreateConstantI64(graph, 2);
197 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
198 auto param2 = g_implG->gFindOrCreateConstantI64(graph, 3);
199 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
200 auto param3 = g_implG->gFindOrCreateConstantI64(graph, 4);
201 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
202
203 auto call3 = g_dynG->iCreateCallthisrange(graph, func, 4, obj, param0, param1, param2, param3);
204 ASSERT_NE(call3, nullptr);
205 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
206
207 g_implG->iInsertAfter(call3, func);
208 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
209 }
210
TransformIrWideCallThisrange(AbckitGraph * graph,AbckitInst * obj,AbckitInst * func)211 static void TransformIrWideCallThisrange(AbckitGraph *graph, AbckitInst *obj, AbckitInst *func)
212 {
213 auto param0 = g_implG->gFindOrCreateConstantI64(graph, 1);
214 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
215 auto param1 = g_implG->gFindOrCreateConstantI64(graph, 2);
216 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
217 auto param2 = g_implG->gFindOrCreateConstantI64(graph, 3);
218 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
219 auto param3 = g_implG->gFindOrCreateConstantI64(graph, 4);
220 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
221
222 auto call3 = g_dynG->iCreateWideCallthisrange(graph, func, 4, obj, param0, param1, param2, param3);
223 ASSERT_NE(call3, nullptr);
224 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
225
226 g_implG->iInsertAfter(call3, func);
227 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
228 }
229
230 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateCallthis0, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynCallThis,CreateDynCallthis0)231 TEST_F(LibAbcKitCreateDynCallThis, CreateDynCallthis0)
232 {
233 TestHelper(TransformIrCallThisarg0, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLTHIS0, "func\n");
234 }
235
236 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateCallthis1, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynCallThis,CreateDynCallthis1)237 TEST_F(LibAbcKitCreateDynCallThis, CreateDynCallthis1)
238 {
239 TestHelper(TransformIrCallThisarg1, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLTHIS1, "func\n1\n");
240 }
241
242 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateCallthis2, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynCallThis,CreateDynCallthis2)243 TEST_F(LibAbcKitCreateDynCallThis, CreateDynCallthis2)
244 {
245 TestHelper(TransformIrCallThisargs2, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLTHIS2, "func\n1\n2\n");
246 }
247
248 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateCallthis3, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynCallThis,CreateDynCallthis3)249 TEST_F(LibAbcKitCreateDynCallThis, CreateDynCallthis3)
250 {
251 TestHelper(TransformIrCallThisargs3, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLTHIS3, "func\n1\n2\n3\n");
252 }
253
254 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateCallthisrange, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynCallThis,CreateDynCallthisrange)255 TEST_F(LibAbcKitCreateDynCallThis, CreateDynCallthisrange)
256 {
257 TestHelper(TransformIrCallThisrange, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLTHISRANGE, "func\n1\n2\n3\n4\n");
258 }
259
260 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateWideCallthisrange, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynCallThis,CreateDynWideCallthisrange)261 TEST_F(LibAbcKitCreateDynCallThis, CreateDynWideCallthisrange)
262 {
263 TestHelper(TransformIrWideCallThisrange, ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_CALLTHISRANGE, "func\n1\n2\n3\n4\n");
264 }
265
266 } // namespace libabckit::test
267 // NOLINTEND(readability-magic-numbers)
268