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/src/adapter_static/metadata_modify_static.h"
17 #include "inst.h"
18 #include "libabckit/src/metadata_inspect_impl.h"
19 #include "libabckit/src/ir_impl.h"
20 #include "libabckit/src/logger.h"
21 #include "libabckit/src/statuses_impl.h"
22
23 #include "libabckit/src/codegen/codegen_static.h"
24
25 #include "optimizer/analysis/liveness_analyzer.h"
26 #include "optimizer/analysis/rpo.h"
27 #include "src/adapter_static/metadata_inspect_static.h"
28 #include "src/adapter_static/abckit_static.h"
29 #include "src/adapter_static/helpers_static.h"
30 #include "static_core/assembler/assembly-program.h"
31
32 #include "static_core/compiler/optimizer/ir/graph_checker.h"
33 #include "static_core/compiler/optimizer/ir/graph_cloner.h"
34 #include "static_core/compiler/optimizer/analysis/loop_analyzer.h"
35 #include "static_core/compiler/optimizer/optimizations/cleanup.h"
36 #include "static_core/compiler/optimizer/optimizations/move_constants.h"
37 #include "static_core/compiler/optimizer/optimizations/lowering.h"
38 #include "static_core/bytecode_optimizer/reg_encoder.h"
39
40 #include <cstdint>
41 #include <string>
42
43 // CC-OFFNXT(WordsTool.95) sensitive word conflict
44 // NOLINTNEXTLINE(google-build-using-namespace)
45 using namespace ark;
46
47 namespace libabckit {
48
49 // ========================================
50 // Create / Update
51 // ========================================
CreateStringStatic(AbckitFile * file,const char * value,size_t len)52 AbckitString *CreateStringStatic(AbckitFile *file, const char *value, size_t len)
53 {
54 LIBABCKIT_LOG_FUNC;
55 LIBABCKIT_LOG(DEBUG) << "\"" << value << "\"" << '\n';
56 auto *prog = file->GetStaticProgram();
57 const auto &[progValueIter, _] = prog->strings.insert(std::string(value, len));
58 const auto &progValue = *progValueIter;
59 auto &strings = file->strings;
60
61 if (strings.find(progValue) != strings.end()) {
62 return strings.at(progValue).get();
63 }
64
65 auto s = std::make_unique<AbckitString>();
66 s->impl = progValue;
67 strings.insert({progValue, std::move(s)});
68 return strings[progValue].get();
69 }
70
FunctionSetGraphStatic(AbckitCoreFunction * function,AbckitGraph * graph)71 void FunctionSetGraphStatic(AbckitCoreFunction *function, AbckitGraph *graph)
72 {
73 LIBABCKIT_LOG_FUNC;
74 LIBABCKIT_LOG_FUNC;
75
76 auto *func = function->GetArkTSImpl()->GetStaticImpl();
77
78 auto graphImpl =
79 compiler::GraphCloner(graph->impl, graph->impl->GetAllocator(), graph->impl->GetLocalAllocator()).CloneGraph();
80
81 graphImpl->RemoveUnreachableBlocks();
82 GraphInvalidateAnalyses(graphImpl);
83 CheckInvalidOpcodes(graphImpl, false);
84
85 LIBABCKIT_LOG(DEBUG) << "======================== BEFORE CODEGEN ========================\n";
86 LIBABCKIT_LOG_DUMP(func->DebugDump(), DEBUG);
87 LIBABCKIT_LOG(DEBUG) << "============================================\n";
88
89 LIBABCKIT_LOG_DUMP(graphImpl->Dump(&std::cerr), DEBUG);
90
91 LIBABCKIT_LOG(DEBUG) << "============================================\n";
92
93 if (!ark::compiler::GraphChecker(graphImpl).Check()) {
94 LIBABCKIT_LOG(DEBUG) << func->name << ": Graph Verifier failed!\n";
95 statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_BAD_ARGUMENT);
96 return;
97 }
98
99 graphImpl->RunPass<compiler::Lowering>();
100
101 graphImpl->RunPass<compiler::Cleanup>(false);
102
103 graphImpl->RunPass<compiler::MoveConstants>();
104
105 if (!AllocateRegisters(graphImpl, CodeGenStatic::RESERVED_REG)) {
106 LIBABCKIT_LOG(DEBUG) << func->name << ": RegAllocGraphColoring failed!\n";
107 statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR);
108 return;
109 }
110
111 if (!graphImpl->RunPass<bytecodeopt::RegEncoder>()) {
112 LIBABCKIT_LOG(DEBUG) << func->name << ": RegEncoder failed!\n";
113 statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR);
114 return;
115 }
116
117 if (!graphImpl->RunPass<CodeGenStatic>(func, graph->irInterface)) {
118 LIBABCKIT_LOG(DEBUG) << func->name << ": Code generation failed!\n";
119 statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR);
120 return;
121 }
122
123 func->valueOfFirstParam = static_cast<int64_t>(graphImpl->GetStackSlotsCount()) - 1L;
124 func->regsNum = static_cast<size_t>(func->valueOfFirstParam + 1U);
125
126 LIBABCKIT_LOG(DEBUG) << "======================== AFTER CODEGEN ========================\n";
127 LIBABCKIT_LOG_DUMP(func->DebugDump(), DEBUG);
128 LIBABCKIT_LOG(DEBUG) << "============================================\n";
129 }
130
FindOrCreateLiteralBoolStatic(AbckitFile * file,bool value)131 AbckitLiteral *FindOrCreateLiteralBoolStatic(AbckitFile *file, bool value)
132 {
133 LIBABCKIT_LOG_FUNC;
134 return FindOrCreateLiteralBoolStaticImpl(file, value);
135 }
136
FindOrCreateLiteralU8Static(AbckitFile * file,uint8_t value)137 AbckitLiteral *FindOrCreateLiteralU8Static(AbckitFile *file, uint8_t value)
138 {
139 LIBABCKIT_LOG_FUNC;
140 return FindOrCreateLiteralU8StaticImpl(file, value);
141 }
142
FindOrCreateLiteralU16Static(AbckitFile * file,uint16_t value)143 AbckitLiteral *FindOrCreateLiteralU16Static(AbckitFile *file, uint16_t value)
144 {
145 LIBABCKIT_LOG_FUNC;
146 return FindOrCreateLiteralU16StaticImpl(file, value);
147 }
148
FindOrCreateLiteralMethodAffiliateStatic(AbckitFile * file,uint16_t value)149 AbckitLiteral *FindOrCreateLiteralMethodAffiliateStatic(AbckitFile *file, uint16_t value)
150 {
151 LIBABCKIT_LOG_FUNC;
152 return FindOrCreateLiteralMethodAffiliateStaticImpl(file, value);
153 }
154
FindOrCreateLiteralU32Static(AbckitFile * file,uint32_t value)155 AbckitLiteral *FindOrCreateLiteralU32Static(AbckitFile *file, uint32_t value)
156 {
157 LIBABCKIT_LOG_FUNC;
158 return FindOrCreateLiteralU32StaticImpl(file, value);
159 }
160
FindOrCreateLiteralU64Static(AbckitFile * file,uint64_t value)161 AbckitLiteral *FindOrCreateLiteralU64Static(AbckitFile *file, uint64_t value)
162 {
163 LIBABCKIT_LOG_FUNC;
164 return FindOrCreateLiteralU64StaticImpl(file, value);
165 }
166
FindOrCreateLiteralFloatStatic(AbckitFile * file,float value)167 AbckitLiteral *FindOrCreateLiteralFloatStatic(AbckitFile *file, float value)
168 {
169 LIBABCKIT_LOG_FUNC;
170 return FindOrCreateLiteralFloatStaticImpl(file, value);
171 }
172
FindOrCreateLiteralDoubleStatic(AbckitFile * file,double value)173 AbckitLiteral *FindOrCreateLiteralDoubleStatic(AbckitFile *file, double value)
174 {
175 LIBABCKIT_LOG_FUNC;
176 return FindOrCreateLiteralDoubleStaticImpl(file, value);
177 }
178
FindOrCreateLiteralStringStatic(AbckitFile * file,const char * value,size_t len)179 AbckitLiteral *FindOrCreateLiteralStringStatic(AbckitFile *file, const char *value, size_t len)
180 {
181 LIBABCKIT_LOG_FUNC;
182 return FindOrCreateLiteralStringStaticImpl(file, std::string(value, len));
183 }
184
FindOrCreateLiteralMethodStatic(AbckitFile * file,AbckitCoreFunction * function)185 AbckitLiteral *FindOrCreateLiteralMethodStatic(AbckitFile *file, AbckitCoreFunction *function)
186 {
187 LIBABCKIT_LOG_FUNC;
188 return FindOrCreateLiteralMethodStaticImpl(file, GetMangleFuncName(function));
189 }
190
EmplaceType(ark::pandasm::Program * prog,AbckitLiteral * value)191 static void EmplaceType(ark::pandasm::Program *prog, AbckitLiteral *value)
192 {
193 switch (LiteralGetTagStatic(value)) {
194 case ABCKIT_LITERAL_TAG_BOOL:
195 prog->arrayTypes.emplace(pandasm::Type("u1", 1));
196 break;
197 case ABCKIT_LITERAL_TAG_BYTE:
198 prog->arrayTypes.emplace(pandasm::Type("u8", 1));
199 break;
200 case ABCKIT_LITERAL_TAG_SHORT:
201 prog->arrayTypes.emplace(pandasm::Type("u16", 1));
202 break;
203 case ABCKIT_LITERAL_TAG_INTEGER:
204 prog->arrayTypes.emplace(pandasm::Type("u32", 1));
205 break;
206 case ABCKIT_LITERAL_TAG_LONG:
207 prog->arrayTypes.emplace(pandasm::Type("u64", 1));
208 break;
209 case ABCKIT_LITERAL_TAG_FLOAT:
210 prog->arrayTypes.emplace(pandasm::Type("f32", 1));
211 break;
212 case ABCKIT_LITERAL_TAG_DOUBLE:
213 prog->arrayTypes.emplace(pandasm::Type("f64", 1));
214 break;
215 case ABCKIT_LITERAL_TAG_STRING:
216 prog->arrayTypes.emplace(pandasm::Type("reference", 1));
217 break;
218 default:
219 UNREACHABLE();
220 }
221 }
222
CreateLiteralArrayStatic(AbckitFile * file,AbckitLiteral ** value,size_t size)223 AbckitLiteralArray *CreateLiteralArrayStatic(AbckitFile *file, AbckitLiteral **value, size_t size)
224 {
225 LIBABCKIT_LOG_FUNC;
226 auto *prog = file->GetStaticProgram();
227 EmplaceType(prog, *value);
228 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
229 auto lit = *reinterpret_cast<pandasm::LiteralArray::Literal *>(value[0]->val.get());
230 pandasm::LiteralArray::Literal tagLit;
231 tagLit.tag = panda_file::LiteralTag::TAGVALUE;
232 tagLit.value = static_cast<uint8_t>(lit.tag);
233 std::vector<pandasm::LiteralArray::Literal> stdLitArr;
234 stdLitArr.emplace_back(tagLit);
235
236 pandasm::LiteralArray::Literal len;
237 len.tag = panda_file::LiteralTag::INTEGER;
238 len.value = static_cast<uint32_t>(size);
239 stdLitArr.emplace_back(len);
240
241 prog->arrayTypes.emplace(pandasm::Type("u32", 1));
242 for (size_t i = 0; i < size; i++) {
243 // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
244 auto lit = *reinterpret_cast<pandasm::LiteralArray::Literal *>(value[i]->val.get());
245 stdLitArr.emplace_back(lit);
246 }
247
248 // NOLINTNEXTLINE(cert-msc51-cpp)
249 uint32_t arrayOffset = 0;
250 while (prog->literalarrayTable.find(std::to_string(arrayOffset)) != prog->literalarrayTable.end()) {
251 arrayOffset++;
252 }
253 auto arrayName = std::to_string(arrayOffset);
254
255 prog->literalarrayTable.emplace(arrayName, pandasm::LiteralArray());
256 pandasm::LiteralArray &arrImpl = prog->literalarrayTable[arrayName];
257 arrImpl.literals = std::move(stdLitArr);
258
259 auto litarr = std::make_unique<AbckitLiteralArray>(file, &arrImpl);
260 return file->litarrs.emplace_back(std::move(litarr)).get();
261 }
262
FindOrCreateValueU1Static(AbckitFile * file,bool value)263 AbckitValue *FindOrCreateValueU1Static(AbckitFile *file, bool value)
264 {
265 LIBABCKIT_LOG_FUNC;
266 return FindOrCreateValueU1StaticImpl(file, value);
267 }
268
FindOrCreateValueDoubleStatic(AbckitFile * file,double value)269 AbckitValue *FindOrCreateValueDoubleStatic(AbckitFile *file, double value)
270 {
271 LIBABCKIT_LOG_FUNC;
272 return FindOrCreateValueDoubleStaticImpl(file, value);
273 }
274
FindOrCreateValueStringStatic(AbckitFile * file,const char * value,size_t len)275 AbckitValue *FindOrCreateValueStringStatic(AbckitFile *file, const char *value, size_t len)
276 {
277 LIBABCKIT_LOG_FUNC;
278 return FindOrCreateValueStringStaticImpl(file, std::string(value, len));
279 }
280
281 } // namespace libabckit
282