1 /*
2  * Copyright (c) 2021-2022 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 <binder/binder.h>
19 #include <binder/scope.h>
20 #include <binder/variable.h>
21 #include <compiler/base/hoisting.h>
22 #include <compiler/core/compilerContext.h>
23 #include <compiler/core/pandagen.h>
24 
25 namespace panda::es2panda::compiler {
26 
27 // RegScope
28 
RegScope(PandaGen *pg)29 RegScope::RegScope(PandaGen *pg) : pg_(pg), regBase_(pg_->usedRegs_) {}
30 
~RegScope()31 RegScope::~RegScope()
32 {
33     pg_->totalRegs_ = std::max(pg_->totalRegs_, pg_->usedRegs_);
34     pg_->usedRegs_ = regBase_;
35 }
36 
DebuggerCloseScope()37 void RegScope::DebuggerCloseScope()
38 {
39     if (!pg_->IsDebug()) {
40         return;
41     }
42 
43     if (insStartIndex_ < pg_->insns_.size()) {
44         auto it = pg_->insns_.begin();
45         std::advance(it, insStartIndex_);
46         pg_->scope_->SetScopeStart(*it);
47     } else {
48         pg_->scope_->SetScopeStart(pg_->insns_.back());
49     }
50 
51     pg_->scope_->SetScopeEnd(pg_->insns_.back());
52 }
53 
54 // LocalRegScope
55 
LocalRegScope(PandaGen *pg)56 LocalRegScope::LocalRegScope(PandaGen *pg) : RegScope(pg) {}
57 
LocalRegScope(PandaGen *pg, binder::Scope *scope)58 LocalRegScope::LocalRegScope(PandaGen *pg, binder::Scope *scope) : RegScope(pg)
59 {
60     prevScope_ = pg_->scope_;
61     pg_->scope_ = scope;
62 
63     for (const auto &[_, var] : scope->Bindings()) {
64         (void)_;
65         if (!var->LexicalBound() && var->IsLocalVariable()) {
66             var->AsLocalVariable()->BindVReg(pg->AllocReg());
67         }
68     }
69 
70     auto *debugInfo = &pg_->debugInfo_.variableDebugInfo;
71     if (pg_->IsDebug() && std::find(debugInfo->begin(), debugInfo->end(), pg_->scope_) == debugInfo->end()) {
72         debugInfo->push_back(pg_->scope_);
73     }
74     insStartIndex_ = pg_->insns_.size();
75 
76     Hoisting::Hoist(pg_);
77 }
78 
79 LocalRegScope::~LocalRegScope() noexcept
80 {
81     if (!prevScope_) {
82         return;
83     }
84 
85     DebuggerCloseScope();
86 
87     pg_->scope_ = prevScope_;
88 }
89 
90 // FunctionRegScope
91 
FunctionRegScope(PandaGen *pg)92 FunctionRegScope::FunctionRegScope(PandaGen *pg) : RegScope(pg), envScope_(pg->Allocator()->New<EnvScope>())
93 {
94     ASSERT(pg_->Scope()->IsFunctionVariableScope());
95     ASSERT(pg_->NextReg() == binder::Binder::MANDATORY_PARAM_FUNC_REG);
96 
97     const auto *funcScope = pg_->Scope()->AsFunctionVariableScope();
98 
99     for (auto *param : funcScope->ParamScope()->Params()) {
100         VReg paramReg = pg_->AllocReg();
101         if (!param->LexicalBound()) {
102             param->BindVReg(paramReg);
103         }
104     }
105 
106     envScope_->Initialize(pg_);
107 
108     for (const auto &[_, var] : funcScope->Bindings()) {
109         (void)_;
110         if (var->Declaration()->IsParameterDecl()) {
111             continue;
112         }
113 
114         if (!var->LexicalBound() && var->IsLocalVariable()) {
115             var->AsLocalVariable()->BindVReg(pg->AllocReg());
116         }
117     }
118 
119     if (pg_->IsDebug()) {
120         pg_->debugInfo_.variableDebugInfo.push_back(funcScope);
121     }
122 
123     pg_->SetSourceLocationFlag(lexer::SourceLocationFlag::INVALID_SOURCE_LOCATION);
124     pg_->LoadAccFromArgs(pg_->rootNode_);
125 
126     Hoisting::Hoist(pg);
127     pg_->SetSourceLocationFlag(lexer::SourceLocationFlag::VALID_SOURCE_LOCATION);
128 }
129 
130 FunctionRegScope::~FunctionRegScope() noexcept
131 {
132     if (pg_->IsDebug()) {
133         pg_->topScope_->SetScopeStart(pg_->insns_.front());
134     }
135 
136     DebuggerCloseScope();
137 
138     envScope_->~EnvScope();
139 }
140 
141 }  // namespace panda::es2panda::compiler
142