• 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/isa/isa_dynamic.h"
19 #include "libabckit/include/c/abckit.h"
20 
21 #include "helpers/helpers.h"
22 #include "helpers/helpers_runtime.h"
23 
24 #include <gtest/gtest.h>
25 
26 // NOLINTBEGIN(readability-magic-numbers)
27 namespace libabckit::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 class LibAbcKitCreateDynCall : public ::testing::Test {};
36 
CreateBBSchemaForDynCall(AbckitIsaApiDynamicOpcode opcode)37 static std::vector<helpers::BBSchema<AbckitIsaApiDynamicOpcode>> CreateBBSchemaForDynCall(
38     AbckitIsaApiDynamicOpcode opcode)
39 {
40     auto paramOp = ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER;
41     auto constOp = ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT;
42     helpers::InstSchema<AbckitIsaApiDynamicOpcode> callInstSchema {0, ABCKIT_ISA_API_DYNAMIC_OPCODE_INVALID, {}};
43     std::vector<helpers::InstSchema<AbckitIsaApiDynamicOpcode>> params {
44         {0, paramOp, {}}, {1, paramOp, {}}, {2, paramOp, {}}};
45     switch (opcode) {
46         case ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG0:
47             callInstSchema = {4, opcode, {3}};
48             break;
49         case ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1:
50             params = {{0, paramOp, {}}, {1, paramOp, {}}, {2, paramOp, {}}, {4, constOp, {}}};
51             callInstSchema = {4, opcode, {3, 4}};
52             break;
53         case ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARGS2:
54             params = {
55                 {0, paramOp, {}}, {1, paramOp, {}}, {2, paramOp, {}}, {4, constOp, {}}, {5, constOp, {}},
56             };
57             callInstSchema = {4, opcode, {3, 4, 5}};
58             break;
59         case ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARGS3:
60             params = {
61                 {0, paramOp, {}}, {1, paramOp, {}}, {2, paramOp, {}},
62                 {4, constOp, {}}, {5, constOp, {}}, {6, constOp, {}},
63             };
64             callInstSchema = {4, opcode, {3, 4, 5, 6}};
65             break;
66         case ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLRANGE:
67         case ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_CALLRANGE:
68             params = {
69                 {0, paramOp, {}}, {1, paramOp, {}}, {2, paramOp, {}}, {4, constOp, {}},
70                 {5, constOp, {}}, {6, constOp, {}}, {7, constOp, {}},
71             };
72             callInstSchema = {4, opcode, {3, 4, 5, 6, 7}};
73             break;
74         case ABCKIT_ISA_API_DYNAMIC_OPCODE_INVALID:
75             break;
76         default:
77             LIBABCKIT_UNREACHABLE_TEST(DEBUG);
78     }
79     return {{{}, {1}, params},
80             {{0},
81              {2},
82              {
83                  {3, ABCKIT_ISA_API_DYNAMIC_OPCODE_DEFINEFUNC, {}},
84                  callInstSchema,
85                  {8, ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURNUNDEFINED, {}},
86              }},
87             {{1}, {}, {}}};
88 }
89 
TestHelper(void (* transformIrCall)(AbckitGraph * graph),AbckitIsaApiDynamicOpcode opcode,const std::string & expectedOutput,bool execute=true)90 static void TestHelper(void (*transformIrCall)(AbckitGraph *graph), AbckitIsaApiDynamicOpcode opcode,
91                        const std::string &expectedOutput, bool execute = true)
92 {
93     auto output =
94         helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ut/isa/isa_dynamic/dyn_call/call_dynamic.abc", "call_dynamic");
95     EXPECT_TRUE(helpers::Match(output, ""));
96 
97     helpers::TransformMethod(
98         ABCKIT_ABC_DIR "ut/isa/isa_dynamic/dyn_call/call_dynamic.abc",
99         ABCKIT_ABC_DIR "ut/isa/isa_dynamic/dyn_call/call_dynamic_modified.abc", "call_dynamic.func_main_0",
100         [&](AbckitFile * /*file*/, AbckitCoreFunction * /*method*/, AbckitGraph *graph) {
101             transformIrCall(graph);
102             ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
103         },
104         [&](AbckitGraph *graph) {
105             std::vector<helpers::BBSchema<AbckitIsaApiDynamicOpcode>> bbSchemas(CreateBBSchemaForDynCall(opcode));
106             helpers::VerifyGraph(graph, bbSchemas);
107         });
108 
109     if (execute) {
110         output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ut/isa/isa_dynamic/dyn_call/call_dynamic_modified.abc",
111                                             "call_dynamic");
112         EXPECT_TRUE(helpers::Match(output, expectedOutput));
113     }
114 }
115 
TransformIrCallarg0(AbckitGraph * graph)116 static void TransformIrCallarg0(AbckitGraph *graph)
117 {
118     auto func = helpers::FindFirstInst(graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_DEFINEFUNC);
119     ASSERT_NE(func, nullptr);
120     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
121 
122     auto call0 = g_dynG->iCreateCallarg0(graph, func);
123     ASSERT_NE(call0, nullptr);
124     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
125 
126     g_implG->iInsertAfter(call0, func);
127     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
128 }
129 
TransformIrCallarg1(AbckitGraph * graph)130 static void TransformIrCallarg1(AbckitGraph *graph)
131 {
132     auto func = helpers::FindFirstInst(graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_DEFINEFUNC);
133     ASSERT_NE(func, nullptr);
134     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
135 
136     auto param0 = g_implG->gFindOrCreateConstantI64(graph, 1);
137     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
138 
139     auto call1 = g_dynG->iCreateCallarg1(graph, func, param0);
140     ASSERT_NE(call1, nullptr);
141     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
142 
143     g_implG->iInsertAfter(call1, func);
144     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
145 }
146 
TransformIrCallargs2(AbckitGraph * graph)147 static void TransformIrCallargs2(AbckitGraph *graph)
148 {
149     auto func = helpers::FindFirstInst(graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_DEFINEFUNC);
150     ASSERT_NE(func, nullptr);
151     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
152 
153     auto param0 = g_implG->gFindOrCreateConstantI64(graph, 1);
154     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
155     auto param1 = g_implG->gFindOrCreateConstantI64(graph, 2);
156     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
157 
158     auto call2 = g_dynG->iCreateCallargs2(graph, func, param0, param1);
159     ASSERT_NE(call2, nullptr);
160     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
161 
162     g_implG->iInsertAfter(call2, func);
163     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
164 }
165 
TransformIrCallargs3(AbckitGraph * graph)166 static void TransformIrCallargs3(AbckitGraph *graph)
167 {
168     auto func = helpers::FindFirstInst(graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_DEFINEFUNC);
169     ASSERT_NE(func, nullptr);
170     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
171 
172     auto param0 = g_implG->gFindOrCreateConstantI64(graph, 1);
173     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
174     auto param1 = g_implG->gFindOrCreateConstantI64(graph, 2);
175     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
176     auto param2 = g_implG->gFindOrCreateConstantI64(graph, 3);
177     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
178 
179     auto call3 = g_dynG->iCreateCallargs3(graph, func, param0, param1, param2);
180     ASSERT_NE(call3, nullptr);
181     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
182 
183     g_implG->iInsertAfter(call3, func);
184     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
185 }
186 
TransformIrCallrange(AbckitGraph * graph)187 static void TransformIrCallrange(AbckitGraph *graph)
188 {
189     auto func = helpers::FindFirstInst(graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_DEFINEFUNC);
190     ASSERT_NE(func, nullptr);
191     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
192 
193     auto param0 = g_implG->gFindOrCreateConstantI64(graph, 1);
194     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
195     auto param1 = g_implG->gFindOrCreateConstantI64(graph, 2);
196     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
197     auto param2 = g_implG->gFindOrCreateConstantI64(graph, 3);
198     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
199     auto param3 = g_implG->gFindOrCreateConstantI64(graph, 4);
200     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
201 
202     auto call4 = g_dynG->iCreateCallrange(graph, func, 4, param0, param1, param2, param3);
203     ASSERT_NE(call4, nullptr);
204     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
205 
206     g_implG->iInsertAfter(call4, func);
207     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
208 }
209 
TransformIrWideCallrange(AbckitGraph * graph)210 static void TransformIrWideCallrange(AbckitGraph *graph)
211 {
212     auto func = helpers::FindFirstInst(graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_DEFINEFUNC);
213     ASSERT_NE(func, nullptr);
214     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
215 
216     auto param0 = g_implG->gFindOrCreateConstantI64(graph, 1);
217     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
218     auto param1 = g_implG->gFindOrCreateConstantI64(graph, 2);
219     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
220     auto param2 = g_implG->gFindOrCreateConstantI64(graph, 3);
221     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
222     auto param3 = g_implG->gFindOrCreateConstantI64(graph, 4);
223     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
224 
225     auto call4 = g_dynG->iCreateWideCallrange(graph, func, 4, param0, param1, param2, param3);
226     ASSERT_NE(call4, nullptr);
227     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
228 
229     g_implG->iInsertAfter(call4, func);
230     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
231 }
232 
233 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateCallarg0, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynCall,CreateDynCallarg0)234 TEST_F(LibAbcKitCreateDynCall, CreateDynCallarg0)
235 {
236     TestHelper(TransformIrCallarg0, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG0, "func\n");
237 }
238 
239 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateCallarg1, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynCall,CreateDynCallarg1)240 TEST_F(LibAbcKitCreateDynCall, CreateDynCallarg1)
241 {
242     TestHelper(TransformIrCallarg1, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, "func\n1\n");
243 }
244 
245 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateCallargs2, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynCall,CreateDynCallargs2)246 TEST_F(LibAbcKitCreateDynCall, CreateDynCallargs2)
247 {
248     TestHelper(TransformIrCallargs2, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARGS2, "func\n1\n2\n");
249 }
250 
251 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateCallargs3, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynCall,CreateDynCallargs3)252 TEST_F(LibAbcKitCreateDynCall, CreateDynCallargs3)
253 {
254     TestHelper(TransformIrCallargs3, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARGS3, "func\n1\n2\n3\n");
255 }
256 
257 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateCallrange, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynCall,CreateDynCallrange)258 TEST_F(LibAbcKitCreateDynCall, CreateDynCallrange)
259 {
260     TestHelper(TransformIrCallrange, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLRANGE, "func\n1\n2\n3\n4\n");
261 }
262 
263 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateWideCallrange, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynCall,CreateDynWideCallrange)264 TEST_F(LibAbcKitCreateDynCall, CreateDynWideCallrange)
265 {
266     // Temporary doesn't execute due to Dynamic VM runtime bug #IA954E
267     TestHelper(TransformIrWideCallrange, ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_CALLRANGE, "func\n1\n2\n3\n4\n", false);
268 }
269 
270 }  // namespace libabckit::test
271 // NOLINTEND(readability-magic-numbers)
272