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 pg_->scope_->SetScopeEnd(pg_->insns_.back());
44 }
45
46 // LocalRegScope
47
LocalRegScope(PandaGen * pg)48 LocalRegScope::LocalRegScope(PandaGen *pg) : RegScope(pg) {}
49
LocalRegScope(PandaGen * pg,binder::Scope * scope)50 LocalRegScope::LocalRegScope(PandaGen *pg, binder::Scope *scope) : RegScope(pg)
51 {
52 prevScope_ = pg_->scope_;
53 pg_->scope_ = scope;
54
55 for (const auto &[_, var] : scope->Bindings()) {
56 (void)_;
57 if (!var->LexicalBound() && var->IsLocalVariable()) {
58 var->AsLocalVariable()->BindVReg(pg->AllocReg());
59 }
60 }
61
62 if (pg_->IsDebug()) {
63 pg_->scope_->SetScopeStart(pg_->insns_.back());
64 pg_->debugInfo_.variableDebugInfo.push_back(pg_->scope_);
65 }
66
67 Hoisting::Hoist(pg_);
68 }
69
~LocalRegScope()70 LocalRegScope::~LocalRegScope()
71 {
72 if (!prevScope_) {
73 return;
74 }
75
76 DebuggerCloseScope();
77
78 pg_->scope_ = prevScope_;
79 }
80
81 // FunctionRegScope
82
FunctionRegScope(PandaGen * pg)83 FunctionRegScope::FunctionRegScope(PandaGen *pg) : RegScope(pg), envScope_(pg->Allocator()->New<EnvScope>())
84 {
85 ASSERT(pg_->Scope()->IsFunctionVariableScope());
86 ASSERT(pg_->NextReg() == binder::Binder::MANDATORY_PARAM_FUNC_REG);
87
88 const auto *funcScope = pg_->Scope()->AsFunctionVariableScope();
89
90 for (auto *param : funcScope->ParamScope()->Params()) {
91 VReg paramReg = pg_->AllocReg();
92 if (!param->LexicalBound()) {
93 param->BindVReg(paramReg);
94 }
95 }
96
97 envScope_->Initialize(pg_);
98
99 for (const auto &[_, var] : funcScope->Bindings()) {
100 (void)_;
101 if (var->Declaration()->IsParameterDecl()) {
102 continue;
103 }
104
105 if (!var->LexicalBound() && var->IsLocalVariable()) {
106 var->AsLocalVariable()->BindVReg(pg->AllocReg());
107 }
108 }
109
110 if (pg_->IsDebug()) {
111 pg_->debugInfo_.variableDebugInfo.push_back(funcScope);
112 }
113
114 pg_->SetSourceLocationFlag(lexer::SourceLocationFlag::INVALID_SOURCE_LOCATION);
115 pg_->LoadAccFromArgs(pg_->rootNode_);
116
117 Hoisting::Hoist(pg);
118 pg_->SetSourceLocationFlag(lexer::SourceLocationFlag::VALID_SOURCE_LOCATION);
119 }
120
~FunctionRegScope()121 FunctionRegScope::~FunctionRegScope()
122 {
123 if (pg_->IsDebug()) {
124 pg_->topScope_->SetScopeStart(pg_->insns_.front());
125 }
126
127 DebuggerCloseScope();
128
129 envScope_->~EnvScope();
130 }
131
132 } // namespace panda::es2panda::compiler
133