• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 - 2023 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 "compiler/core/compilerContext.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 
27 namespace panda::es2panda::compiler {
28 
Allocator() const29 ArenaAllocator *CodeGen::Allocator() const noexcept
30 {
31     return allocator_;
32 }
33 
CatchList() const34 const ArenaVector<CatchTable *> &CodeGen::CatchList() const noexcept
35 {
36     return catchList_;
37 }
38 
TopScope() const39 const varbinder::FunctionScope *CodeGen::TopScope() const noexcept
40 {
41     return topScope_;
42 }
43 
Scope() const44 const varbinder::Scope *CodeGen::Scope() const noexcept
45 {
46     return scope_;
47 }
48 
RootNode() const49 const ir::AstNode *CodeGen::RootNode() const noexcept
50 {
51     return rootNode_;
52 }
53 
Insns()54 ArenaVector<IRNode *> &CodeGen::Insns() noexcept
55 {
56     return insns_;
57 }
58 
Insns() const59 const ArenaVector<IRNode *> &CodeGen::Insns() const noexcept
60 {
61     return insns_;
62 }
63 
NextReg() const64 VReg CodeGen::NextReg() const noexcept
65 {
66     return VReg {usedRegs_};
67 }
68 
TotalRegsNum() const69 std::uint32_t CodeGen::TotalRegsNum() const noexcept
70 {
71     return totalRegs_;
72 }
73 
LabelCount() const74 std::size_t CodeGen::LabelCount() const noexcept
75 {
76     return labelId_;
77 }
78 
Debuginfo() const79 const DebugInfo &CodeGen::Debuginfo() const noexcept
80 {
81     return debugInfo_;
82 }
83 
AllocReg()84 VReg CodeGen::AllocReg()
85 {
86     const VReg vreg(usedRegs_--);
87     SetVRegType(vreg, nullptr);
88     return vreg;
89 }
90 
AllocRegWithType(const checker::Type * const type)91 VReg CodeGen::AllocRegWithType(const checker::Type *const type)
92 {
93     const VReg vreg(usedRegs_--);
94     SetVRegType(vreg, type);
95     return vreg;
96 }
97 
SetVRegType(const VReg vreg,const checker::Type * const type)98 void CodeGen::SetVRegType(const VReg vreg, const checker::Type *const type)
99 {
100     typeMap_.insert_or_assign(vreg, type);
101 }
102 
GetVRegType(const VReg vreg) const103 const checker::Type *CodeGen::GetVRegType(const VReg vreg) const
104 {
105     const auto it = typeMap_.find(vreg);
106     return it != typeMap_.end() ? it->second : nullptr;
107 }
108 
TypeForVar(varbinder::Variable const * var) const109 checker::Type const *CodeGen::TypeForVar(varbinder::Variable const *var) const noexcept
110 {
111     return var->TsType();
112 }
113 
AllocLabel()114 Label *CodeGen::AllocLabel()
115 {
116     std::string id = std::string {Label::PREFIX} + std::to_string(labelId_++);
117     return sa_.AllocLabel(std::move(id));
118 }
119 
IsDebug() const120 bool CodeGen::IsDebug() const noexcept
121 {
122     return context_->IsDebug();
123 }
124 
ParamCount() const125 std::uint32_t CodeGen::ParamCount() const noexcept
126 {
127     if (rootNode_->IsProgram()) {
128         return 0U;
129     }
130 
131     return rootNode_->AsScriptFunction()->Params().size();
132 }
133 
FormalParametersCount() const134 std::uint32_t CodeGen::FormalParametersCount() const noexcept
135 {
136     if (rootNode_->IsProgram()) {
137         return 0U;
138     }
139 
140     ASSERT(rootNode_->IsScriptFunction());
141 
142     return rootNode_->AsScriptFunction()->FormalParamsLength();
143 }
144 
InternalParamCount() const145 std::uint32_t CodeGen::InternalParamCount() const noexcept
146 {
147     static constexpr std::uint32_t HIDDEN_PARAMS = 3U;
148     return ParamCount() + HIDDEN_PARAMS;
149 }
150 
InternalName() const151 const util::StringView &CodeGen::InternalName() const noexcept
152 {
153     return topScope_->InternalName();
154 }
155 
FunctionName() const156 const util::StringView &CodeGen::FunctionName() const noexcept
157 {
158     return topScope_->Name();
159 }
160 
VarBinder() const161 varbinder::VarBinder *CodeGen::VarBinder() const noexcept
162 {
163     return context_->VarBinder();
164 }
165 
AddLiteralBuffer(LiteralBuffer && buf)166 std::int32_t CodeGen::AddLiteralBuffer(LiteralBuffer &&buf)
167 {
168     programElement_->BuffStorage().emplace_back(std::move(buf));
169     return literalBufferIdx_++;
170 }
171 
LoadAccumulatorString(const ir::AstNode * node,const util::StringView & str)172 void CodeGen::LoadAccumulatorString(const ir::AstNode *node, const util::StringView &str)
173 {
174     sa_.Emit<LdaStr>(node, str);
175 }
176 
SetLabel(const ir::AstNode * node,Label * label)177 void CodeGen::SetLabel([[maybe_unused]] const ir::AstNode *node, Label *label)
178 {
179     sa_.AddLabel(label);
180 }
181 
Branch(const ir::AstNode * node,Label * label)182 void CodeGen::Branch(const ir::AstNode *node, Label *label)
183 {
184     sa_.Emit<Jmp>(node, label);
185 }
186 
CheckControlFlowChange() const187 bool CodeGen::CheckControlFlowChange() const
188 {
189     const auto *iter = dynamicContext_;
190 
191     while (iter != nullptr) {
192         if (iter->HasFinalizer()) {
193             return true;
194         }
195 
196         iter = iter->Prev();
197     }
198 
199     return false;
200 }
201 
ControlFlowChangeBreak(const ir::Identifier * label)202 Label *CodeGen::ControlFlowChangeBreak(const ir::Identifier *label)
203 {
204     auto *iter = dynamicContext_;
205 
206     util::StringView labelName = label != nullptr ? label->Name() : LabelTarget::BREAK_LABEL;
207     Label *breakTarget = nullptr;
208 
209     while (iter != nullptr) {
210         iter->AbortContext(ControlFlowChange::BREAK, labelName);
211         const auto *constIter = iter;
212 
213         const auto &labelTargetName = constIter->Target().BreakLabel();
214 
215         if (constIter->Target().BreakTarget() != nullptr) {
216             breakTarget = constIter->Target().BreakTarget();
217         }
218 
219         if (labelTargetName == labelName) {
220             break;
221         }
222 
223         iter = iter->Prev();
224     }
225 
226     return breakTarget;
227 }
228 
ControlFlowChangeContinue(const ir::Identifier * label)229 Label *CodeGen::ControlFlowChangeContinue(const ir::Identifier *label)
230 {
231     auto *iter = dynamicContext_;
232     util::StringView labelName = label != nullptr ? label->Name() : LabelTarget::CONTINUE_LABEL;
233     Label *continueTarget = nullptr;
234 
235     while (iter != nullptr) {
236         iter->AbortContext(ControlFlowChange::CONTINUE, labelName);
237         const auto *constIter = iter;
238 
239         const auto &labelTargetName = constIter->Target().ContinueLabel();
240 
241         if (constIter->Target().ContinueTarget() != nullptr) {
242             continueTarget = constIter->Target().ContinueTarget();
243         }
244 
245         if (labelTargetName == labelName) {
246             break;
247         }
248 
249         iter = iter->Prev();
250     }
251 
252     return continueTarget;
253 }
254 
TryDepth() const255 std::uint32_t CodeGen::TryDepth() const
256 {
257     const auto *iter = dynamicContext_;
258     std::uint32_t depth = 0;
259 
260     while (iter != nullptr) {
261         if (iter->HasTryCatch()) {
262             depth++;
263         }
264 
265         iter = iter->Prev();
266     }
267 
268     return depth;
269 }
270 
CreateCatchTable(const util::StringView exceptionType)271 CatchTable *CodeGen::CreateCatchTable(const util::StringView exceptionType)
272 {
273     auto *catchTable = allocator_->New<CatchTable>(this, TryDepth(), exceptionType);
274     catchList_.push_back(catchTable);
275     return catchTable;
276 }
277 
CreateCatchTable(const LabelPair tryLabelPair,const util::StringView exceptionType)278 CatchTable *CodeGen::CreateCatchTable(const LabelPair tryLabelPair, const util::StringView exceptionType)
279 {
280     auto *catchTable = allocator_->New<CatchTable>(this, TryDepth(), tryLabelPair, exceptionType);
281     catchList_.push_back(catchTable);
282     return catchTable;
283 }
284 
SortCatchTables()285 void CodeGen::SortCatchTables()
286 {
287     std::stable_sort(catchList_.begin(), catchList_.end(),
288                      [](const CatchTable *a, const CatchTable *b) { return b->Depth() < a->Depth(); });
289 }
290 
SetFirstStmt(const ir::Statement * stmt)291 void CodeGen::SetFirstStmt(const ir::Statement *stmt) noexcept
292 {
293     debugInfo_.firstStmt_ = stmt;
294 }
295 
Unimplemented()296 void CodeGen::Unimplemented()
297 {
298     throw Error(ErrorType::GENERIC, "", "Unimplemented code path");
299 }
300 
Sa()301 SimpleAllocator &CodeGen::Sa() noexcept
302 {
303     return sa_;
304 }
305 
Sa() const306 const SimpleAllocator &CodeGen::Sa() const noexcept
307 {
308     return sa_;
309 }
310 
Ra()311 RegAllocator &CodeGen::Ra() noexcept
312 {
313     return ra_;
314 }
315 
Ra() const316 const RegAllocator &CodeGen::Ra() const noexcept
317 {
318     return ra_;
319 }
320 
Rra()321 RangeRegAllocator &CodeGen::Rra() noexcept
322 {
323     return rra_;
324 }
325 
Rra() const326 const RangeRegAllocator &CodeGen::Rra() const noexcept
327 {
328     return rra_;
329 }
330 
Context() const331 CompilerContext *CodeGen::Context() const noexcept
332 {
333     return context_;
334 }
335 
ProgElement() const336 ProgramElement *CodeGen::ProgElement() const noexcept
337 {
338     return programElement_;
339 }
340 
GetTypeMap()341 CodeGen::TypeMap &CodeGen::GetTypeMap() noexcept
342 {
343     return typeMap_;
344 }
345 
GetTypeMap() const346 const CodeGen::TypeMap &CodeGen::GetTypeMap() const noexcept
347 {
348     return typeMap_;
349 }
350 
GetAstCompiler() const351 compiler::AstCompiler *CodeGen::GetAstCompiler() const
352 {
353     return astCompiler_;
354 }
355 }  // namespace panda::es2panda::compiler
356