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