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 "regScope.h" 17 18#include "varbinder/varbinder.h" 19#include "varbinder/scope.h" 20#include "varbinder/variable.h" 21#include "compiler/base/hoisting.h" 22#include "compiler/core/codeGen.h" 23#include "compiler/core/pandagen.h" 24#include "compiler/core/moduleContext.h" 25 26namespace ark::es2panda::compiler { 27// RegScope 28 29RegScope::RegScope(CodeGen *cg) : cg_(cg), regBase_(cg_->usedRegs_) {} 30 31RegScope::~RegScope() 32{ 33 cg_->totalRegs_ = std::min(cg_->totalRegs_, cg_->usedRegs_); 34 cg_->usedRegs_ = regBase_; 35} 36 37void RegScope::DebuggerCloseScope() 38{ 39 if (!cg_->IsDebug()) { 40 return; 41 } 42 43 cg_->scope_->SetScopeEnd(cg_->insns_.back()); 44} 45 46// LocalRegScope 47 48LocalRegScope::LocalRegScope(PandaGen *pg) : RegScope(pg) {} 49 50LocalRegScope::LocalRegScope(CodeGen *cg, varbinder::Scope *scope) : RegScope(cg) 51{ 52 prevScope_ = cg_->scope_; 53 cg_->scope_ = scope; 54 55 for (const auto &[_, var] : scope->OrderedBindings(cg_->Allocator())) { 56 (void)_; 57 if (!var->LexicalBound() && var->IsLocalVariable()) { 58 var->AsLocalVariable()->BindVReg(cg_->AllocReg()); 59 } 60 } 61 62 if (cg_->IsDebug() && !cg_->insns_.empty()) { 63 cg_->scope_->SetScopeStart(cg_->insns_.back()); 64 cg_->debugInfo_.VariableDebugInfo().push_back(cg_->scope_); 65 } 66} 67 68LocalRegScope::LocalRegScope(PandaGen *pg, varbinder::Scope *scope) : LocalRegScope(static_cast<CodeGen *>(pg), scope) 69{ 70 Hoisting::Hoist(pg); 71} 72 73LocalRegScope::~LocalRegScope() 74{ 75 if (prevScope_ == nullptr) { 76 return; 77 } 78 79 DebuggerCloseScope(); 80 81 cg_->scope_ = prevScope_; 82} 83 84// FunctionRegScope 85 86FunctionRegScope::FunctionRegScope(CodeGen *cg) : RegScope(cg) 87{ 88 InitializeParams([](varbinder::LocalVariable *const param, const VReg paramReg) { param->BindVReg(paramReg); }); 89} 90 91void FunctionRegScope::InitializeParams(const StoreParamCb &cb) 92{ 93 const auto *funcScope = cg_->Scope()->AsFunctionVariableScope(); 94 95 VReg paramReg = VReg(VReg::PARAM_START); 96 for (auto *param : funcScope->ParamScope()->Params()) { 97 cg_->SetVRegType(paramReg, cg_->TypeForVar(param)); 98 cb(param, paramReg); 99 paramReg++; 100 } 101 102 for (const auto it : funcScope->OrderedBindings(cg_->Allocator())) { 103 auto *const var = std::get<1>(it); 104 if (var->Declaration()->IsParameterDecl() || var->Declaration()->IsTypeAliasDecl()) { 105 continue; 106 } 107 108 if (!var->LexicalBound() && var->IsLocalVariable()) { 109 const auto vreg = cg_->AllocReg(); 110 var->AsLocalVariable()->BindVReg(vreg); 111 } 112 } 113 114 if (cg_->IsDebug()) { 115 cg_->debugInfo_.VariableDebugInfo().push_back(funcScope); 116 } 117} 118 119FunctionRegScope::FunctionRegScope(PandaGen *pg) : RegScope(pg), envScope_(pg->Allocator()->New<EnvScope>()) 120{ 121 ASSERT(cg_->Scope()->IsFunctionVariableScope()); 122 ASSERT(cg_->NextReg().GetIndex() == VReg::REG_START); 123 124 VReg lexEnv = pg->AllocReg(); 125 envScope_->Initialize(pg, lexEnv); 126 127 const auto *funcScope = pg->Scope()->AsFunctionVariableScope(); 128 const auto *node = pg->RootNode(); 129 130 if (funcScope->NeedLexEnv()) { 131 pg->NewLexEnv(node, funcScope->LexicalSlots()); 132 } else { 133 pg->LdLexEnv(node); 134 } 135 136 pg->StoreAccumulator(node, lexEnv); 137 138 InitializeParams([pg, node](varbinder::LocalVariable *const param, const VReg paramReg) { 139 if (param->LexicalBound()) { 140 pg->LoadAccumulator(node, paramReg); 141 pg->StoreLexicalVar(node, 0, param->LexIdx()); 142 } else { 143 param->BindVReg(paramReg); 144 } 145 }); 146 147 pg->LoadAccFromArgs(pg->rootNode_); 148 149 if (funcScope->IsModuleScope()) { 150 ModuleContext::Compile(pg, pg->scope_->AsModuleScope()); 151 } 152 153 Hoisting::Hoist(pg); 154} 155 156FunctionRegScope::~FunctionRegScope() 157{ 158 if (cg_->IsDebug() && !cg_->insns_.empty()) { 159 cg_->topScope_->SetScopeStart(cg_->insns_.front()); 160 DebuggerCloseScope(); 161 } 162 163 if (envScope_ != nullptr) { 164 envScope_->~EnvScope(); 165 } 166} 167} // namespace ark::es2panda::compiler 168