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/isa/isa_static.h"
17 #include "libabckit/include/c/metadata_core.h"
18 #include "libabckit/include/c/ir_core.h"
19 #include "libabckit/include/c/isa/isa_dynamic.h"
20 #include "libabckit/include/c/abckit.h"
21
22 #include "helpers/helpers.h"
23 #include "helpers/helpers_runtime.h"
24 #include "libabckit/include/c/statuses.h"
25
26 #include <gtest/gtest.h>
27
28 // NOLINTBEGIN(readability-magic-numbers)
29 namespace libabckit::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 class LibAbcKitCreateDynLexEnvVar : public ::testing::Test {};
38
TransformIrMain(AbckitFile * file,AbckitGraph * graph,bool isWideMode,bool isWithName)39 static void TransformIrMain(AbckitFile *file, AbckitGraph *graph, bool isWideMode, bool isWithName)
40 {
41 auto *mainBB = g_implG->gGetBasicBlock(graph, 0);
42 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
43
44 auto *firstConst = g_implG->gFindOrCreateConstantI32(graph, 0x1);
45 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
46 auto *secondConst = g_implG->gFindOrCreateConstantI32(graph, 0x3);
47 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
48
49 AbckitInst *newlexenv = nullptr;
50 if (isWithName) {
51 std::array<AbckitLiteral *, 5U> statlitarr = {
52 g_implM->createLiteralU32(file, 2), g_implM->createLiteralString(file, "x", strlen("x")),
53 g_implM->createLiteralU32(file, 0), g_implM->createLiteralString(file, "y", strlen("x")),
54 g_implM->createLiteralU32(file, 1)};
55 AbckitLiteralArray *litarr = g_implM->createLiteralArray(file, statlitarr.data(), 5U);
56 newlexenv = isWideMode ? g_dynG->iCreateWideNewlexenvwithname(graph, 0x2, litarr)
57 : g_dynG->iCreateNewlexenvwithname(graph, 0x2, litarr);
58 } else {
59 newlexenv = isWideMode ? g_dynG->iCreateWideNewlexenv(graph, 0x2) : g_dynG->iCreateNewlexenv(graph, 0x2);
60 }
61 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
62
63 AbckitInst *firstStlexvar = nullptr;
64 if (isWideMode) {
65 firstStlexvar = g_dynG->iCreateWideStlexvar(graph, firstConst, 0x0, 0x0);
66 } else {
67 firstStlexvar = g_dynG->iCreateStlexvar(graph, firstConst, 0x0, 0x0);
68 }
69 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
70 AbckitInst *secondStlexvar = nullptr;
71 if (isWideMode) {
72 secondStlexvar = g_dynG->iCreateWideStlexvar(graph, secondConst, 0x0, 0x1);
73 } else {
74 secondStlexvar = g_dynG->iCreateStlexvar(graph, secondConst, 0x0, 0x1);
75 }
76 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
77
78 auto *firstInstToInsert = helpers::FindFirstInst(graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME);
79 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
80
81 g_implG->iInsertBefore(secondStlexvar, firstInstToInsert);
82 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
83 g_implG->iInsertBefore(firstStlexvar, secondStlexvar);
84 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
85
86 g_implG->bbAddInstFront(mainBB, newlexenv);
87 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
88
89 auto *ret = helpers::FindFirstInst(graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURNUNDEFINED);
90 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
91
92 auto *poplexenv = g_dynG->iCreatePoplexenv(graph);
93 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
94
95 g_implG->iInsertBefore(poplexenv, ret);
96 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
97 }
98
TransformIrFuncs(AbckitFile * file,AbckitGraph * graph,uint32_t slot,bool isWideMode)99 static void TransformIrFuncs(AbckitFile *file, AbckitGraph *graph, uint32_t slot, bool isWideMode)
100 {
101 auto *firstConst = g_implG->gFindOrCreateConstantI32(graph, 0x1);
102 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
103
104 AbckitInst *ldlexvar = nullptr;
105 if (isWideMode) {
106 ldlexvar = g_dynG->iCreateWideLdlexvar(graph, 0x0, slot);
107 } else {
108 ldlexvar = g_dynG->iCreateLdlexvar(graph, 0x0, slot);
109 }
110 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
111 AbckitString *name = nullptr;
112 if (slot == 0x0) {
113 name = g_implM->createString(file, "x", strlen("x"));
114 } else if (slot == 0x1) {
115 name = g_implM->createString(file, "y", strlen("y"));
116 }
117 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
118 auto *throwundef = g_dynG->iCreateThrowUndefinedifholewithname(graph, ldlexvar, name);
119 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
120 auto *add2 = g_dynG->iCreateAdd2(graph, firstConst, ldlexvar);
121 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
122
123 auto *ret = helpers::FindFirstInst(graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURN);
124 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
125
126 g_implG->iInsertBefore(add2, ret);
127 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
128 g_implG->iInsertBefore(throwundef, add2);
129 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
130 g_implG->iInsertBefore(ldlexvar, throwundef);
131 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
132
133 g_implG->iSetInput(ret, add2, 0);
134 ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
135 }
136
ValidateIrMain(AbckitGraph * graph,bool isWideMode,bool isWithName)137 static void ValidateIrMain(AbckitGraph *graph, bool isWideMode, bool isWithName)
138 {
139 AbckitIsaApiDynamicOpcode newlexenv;
140 if (isWithName) {
141 newlexenv = isWideMode ? ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_NEWLEXENVWITHNAME
142 : ABCKIT_ISA_API_DYNAMIC_OPCODE_NEWLEXENVWITHNAME;
143 } else {
144 newlexenv = isWideMode ? ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_NEWLEXENV : ABCKIT_ISA_API_DYNAMIC_OPCODE_NEWLEXENV;
145 }
146 AbckitIsaApiDynamicOpcode stlexvar =
147 isWideMode ? ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_STLEXVAR : ABCKIT_ISA_API_DYNAMIC_OPCODE_STLEXVAR;
148 std::vector<helpers::BBSchema<AbckitIsaApiDynamicOpcode>> bbSchema = {
149 {{},
150 {1},
151 {
152 {0, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
153 {1, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
154 {2, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
155 {8, ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT, {}},
156 {10, ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT, {}},
157 }},
158 {{0},
159 {2},
160 {
161 {3, newlexenv, {}},
162 {6, ABCKIT_ISA_API_DYNAMIC_OPCODE_DEFINEFUNC, {}},
163 {7, ABCKIT_ISA_API_DYNAMIC_OPCODE_DEFINEFUNC, {}},
164 {9, stlexvar, {8}},
165 {11, stlexvar, {10}},
166 {12, ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, {}},
167 {13, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG0, {7}},
168 {14, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, {12, 13}},
169 {15, ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, {}},
170 {16, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG0, {6}},
171 {17, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, {15, 16}},
172 {18, ABCKIT_ISA_API_DYNAMIC_OPCODE_POPLEXENV, {}},
173 {19, ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURNUNDEFINED, {}},
174 }},
175 {{1}, {}, {}}};
176
177 helpers::VerifyGraph(graph, bbSchema);
178 }
179
ValidateIrFuncs(AbckitGraph * graph,bool isWideMode)180 static void ValidateIrFuncs(AbckitGraph *graph, bool isWideMode)
181 {
182 AbckitIsaApiDynamicOpcode ldlexvar =
183 isWideMode ? ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_LDLEXVAR : ABCKIT_ISA_API_DYNAMIC_OPCODE_LDLEXVAR;
184 std::vector<helpers::BBSchema<AbckitIsaApiDynamicOpcode>> bbSchema = {
185 {{},
186 {1},
187 {
188 {0, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
189 {1, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
190 {2, ABCKIT_ISA_API_DYNAMIC_OPCODE_PARAMETER, {}},
191 {5, ABCKIT_ISA_API_DYNAMIC_OPCODE_CONSTANT, {}},
192 }},
193 {{0},
194 {2},
195 {
196 {3, ldlexvar, {}},
197 {4, ABCKIT_ISA_API_DYNAMIC_OPCODE_THROW_UNDEFINEDIFHOLEWITHNAME, {3}},
198 {6, ABCKIT_ISA_API_DYNAMIC_OPCODE_ADD2, {5, 3}},
199 {7, ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURN, {6}},
200 }},
201 {{1}, {}, {}}};
202
203 helpers::VerifyGraph(graph, bbSchema);
204 }
205
TestLexEnvVar(bool isWideMode,bool isWithName=false)206 static void TestLexEnvVar(bool isWideMode, bool isWithName = false)
207 {
208 auto output =
209 helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ut/isa/isa_dynamic/lexenv/lexenv_dynamic.abc", "lexenv_dynamic");
210 EXPECT_TRUE(helpers::Match(output, "0\n0\n"));
211
212 helpers::TransformMethod(
213 ABCKIT_ABC_DIR "ut/isa/isa_dynamic/lexenv/lexenv_dynamic.abc",
214 ABCKIT_ABC_DIR "ut/isa/isa_dynamic/lexenv/lexenv_dynamic_modified.abc", "lexenv_dynamic.func_main_0",
215 [&](AbckitFile *file, AbckitCoreFunction * /*func*/, AbckitGraph *graph) {
216 TransformIrMain(file, graph, isWideMode, isWithName);
217 },
218 [&](AbckitGraph *graph) { ValidateIrMain(graph, isWideMode, isWithName); });
219
220 helpers::TransformMethod(
221 ABCKIT_ABC_DIR "ut/isa/isa_dynamic/lexenv/lexenv_dynamic_modified.abc",
222 ABCKIT_ABC_DIR "ut/isa/isa_dynamic/lexenv/lexenv_dynamic_modified.abc", "lexenv_dynamic.foo",
223 [&](AbckitFile *file, AbckitCoreFunction * /*func*/, AbckitGraph *graph) {
224 TransformIrFuncs(file, graph, 0x0, isWideMode);
225 },
226 [&](AbckitGraph *graph) { ValidateIrFuncs(graph, isWideMode); });
227
228 helpers::TransformMethod(
229 ABCKIT_ABC_DIR "ut/isa/isa_dynamic/lexenv/lexenv_dynamic_modified.abc",
230 ABCKIT_ABC_DIR "ut/isa/isa_dynamic/lexenv/lexenv_dynamic_modified.abc", "lexenv_dynamic.bar",
231 [&](AbckitFile *file, AbckitCoreFunction * /*func*/, AbckitGraph *graph) {
232 TransformIrFuncs(file, graph, 0x1, isWideMode);
233 },
234 [&](AbckitGraph *graph) { ValidateIrFuncs(graph, isWideMode); });
235
236 output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "ut/isa/isa_dynamic/lexenv/lexenv_dynamic_modified.abc",
237 "lexenv_dynamic");
238 EXPECT_TRUE(helpers::Match(output, "2\n4\n"));
239 }
240
241 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateNewlexenv, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynLexEnvVar,NewLexenv)242 TEST_F(LibAbcKitCreateDynLexEnvVar, NewLexenv)
243 {
244 TestLexEnvVar(false);
245 }
246
247 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateStlexvar, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynLexEnvVar,StLexvar)248 TEST_F(LibAbcKitCreateDynLexEnvVar, StLexvar)
249 {
250 TestLexEnvVar(false);
251 }
252
253 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateLdlexvar, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynLexEnvVar,LdLexvar)254 TEST_F(LibAbcKitCreateDynLexEnvVar, LdLexvar)
255 {
256 TestLexEnvVar(false);
257 }
258
259 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateWideNewlexenv, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynLexEnvVar,WideNewLexenv)260 TEST_F(LibAbcKitCreateDynLexEnvVar, WideNewLexenv)
261 {
262 TestLexEnvVar(true);
263 }
264
265 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateWideStlexvar, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynLexEnvVar,WideStLexvar)266 TEST_F(LibAbcKitCreateDynLexEnvVar, WideStLexvar)
267 {
268 TestLexEnvVar(true);
269 }
270
271 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateWideLdlexvar, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynLexEnvVar,WideLdLexvar)272 TEST_F(LibAbcKitCreateDynLexEnvVar, WideLdLexvar)
273 {
274 TestLexEnvVar(true);
275 }
276
277 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateNewlexenvwithname, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynLexEnvVar,NewLexenvWithName)278 TEST_F(LibAbcKitCreateDynLexEnvVar, NewLexenvWithName)
279 {
280 TestLexEnvVar(false, true);
281 }
282
283 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreateWideNewlexenvwithname, abc-kind=ArkTS1, category=positive,
284 // extension=c
TEST_F(LibAbcKitCreateDynLexEnvVar,WideNewLexenvWithName)285 TEST_F(LibAbcKitCreateDynLexEnvVar, WideNewLexenvWithName)
286 {
287 TestLexEnvVar(true, true);
288 }
289
290 // Test: test-kind=api, api=IsaApiDynamicImpl::iCreatePoplexenv, abc-kind=ArkTS1, category=positive, extension=c
TEST_F(LibAbcKitCreateDynLexEnvVar,PopLexenv)291 TEST_F(LibAbcKitCreateDynLexEnvVar, PopLexenv)
292 {
293 TestLexEnvVar(false);
294 }
295
296 } // namespace libabckit::test
297 // NOLINTEND(readability-magic-numbers)
298