1/* 2 * Copyright (c) 2021 - 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 "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 27namespace ark::es2panda::compiler { 28 29ArenaAllocator *CodeGen::Allocator() const noexcept 30{ 31 return allocator_; 32} 33 34const ArenaVector<CatchTable *> &CodeGen::CatchList() const noexcept 35{ 36 return catchList_; 37} 38 39const varbinder::FunctionScope *CodeGen::TopScope() const noexcept 40{ 41 return topScope_; 42} 43 44const varbinder::Scope *CodeGen::Scope() const noexcept 45{ 46 return scope_; 47} 48 49const ir::AstNode *CodeGen::RootNode() const noexcept 50{ 51 return rootNode_; 52} 53 54ArenaVector<IRNode *> &CodeGen::Insns() noexcept 55{ 56 return insns_; 57} 58 59const ArenaVector<IRNode *> &CodeGen::Insns() const noexcept 60{ 61 return insns_; 62} 63 64VReg CodeGen::NextReg() const noexcept 65{ 66 return VReg {usedRegs_}; 67} 68 69std::uint32_t CodeGen::TotalRegsNum() const noexcept 70{ 71 return totalRegs_; 72} 73 74std::size_t CodeGen::LabelCount() const noexcept 75{ 76 return labelId_; 77} 78 79const DebugInfo &CodeGen::Debuginfo() const noexcept 80{ 81 return debugInfo_; 82} 83 84VReg CodeGen::AllocReg() 85{ 86 const VReg vreg(usedRegs_--); 87 SetVRegType(vreg, nullptr); 88 return vreg; 89} 90 91VReg CodeGen::AllocRegWithType(const checker::Type *const type) 92{ 93 const VReg vreg(usedRegs_--); 94 SetVRegType(vreg, type); 95 return vreg; 96} 97 98void CodeGen::SetVRegType(const VReg vreg, const checker::Type *const type) 99{ 100 typeMap_.insert_or_assign(vreg, type); 101} 102 103const 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 109checker::Type const *CodeGen::TypeForVar(varbinder::Variable const *var) const noexcept 110{ 111 return var->TsType(); 112} 113 114Label *CodeGen::AllocLabel() 115{ 116 std::string id = std::string {Label::PREFIX} + std::to_string(labelId_++); 117 return sa_.AllocLabel(std::move(id)); 118} 119 120bool CodeGen::IsDebug() const noexcept 121{ 122 return context_->config->options->CompilerOptions().isDebug; 123} 124 125std::uint32_t CodeGen::ParamCount() const noexcept 126{ 127 if (rootNode_->IsProgram()) { 128 return 0U; 129 } 130 131 return rootNode_->AsScriptFunction()->Params().size(); 132} 133 134std::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 145std::uint32_t CodeGen::InternalParamCount() const noexcept 146{ 147 static constexpr std::uint32_t HIDDEN_PARAMS = 3U; 148 return ParamCount() + HIDDEN_PARAMS; 149} 150 151const util::StringView &CodeGen::InternalName() const noexcept 152{ 153 return topScope_->InternalName(); 154} 155 156const util::StringView &CodeGen::FunctionName() const noexcept 157{ 158 return topScope_->Name(); 159} 160 161varbinder::VarBinder *CodeGen::VarBinder() const noexcept 162{ 163 return context_->parserProgram->VarBinder(); 164} 165 166std::uint32_t CodeGen::AddLiteralBuffer(LiteralBuffer &&buf) 167{ 168 programElement_->BuffStorage().emplace_back(std::move(buf)); 169 return literalBufferIdx_++; 170} 171 172void CodeGen::LoadAccumulatorString(const ir::AstNode *node, const util::StringView &str) 173{ 174 sa_.Emit<LdaStr>(node, str); 175} 176 177void CodeGen::SetLabel([[maybe_unused]] const ir::AstNode *node, Label *label) 178{ 179 sa_.AddLabel(label); 180} 181 182void CodeGen::Branch(const ir::AstNode *node, Label *label) 183{ 184 sa_.Emit<Jmp>(node, label); 185} 186 187bool 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 202Label *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 229Label *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 255std::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 271CatchTable *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 278CatchTable *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 285void 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 291void CodeGen::SetFirstStmt(const ir::Statement *stmt) noexcept 292{ 293 debugInfo_.firstStmt_ = stmt; 294} 295 296void CodeGen::Unimplemented() 297{ 298 throw Error(ErrorType::GENERIC, "", "Unimplemented code path"); 299} 300 301SimpleAllocator &CodeGen::Sa() noexcept 302{ 303 return sa_; 304} 305 306const SimpleAllocator &CodeGen::Sa() const noexcept 307{ 308 return sa_; 309} 310 311RegAllocator &CodeGen::Ra() noexcept 312{ 313 return ra_; 314} 315 316const RegAllocator &CodeGen::Ra() const noexcept 317{ 318 return ra_; 319} 320 321RangeRegAllocator &CodeGen::Rra() noexcept 322{ 323 return rra_; 324} 325 326const RangeRegAllocator &CodeGen::Rra() const noexcept 327{ 328 return rra_; 329} 330 331public_lib::Context *CodeGen::Context() const noexcept 332{ 333 return context_; 334} 335 336ProgramElement *CodeGen::ProgElement() const noexcept 337{ 338 return programElement_; 339} 340 341CodeGen::TypeMap &CodeGen::GetTypeMap() noexcept 342{ 343 return typeMap_; 344} 345 346const CodeGen::TypeMap &CodeGen::GetTypeMap() const noexcept 347{ 348 return typeMap_; 349} 350 351compiler::AstCompiler *CodeGen::GetAstCompiler() const 352{ 353 return astCompiler_; 354} 355} // namespace ark::es2panda::compiler 356