• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 - 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 "codeGen.h"
17 
18 #include "compiler/core/emitter.h"
19 #include "compiler/core/regAllocator.h"
20 #include "compiler/core/regScope.h"
21 #include "public/public.h"
22 #include "compiler/core/dynamicContext.h"
23 #include "compiler/base/catchTable.h"
24 #include "ir/base/scriptFunction.h"
25 #include "ir/expressions/identifier.h"
26 #include "util/options.h"
27 
28 namespace ark::es2panda::compiler {
29 
Allocator() const30 ArenaAllocator *CodeGen::Allocator() const noexcept
31 {
32     return allocator_;
33 }
34 
CatchList() const35 const ArenaVector<CatchTable *> &CodeGen::CatchList() const noexcept
36 {
37     return catchList_;
38 }
39 
TopScope() const40 const varbinder::FunctionScope *CodeGen::TopScope() const noexcept
41 {
42     return topScope_;
43 }
44 
Scope() const45 const varbinder::Scope *CodeGen::Scope() const noexcept
46 {
47     return scope_;
48 }
49 
RootNode() const50 const ir::AstNode *CodeGen::RootNode() const noexcept
51 {
52     return rootNode_;
53 }
54 
Insns()55 ArenaVector<IRNode *> &CodeGen::Insns() noexcept
56 {
57     return insns_;
58 }
59 
Insns() const60 const ArenaVector<IRNode *> &CodeGen::Insns() const noexcept
61 {
62     return insns_;
63 }
64 
NextReg() const65 VReg CodeGen::NextReg() const noexcept
66 {
67     return VReg {usedRegs_};
68 }
69 
TotalRegsNum() const70 std::uint32_t CodeGen::TotalRegsNum() const noexcept
71 {
72     return totalRegs_;
73 }
74 
LabelCount() const75 std::size_t CodeGen::LabelCount() const noexcept
76 {
77     return labelId_;
78 }
79 
Debuginfo() const80 const DebugInfo &CodeGen::Debuginfo() const noexcept
81 {
82     return debugInfo_;
83 }
84 
AllocReg()85 VReg CodeGen::AllocReg()
86 {
87     const VReg vreg(usedRegs_--);
88     SetVRegType(vreg, nullptr);
89     return vreg;
90 }
91 
AllocRegWithType(const checker::Type * const type)92 VReg CodeGen::AllocRegWithType(const checker::Type *const type)
93 {
94     const VReg vreg(usedRegs_--);
95     SetVRegType(vreg, type);
96     return vreg;
97 }
98 
SetVRegType(const VReg vreg,const checker::Type * const type)99 void CodeGen::SetVRegType(const VReg vreg, const checker::Type *const type)
100 {
101     typeMap_.insert_or_assign(vreg, type);
102 }
103 
GetVRegType(const VReg vreg) const104 const checker::Type *CodeGen::GetVRegType(const VReg vreg) const
105 {
106     const auto it = typeMap_.find(vreg);
107     return it != typeMap_.end() ? it->second : nullptr;
108 }
109 
TypeForVar(varbinder::Variable const * var) const110 checker::Type const *CodeGen::TypeForVar(varbinder::Variable const *var) const noexcept
111 {
112     return var->TsType();
113 }
114 
AllocLabel()115 Label *CodeGen::AllocLabel()
116 {
117     std::string id = std::string {Label::PREFIX} + std::to_string(labelId_++);
118     return sa_.AllocLabel(std::move(id));
119 }
120 
IsDebug() const121 bool CodeGen::IsDebug() const noexcept
122 {
123     return context_->config->options->IsDebugInfo();
124 }
125 
ParamCount() const126 std::uint32_t CodeGen::ParamCount() const noexcept
127 {
128     if (rootNode_->IsProgram()) {
129         return 0U;
130     }
131 
132     return rootNode_->AsScriptFunction()->Params().size();
133 }
134 
FormalParametersCount() const135 std::uint32_t CodeGen::FormalParametersCount() const noexcept
136 {
137     if (rootNode_->IsProgram()) {
138         return 0U;
139     }
140 
141     ES2PANDA_ASSERT(rootNode_->IsScriptFunction());
142 
143     return rootNode_->AsScriptFunction()->FormalParamsLength();
144 }
145 
InternalParamCount() const146 std::uint32_t CodeGen::InternalParamCount() const noexcept
147 {
148     static constexpr std::uint32_t HIDDEN_PARAMS = 3U;
149     return ParamCount() + HIDDEN_PARAMS;
150 }
151 
InternalName() const152 const util::StringView &CodeGen::InternalName() const noexcept
153 {
154     return topScope_->InternalName();
155 }
156 
FunctionName() const157 const util::StringView &CodeGen::FunctionName() const noexcept
158 {
159     return topScope_->Name();
160 }
161 
VarBinder() const162 varbinder::VarBinder *CodeGen::VarBinder() const noexcept
163 {
164     return context_->parserProgram->VarBinder();
165 }
166 
AddLiteralBuffer(LiteralBuffer && buf)167 std::uint32_t CodeGen::AddLiteralBuffer(LiteralBuffer &&buf)
168 {
169     programElement_->BuffStorage().emplace_back(std::move(buf));
170     return literalBufferIdx_++;
171 }
172 
LoadAccumulatorString(const ir::AstNode * node,const util::StringView & str)173 void CodeGen::LoadAccumulatorString(const ir::AstNode *node, const util::StringView &str)
174 {
175     sa_.Emit<LdaStr>(node, str);
176 }
177 
SetLabel(const ir::AstNode * node,Label * label)178 void CodeGen::SetLabel([[maybe_unused]] const ir::AstNode *node, Label *label)
179 {
180     sa_.AddLabel(label);
181 }
182 
Branch(const ir::AstNode * node,Label * label)183 void CodeGen::Branch(const ir::AstNode *node, Label *label)
184 {
185     sa_.Emit<Jmp>(node, label);
186 }
187 
CheckControlFlowChange() const188 bool CodeGen::CheckControlFlowChange() const
189 {
190     const auto *iter = dynamicContext_;
191 
192     while (iter != nullptr) {
193         if (iter->HasFinalizer()) {
194             return true;
195         }
196 
197         iter = iter->Prev();
198     }
199 
200     return false;
201 }
202 
ControlFlowChangeBreak(const ir::Identifier * label)203 Label *CodeGen::ControlFlowChangeBreak(const ir::Identifier *label)
204 {
205     auto *iter = dynamicContext_;
206 
207     util::StringView labelName = label != nullptr ? label->Name() : LabelTarget::BREAK_LABEL;
208     Label *breakTarget = nullptr;
209 
210     while (iter != nullptr) {
211         iter->AbortContext(ControlFlowChange::BREAK, labelName);
212         const auto *constIter = iter;
213 
214         const auto &labelTargetName = constIter->Target().BreakLabel();
215 
216         if (constIter->Target().BreakTarget() != nullptr) {
217             breakTarget = constIter->Target().BreakTarget();
218         }
219 
220         if (labelTargetName == labelName) {
221             break;
222         }
223 
224         iter = iter->Prev();
225     }
226 
227     return breakTarget;
228 }
229 
ControlFlowChangeContinue(const ir::Identifier * label)230 Label *CodeGen::ControlFlowChangeContinue(const ir::Identifier *label)
231 {
232     auto *iter = dynamicContext_;
233     util::StringView labelName = label != nullptr ? label->Name() : LabelTarget::CONTINUE_LABEL;
234     Label *continueTarget = nullptr;
235 
236     while (iter != nullptr) {
237         iter->AbortContext(ControlFlowChange::CONTINUE, labelName);
238         const auto *constIter = iter;
239 
240         const auto &labelTargetName = constIter->Target().ContinueLabel();
241 
242         if (constIter->Target().ContinueTarget() != nullptr) {
243             continueTarget = constIter->Target().ContinueTarget();
244         }
245 
246         if (labelTargetName == labelName) {
247             break;
248         }
249 
250         iter = iter->Prev();
251     }
252 
253     return continueTarget;
254 }
255 
TryDepth() const256 std::uint32_t CodeGen::TryDepth() const
257 {
258     const auto *iter = dynamicContext_;
259     std::uint32_t depth = 0;
260 
261     while (iter != nullptr) {
262         if (iter->HasTryCatch()) {
263             depth++;
264         }
265 
266         iter = iter->Prev();
267     }
268 
269     return depth;
270 }
271 
CreateCatchTable(const util::StringView exceptionType)272 CatchTable *CodeGen::CreateCatchTable(const util::StringView exceptionType)
273 {
274     auto *catchTable = allocator_->New<CatchTable>(this, TryDepth(), exceptionType);
275     catchList_.push_back(catchTable);
276     return catchTable;
277 }
278 
CreateCatchTable(const LabelPair tryLabelPair,const util::StringView exceptionType)279 CatchTable *CodeGen::CreateCatchTable(const LabelPair tryLabelPair, const util::StringView exceptionType)
280 {
281     auto *catchTable = allocator_->New<CatchTable>(this, TryDepth(), tryLabelPair, exceptionType);
282     catchList_.push_back(catchTable);
283     return catchTable;
284 }
285 
SortCatchTables()286 void CodeGen::SortCatchTables()
287 {
288     std::stable_sort(catchList_.begin(), catchList_.end(),
289                      [](const CatchTable *a, const CatchTable *b) { return b->Depth() < a->Depth(); });
290 }
291 
SetFirstStmt(const ir::Statement * stmt)292 void CodeGen::SetFirstStmt(const ir::Statement *stmt) noexcept
293 {
294     debugInfo_.firstStmt_ = stmt;
295 }
296 
Unimplemented()297 void CodeGen::Unimplemented()
298 {
299     // Unimplemented code path
300     ES2PANDA_UNREACHABLE();
301 }
302 
Sa()303 SimpleAllocator &CodeGen::Sa() noexcept
304 {
305     return sa_;
306 }
307 
Sa() const308 const SimpleAllocator &CodeGen::Sa() const noexcept
309 {
310     return sa_;
311 }
312 
Ra()313 RegAllocator &CodeGen::Ra() noexcept
314 {
315     return ra_;
316 }
317 
Ra() const318 const RegAllocator &CodeGen::Ra() const noexcept
319 {
320     return ra_;
321 }
322 
Rra()323 RangeRegAllocator &CodeGen::Rra() noexcept
324 {
325     return rra_;
326 }
327 
Rra() const328 const RangeRegAllocator &CodeGen::Rra() const noexcept
329 {
330     return rra_;
331 }
332 
Context() const333 public_lib::Context *CodeGen::Context() const noexcept
334 {
335     return context_;
336 }
337 
ProgElement() const338 ProgramElement *CodeGen::ProgElement() const noexcept
339 {
340     return programElement_;
341 }
342 
GetTypeMap()343 CodeGen::TypeMap &CodeGen::GetTypeMap() noexcept
344 {
345     return typeMap_;
346 }
347 
GetTypeMap() const348 const CodeGen::TypeMap &CodeGen::GetTypeMap() const noexcept
349 {
350     return typeMap_;
351 }
352 
GetAstCompiler() const353 compiler::AstCompiler *CodeGen::GetAstCompiler() const
354 {
355     return astCompiler_;
356 }
357 }  // namespace ark::es2panda::compiler
358