• 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 "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>> &params,
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