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