• 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 <gtest/gtest.h>
17 
18 #include "libabckit/include/c/abckit.h"
19 #include "libabckit/include/c/metadata_core.h"
20 #include "libabckit/include/c/ir_core.h"
21 
22 #include "helpers/helpers.h"
23 #include "helpers/helpers_runtime.h"
24 
25 namespace libabckit::test {
26 
27 class LibAbcKitInternalTest : public ::testing::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 struct UserData {
36     AbckitString *print = nullptr;
37     AbckitString *date = nullptr;
38     AbckitString *getTime = nullptr;
39     AbckitString *str = nullptr;
40     AbckitString *consume = nullptr;
41 };
42 
43 struct ICSlotDescription {
44     AbckitIsaApiDynamicOpcode op = AbckitIsaApiDynamicOpcode::ABCKIT_ISA_API_DYNAMIC_OPCODE_INVALID;
45     int32_t icSlot = -1;
46 };
47 
CheckICSlots(AbckitBasicBlock * bb,std::vector<ICSlotDescription> icSlotDescr)48 static void CheckICSlots(AbckitBasicBlock *bb, std::vector<ICSlotDescription> icSlotDescr)
49 {
50     ASSERT_EQ(g_implG->bbGetNumberOfInstructions(bb), icSlotDescr.size());
51 
52     uint32_t counter = 0;
53     for (AbckitInst *inst = g_implG->bbGetFirstInst(bb); inst != nullptr; inst = g_implG->iGetNext(inst), ++counter) {
54         if (icSlotDescr[counter].icSlot == -1) {
55             continue;
56         }
57 
58         ASSERT_EQ(g_dynG->iGetOpcode(inst), icSlotDescr[counter].op);
59         ASSERT_NE(g_implG->iGetImmediateCount(inst), 0);
60         ASSERT_EQ(g_implG->iGetImmediate(inst, 0), icSlotDescr[counter].icSlot);
61     }
62 }
63 
TransformIrEpilog(AbckitGraph * graph,UserData * userData,AbckitInst * time,AbckitInst * callInst)64 static void TransformIrEpilog(AbckitGraph *graph, UserData *userData, AbckitInst *time, AbckitInst *callInst)
65 {
66     auto *dateClass2 = g_dynG->iCreateTryldglobalbyname(graph, userData->date);
67     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
68     g_implG->iInsertAfter(dateClass2, callInst);
69     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
70     auto *dateObj2 = g_dynG->iCreateNewobjrange(graph, 1, dateClass2);
71     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
72     g_implG->iInsertAfter(dateObj2, dateClass2);
73     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
74     auto *getTime2 = g_dynG->iCreateLdobjbyname(graph, dateObj2, userData->getTime);
75     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
76     g_implG->iInsertAfter(getTime2, dateObj2);
77     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
78     auto *time2 = g_dynG->iCreateCallthis0(graph, getTime2, dateObj2);
79     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
80     g_implG->iInsertAfter(time2, getTime2);
81     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
82     auto *consume = g_dynG->iCreateLoadString(graph, userData->consume);
83     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
84     g_implG->iInsertAfter(consume, time2);
85     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
86 
87     auto *print2 = g_dynG->iCreateTryldglobalbyname(graph, userData->print);
88     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
89     g_implG->iInsertAfter(print2, consume);
90     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
91     auto *callArg2 = g_dynG->iCreateCallarg1(graph, print2, consume);
92     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
93     g_implG->iInsertAfter(callArg2, print2);
94     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
95     auto *sub = g_dynG->iCreateSub2(graph, time, time2);
96     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
97     g_implG->iInsertAfter(sub, callArg2);
98     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
99 
100     auto *print3 = g_dynG->iCreateTryldglobalbyname(graph, userData->print);
101     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
102     g_implG->iInsertAfter(print3, sub);
103     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
104     auto *callArg3 = g_dynG->iCreateCallarg1(graph, print3, sub);
105     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
106     g_implG->iInsertAfter(callArg3, print3);
107     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
108 }
109 
TransformIr(AbckitGraph * graph,UserData * userData)110 static void TransformIr(AbckitGraph *graph, UserData *userData)
111 {
112     AbckitBasicBlock *startBB = g_implG->gGetStartBasicBlock(graph);
113     std::vector<AbckitBasicBlock *> succBBs = helpers::BBgetSuccBlocks(startBB);
114     auto *bb = succBBs[0];
115     auto *callInst = helpers::FindFirstInst(graph, ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1);
116 
117     // Prolog
118     auto *str = g_dynG->iCreateLoadString(graph, userData->str);
119     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
120     g_implG->bbAddInstFront(bb, str);
121     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
122     auto *print = g_dynG->iCreateTryldglobalbyname(graph, userData->print);
123     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
124     g_implG->iInsertAfter(print, str);
125     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
126     auto *callArg = g_dynG->iCreateCallarg1(graph, print, str);
127     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
128     g_implG->iInsertAfter(callArg, print);
129     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
130 
131     auto *dateClass = g_dynG->iCreateTryldglobalbyname(graph, userData->date);
132     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
133     g_implG->iInsertAfter(dateClass, callArg);
134     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
135     auto *dateObj = g_dynG->iCreateNewobjrange(graph, 1, dateClass);
136     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
137     g_implG->iInsertAfter(dateObj, dateClass);
138     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
139     auto *getTime = g_dynG->iCreateLdobjbyname(graph, dateObj, userData->getTime);
140     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
141     g_implG->iInsertAfter(getTime, dateObj);
142     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
143     auto *time = g_dynG->iCreateCallthis0(graph, getTime, dateObj);
144     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
145     g_implG->iInsertAfter(time, getTime);
146     ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR);
147 
148     TransformIrEpilog(graph, userData, time, callInst);
149 }
150 
151 // Test: test-kind=internal, abc-kind=ArkTS1, category=internal, extension=c
TEST_F(LibAbcKitInternalTest,LibAbcKitTestICSlotAllocator)152 TEST_F(LibAbcKitInternalTest, LibAbcKitTestICSlotAllocator)
153 {
154     auto output =
155         helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "internal/ICSlotAllocator/ICSlotAllocator.abc", "ICSlotAllocator");
156     EXPECT_TRUE(helpers::Match(output, "abckit\n"));
157 
158     helpers::TransformMethod(
159         ABCKIT_ABC_DIR "internal/ICSlotAllocator/ICSlotAllocator.abc",
160         ABCKIT_ABC_DIR "internal/ICSlotAllocator/ICSlotAllocator_modified.abc", "handle",
161         [](AbckitFile *file, AbckitCoreFunction *, AbckitGraph *graph) {
162             UserData data = {};
163             data.print = g_implM->createString(file, "print", strlen("print"));
164             data.date = g_implM->createString(file, "Date", strlen("Date"));
165             data.getTime = g_implM->createString(file, "getTime", strlen("getTime"));
166             data.str = g_implM->createString(file, "file: src/MyClass, function: MyClass.handle",
167                                              strlen("file: src/MyClass, function: MyClass.handle"));
168             data.consume = g_implM->createString(file, "Ellapsed time:", strlen("Ellapsed time:"));
169             TransformIr(graph, &data);
170         },
171         [](AbckitGraph *graph) {
172             AbckitBasicBlock *startBB = g_implG->gGetStartBasicBlock(graph);
173             // NOLINTBEGIN(readability-magic-numbers)
174             CheckICSlots(g_implG->bbGetTrueBranch(startBB), {{ABCKIT_ISA_API_DYNAMIC_OPCODE_LOADSTRING, -1},
175                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, 0XD},
176                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, 0X0},
177                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, 0XE},
178                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_NEWOBJRANGE, 0XF},
179                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_LDOBJBYNAME, 0X11},
180                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLTHIS0, 0X2},
181                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, 0X13},
182                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_LOADSTRING, -1},
183                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, 0X4},
184                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, 0X14},
185                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_NEWOBJRANGE, 0X15},
186                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_LDOBJBYNAME, 0X17},
187                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLTHIS0, 0X6},
188                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_LOADSTRING, -1},
189                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, 0X19},
190                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, 0X8},
191                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_SUB2, 0XA},
192                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_TRYLDGLOBALBYNAME, 0X1A},
193                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_CALLARG1, 0XB},
194                                                              {ABCKIT_ISA_API_DYNAMIC_OPCODE_RETURNUNDEFINED, -1}});
195             // NOLINTEND(readability-magic-numbers)
196         });
197 
198     output = helpers::ExecuteDynamicAbc(ABCKIT_ABC_DIR "internal/ICSlotAllocator/ICSlotAllocator_modified.abc",
199                                         "ICSlotAllocator");
200     EXPECT_TRUE(helpers::Match(output,
201                                "file: src/MyClass, function: MyClass.handle\n"
202                                "abckit\n"
203                                "Ellapsed time:\n"
204                                "\\d+\n"));
205 }
206 
207 }  // namespace libabckit::test
208