1 /**
2 * Copyright (c) 2024-2025 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 "libabckit/include/c/isa/isa_static.h"
18 #include "libabckit/include/c/metadata_core.h"
19 #include "libabckit/include/c/ir_core.h"
20
21 #include "helpers/helpers_runtime.h"
22 #include "helpers/helpers.h"
23
24 #include <gtest/gtest.h>
25
26 // NOLINTBEGIN(readability-magic-numbers)
27 namespace libabckit::test {
28
29 namespace {
30 auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
31 auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
32 auto g_implM = AbckitGetModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
33 auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0);
34 auto g_statG = AbckitGetIsaApiStaticImpl(ABCKIT_VERSION_RELEASE_1_0_0);
35
TransformIr(AbckitGraph * graph,AbckitCoreFunction * consoleLogInt)36 void TransformIr(AbckitGraph *graph, AbckitCoreFunction *consoleLogInt)
37 {
38 AbckitInst *callInst = helpers::FindFirstInst(graph, ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC);
39 AbckitInst *castToInt =
40 g_statG->iCreateCast(graph, g_implG->iGetInput(callInst, 0), AbckitTypeId::ABCKIT_TYPE_ID_I32);
41 g_implG->iInsertAfter(castToInt, callInst);
42 AbckitInst *callLogInt = g_statG->iCreateCallStatic(graph, consoleLogInt, 1, castToInt);
43 g_implG->iInsertAfter(callLogInt, castToInt);
44 }
45
TransformCheckCastIr(AbckitGraph * graph,AbckitFile * file,AbckitCoreClass * classA)46 void TransformCheckCastIr(AbckitGraph *graph, AbckitFile *file, AbckitCoreClass *classA)
47 {
48 AbckitInst *initObj = helpers::FindFirstInst(graph, ABCKIT_ISA_API_STATIC_OPCODE_INITOBJECT);
49 ASSERT_NE(initObj, nullptr);
50 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
51
52 auto *type = g_implM->createReferenceType(file, classA);
53 ASSERT_NE(type, nullptr);
54 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
55
56 AbckitInst *checkCast = g_statG->iCreateCheckCast(graph, initObj, type);
57 ASSERT_NE(checkCast, nullptr);
58 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
59
60 g_implG->iInsertAfter(checkCast, initObj);
61 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
62 }
63 } // namespace
64
65 class LibAbcKitCastStaticTest : public ::testing::Test {};
66
67 // Test: test-kind=api, api=IsaApiStaticImpl::iCreateCast, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(LibAbcKitCastStaticTest,LibAbcKitTestCreateCast)68 TEST_F(LibAbcKitCastStaticTest, LibAbcKitTestCreateCast)
69 {
70 helpers::TransformMethod(
71 ABCKIT_ABC_DIR "ut/isa/isa_static/cast/cast_static.abc",
72 ABCKIT_ABC_DIR "ut/isa/isa_static/cast/cast_static_modified.abc", "handle",
73 [](AbckitFile * /*file*/, AbckitCoreFunction *method, AbckitGraph *graph) {
74 AbckitCoreFunction *consoleLogInt =
75 helpers::FindMethodByName(g_implI->functionGetFile(method), "ConsoleLogInt");
76 TransformIr(graph, consoleLogInt);
77 },
78 [](AbckitGraph *graph) {
79 std::vector<helpers::BBSchema<AbckitIsaApiStaticOpcode>> bbSchemas(
80 {{{},
81 {1},
82 {
83 {0, ABCKIT_ISA_API_STATIC_OPCODE_PARAMETER, {}},
84 {2, ABCKIT_ISA_API_STATIC_OPCODE_CONSTANT, {}},
85 }},
86 {{0},
87 {2},
88 {
89 {4, ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC, {2}},
90 {6, ABCKIT_ISA_API_STATIC_OPCODE_CAST, {2}},
91 {8, ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC, {6}},
92 {10, ABCKIT_ISA_API_STATIC_OPCODE_RETURN_VOID, {}},
93 }},
94 {{1}, {}, {}}});
95 helpers::VerifyGraph(graph, bbSchemas);
96 });
97 }
98
99 // Test: test-kind=api, api=IsaApiStaticImpl::iCreateCheckCast, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(LibAbcKitCastStaticTest,LibAbcKitTestCheckCast)100 TEST_F(LibAbcKitCastStaticTest, LibAbcKitTestCheckCast)
101 {
102 helpers::TransformMethod(
103 ABCKIT_ABC_DIR "ut/isa/isa_static/cast/checkcast_static.abc",
104 ABCKIT_ABC_DIR "ut/isa/isa_static/cast/checkcast_static_modified.abc", "main",
105 []([[maybe_unused]] AbckitFile *file, [[maybe_unused]] AbckitCoreFunction *method,
106 [[maybe_unused]] AbckitGraph *graph) {
107 auto *module = g_implI->functionGetModule(method);
108 helpers::ClassByNameContext classCtxFinder = {nullptr, "A"};
109 g_implI->moduleEnumerateClasses(module, &classCtxFinder, helpers::ClassByNameFinder);
110 ASSERT_NE(classCtxFinder.klass, nullptr);
111 TransformCheckCastIr(graph, file, classCtxFinder.klass);
112 },
113 [](AbckitGraph *graph) {
114 helpers::BBSchema<AbckitIsaApiStaticOpcode> bb1({{}, {1}, {{}}});
115 std::vector<helpers::InstSchema<AbckitIsaApiStaticOpcode>> insts({
116 {0, ABCKIT_ISA_API_STATIC_OPCODE_INITOBJECT, {}},
117 {2, ABCKIT_ISA_API_STATIC_OPCODE_CHECKCAST, {0}},
118 {1, ABCKIT_ISA_API_STATIC_OPCODE_RETURN_VOID, {}},
119 });
120 helpers::BBSchema<AbckitIsaApiStaticOpcode> bb2({{0}, {2}, insts});
121 helpers::BBSchema<AbckitIsaApiStaticOpcode> bb3({{1}, {}, {}});
122 std::vector<helpers::BBSchema<AbckitIsaApiStaticOpcode>> bbSchemas({bb1, bb2, bb3});
123 helpers::VerifyGraph(graph, bbSchemas);
124 });
125
126 auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ut/isa/isa_static/cast/checkcast_static_modified.abc",
127 "checkcast_static/ETSGLOBAL", "main");
128 EXPECT_TRUE(helpers::Match(output, ""));
129 }
130
131 // Test: test-kind=api, api=IsaApiStaticImpl::iGetTargetType, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(LibAbcKitCastStaticTest,LibAbcKitTestGetTargetType1)132 TEST_F(LibAbcKitCastStaticTest, LibAbcKitTestGetTargetType1)
133 {
134 helpers::TransformMethod(
135 ABCKIT_ABC_DIR "ut/isa/isa_static/cast/target_type_static.abc",
136 ABCKIT_ABC_DIR "ut/isa/isa_static/cast/target_type_static_modified.abc", "handle",
137 [](AbckitFile * /*file*/, AbckitCoreFunction * /*method*/, AbckitGraph *graph) {
138 AbckitInst *cast = helpers::FindFirstInst(graph, ABCKIT_ISA_API_STATIC_OPCODE_CAST);
139 auto targetType = g_statG->iGetTargetType(cast);
140 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
141 ASSERT_EQ(targetType, ABCKIT_TYPE_ID_I32);
142
143 cast = g_implG->iGetNext(cast);
144 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
145 ASSERT_NE(cast, nullptr);
146 targetType = g_statG->iGetTargetType(cast);
147 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
148 ASSERT_EQ(targetType, ABCKIT_TYPE_ID_F64);
149 },
150 [](AbckitGraph *graph) {
151 std::vector<helpers::BBSchema<AbckitIsaApiStaticOpcode>> bbSchemas(
152 {{{},
153 {1},
154 {
155 {0, ABCKIT_ISA_API_STATIC_OPCODE_PARAMETER, {}},
156 {1, ABCKIT_ISA_API_STATIC_OPCODE_CONSTANT, {}},
157 }},
158 {{0},
159 {2},
160 {
161 {2, ABCKIT_ISA_API_STATIC_OPCODE_CAST, {1}},
162 {3, ABCKIT_ISA_API_STATIC_OPCODE_CAST, {2}},
163 {4, ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC, {3}},
164 {5, ABCKIT_ISA_API_STATIC_OPCODE_RETURN_VOID, {}},
165 }},
166 {{1}, {}, {}}});
167 helpers::VerifyGraph(graph, bbSchemas);
168 });
169 }
170
171 // Test: test-kind=api, api=IsaApiStaticImpl::iGetTargetType, abc-kind=ArkTS2, category=negative
TEST_F(LibAbcKitCastStaticTest,LibAbcKitTestGetTargetType2)172 TEST_F(LibAbcKitCastStaticTest, LibAbcKitTestGetTargetType2)
173 {
174 helpers::TransformMethod(
175 ABCKIT_ABC_DIR "ut/isa/isa_static/cast/target_type_static.abc",
176 ABCKIT_ABC_DIR "ut/isa/isa_static/cast/target_type_static_modified.abc", "handle",
177 [](AbckitFile * /*file*/, AbckitCoreFunction * /*method*/, AbckitGraph *graph) {
178 AbckitInst *ret = helpers::FindFirstInst(graph, ABCKIT_ISA_API_STATIC_OPCODE_RETURN_VOID);
179 auto targetType = g_statG->iGetTargetType(ret);
180 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT);
181 ASSERT_EQ(targetType, ABCKIT_TYPE_ID_INVALID);
182 },
183 [](AbckitGraph *graph) {
184 std::vector<helpers::BBSchema<AbckitIsaApiStaticOpcode>> bbSchemas(
185 {{{},
186 {1},
187 {
188 {0, ABCKIT_ISA_API_STATIC_OPCODE_PARAMETER, {}},
189 {1, ABCKIT_ISA_API_STATIC_OPCODE_CONSTANT, {}},
190 }},
191 {{0},
192 {2},
193 {
194 {2, ABCKIT_ISA_API_STATIC_OPCODE_CAST, {1}},
195 {3, ABCKIT_ISA_API_STATIC_OPCODE_CAST, {2}},
196 {4, ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC, {3}},
197 {5, ABCKIT_ISA_API_STATIC_OPCODE_RETURN_VOID, {}},
198 }},
199 {{1}, {}, {}}});
200 helpers::VerifyGraph(graph, bbSchemas);
201 });
202 }
203
204 // Test: test-kind=api, api=IsaApiStaticImpl::iSetTargetType, abc-kind=ArkTS2, category=positive, extension=c
TEST_F(LibAbcKitCastStaticTest,LibAbcKitTestSetTargetType1)205 TEST_F(LibAbcKitCastStaticTest, LibAbcKitTestSetTargetType1)
206 {
207 helpers::TransformMethod(
208 ABCKIT_ABC_DIR "ut/isa/isa_static/cast/target_type_static.abc",
209 ABCKIT_ABC_DIR "ut/isa/isa_static/cast/target_type_static_modified.abc", "handle",
210 [](AbckitFile * /*file*/, AbckitCoreFunction * /*method*/, AbckitGraph *graph) {
211 AbckitInst *cast = helpers::FindFirstInst(graph, ABCKIT_ISA_API_STATIC_OPCODE_CAST);
212 g_statG->iSetTargetType(cast, ABCKIT_TYPE_ID_F32);
213 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
214
215 g_implG->iVisitUsers(cast, nullptr, [](AbckitInst *user, void * /*data*/) {
216 g_implG->iRemove(user);
217 return true;
218 });
219
220 AbckitInst *newCast = g_statG->iCreateCast(graph, cast, ABCKIT_TYPE_ID_F64);
221 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
222
223 AbckitInst *call = helpers::FindFirstInst(graph, ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC);
224
225 g_implG->iInsertBefore(newCast, call);
226
227 g_implG->iSetInput(call, newCast, 0);
228 },
229 [](AbckitGraph *graph) {
230 std::vector<helpers::BBSchema<AbckitIsaApiStaticOpcode>> bbSchemas(
231 {{{},
232 {1},
233 {
234 {0, ABCKIT_ISA_API_STATIC_OPCODE_PARAMETER, {}},
235 {1, ABCKIT_ISA_API_STATIC_OPCODE_CONSTANT, {}},
236 }},
237 {{0},
238 {2},
239 {
240 {2, ABCKIT_ISA_API_STATIC_OPCODE_CAST, {1}},
241 {3, ABCKIT_ISA_API_STATIC_OPCODE_CAST, {2}},
242 {4, ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC, {3}},
243 {5, ABCKIT_ISA_API_STATIC_OPCODE_RETURN_VOID, {}},
244 }},
245 {{1}, {}, {}}});
246 helpers::VerifyGraph(graph, bbSchemas);
247 });
248 }
249
250 // Test: test-kind=api, api=IsaApiStaticImpl::iSetTargetType, abc-kind=ArkTS2, category=negative
TEST_F(LibAbcKitCastStaticTest,LibAbcKitTestSetTargetType2)251 TEST_F(LibAbcKitCastStaticTest, LibAbcKitTestSetTargetType2)
252 {
253 helpers::TransformMethod(
254 ABCKIT_ABC_DIR "ut/isa/isa_static/cast/target_type_static.abc",
255 ABCKIT_ABC_DIR "ut/isa/isa_static/cast/target_type_static_modified.abc", "handle",
256 [](AbckitFile * /*file*/, AbckitCoreFunction * /*method*/, AbckitGraph *graph) {
257 AbckitInst *ret = helpers::FindFirstInst(graph, ABCKIT_ISA_API_STATIC_OPCODE_RETURN_VOID);
258 g_statG->iSetTargetType(ret, ABCKIT_TYPE_ID_F64);
259 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT);
260 },
261 [](AbckitGraph *graph) {
262 std::vector<helpers::BBSchema<AbckitIsaApiStaticOpcode>> bbSchemas(
263 {{{},
264 {1},
265 {
266 {0, ABCKIT_ISA_API_STATIC_OPCODE_PARAMETER, {}},
267 {1, ABCKIT_ISA_API_STATIC_OPCODE_CONSTANT, {}},
268 }},
269 {{0},
270 {2},
271 {
272 {2, ABCKIT_ISA_API_STATIC_OPCODE_CAST, {1}},
273 {3, ABCKIT_ISA_API_STATIC_OPCODE_CAST, {2}},
274 {4, ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC, {3}},
275 {5, ABCKIT_ISA_API_STATIC_OPCODE_RETURN_VOID, {}},
276 }},
277 {{1}, {}, {}}});
278 helpers::VerifyGraph(graph, bbSchemas);
279 });
280 }
281
282 } // namespace libabckit::test
283 // NOLINTEND(readability-magic-numbers)
284