1 /**
2 * Copyright (c) 2021 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 "lexenv.h"
17
18 #include <compiler/core/pandagen.h>
19 #include <ir/base/classDefinition.h>
20 #include <ir/base/scriptFunction.h>
21
22 namespace panda::es2panda::compiler {
23
24 // Helpers
25
CheckTdz(const ir::AstNode * node)26 static bool CheckTdz(const ir::AstNode *node)
27 {
28 return node->IsIdentifier() && node->AsIdentifier()->IsTdz();
29 }
30
CheckConstAssignment(PandaGen * pg,const ir::AstNode * node,binder::Variable * variable)31 static void CheckConstAssignment(PandaGen *pg, const ir::AstNode *node, binder::Variable *variable)
32 {
33 if (!variable->Declaration()->IsConstDecl()) {
34 return;
35 }
36
37 pg->ThrowConstAssignment(node, variable->Name());
38 }
39
40 // VirtualLoadVar
41
ExpandLoadLexVar(PandaGen * pg,const ir::AstNode * node,const binder::ScopeFindResult & result)42 static void ExpandLoadLexVar(PandaGen *pg, const ir::AstNode *node, const binder::ScopeFindResult &result)
43 {
44 /**
45 * Instruction ldsendableclass is generated when use sendable class inside itself, except static initializer.
46 * Because static initializer is not defined with instruction definesendableclass.
47 */
48 auto decl = result.variable->Declaration();
49 if (decl->IsSendableClassDecl()) {
50 auto classDef = decl->Node()->AsClassDefinition();
51 if (classDef == util::Helpers::GetContainingSendableClass(node) &&
52 !util::Helpers::IsChildScope(classDef->StaticInitializer()->Function()->Scope(), pg->TopScope())) {
53 pg->LoadSendableClass(node, result.lexLevel);
54 return;
55 }
56 }
57
58 auto *local = result.variable->AsLocalVariable();
59 if (local->InSendableEnv()) {
60 pg->LoadSendableVar(node, result.sendableLevel, local->LexIdx());
61 } else {
62 pg->LoadLexicalVar(node, result.lexLevel, local->LexIdx(), result.variable->Name());
63 }
64
65 if (decl->IsLetOrConstOrClassDecl()) {
66 pg->ThrowUndefinedIfHole(node, result.variable->Name());
67 }
68 }
69
ExpandLoadNormalVar(PandaGen * pg,const ir::AstNode * node,const binder::ScopeFindResult & result)70 static void ExpandLoadNormalVar(PandaGen *pg, const ir::AstNode *node, const binder::ScopeFindResult &result)
71 {
72 auto *local = result.variable->AsLocalVariable();
73
74 if (CheckTdz(node)) {
75 pg->LoadConst(node, Constant::JS_HOLE);
76 pg->ThrowUndefinedIfHole(node, local->Name());
77 } else {
78 pg->LoadAccumulator(node, local->Vreg());
79 }
80 }
81
Expand(PandaGen * pg,const ir::AstNode * node,const binder::ScopeFindResult & result)82 void VirtualLoadVar::Expand(PandaGen *pg, const ir::AstNode *node, const binder::ScopeFindResult &result)
83 {
84 if (result.variable->LexicalBound()) {
85 ExpandLoadLexVar(pg, node, result);
86 } else {
87 ExpandLoadNormalVar(pg, node, result);
88 }
89 }
90
91 // VirtualStoreVar
92
ExpandStoreLexVar(PandaGen * pg,const ir::AstNode * node,const binder::ScopeFindResult & result,bool isDecl)93 static void ExpandStoreLexVar(PandaGen *pg, const ir::AstNode *node, const binder::ScopeFindResult &result, bool isDecl)
94 {
95 binder::LocalVariable *local = result.variable->AsLocalVariable();
96
97 const auto *decl = result.variable->Declaration();
98
99 if (decl->IsLetOrConstOrClassDecl() && !isDecl) {
100 RegScope rs(pg);
101
102 VReg valueReg = pg->AllocReg();
103 pg->StoreAccumulator(node, valueReg);
104
105 ExpandLoadLexVar(pg, node, result);
106
107 if (decl->IsConstDecl()) {
108 pg->ThrowConstAssignment(node, local->Name());
109 }
110
111 pg->LoadAccumulator(node, valueReg);
112 }
113
114 if (local->InSendableEnv()) {
115 pg->StoreSendableVar(node, result.sendableLevel, local->LexIdx());
116 return;
117 }
118 pg->StoreLexicalVar(node, result.lexLevel, local->LexIdx(), local);
119 }
120
ExpandStoreNormalVar(PandaGen * pg,const ir::AstNode * node,const binder::ScopeFindResult & result,bool isDecl)121 static void ExpandStoreNormalVar(PandaGen *pg, const ir::AstNode *node, const binder::ScopeFindResult &result,
122 bool isDecl)
123 {
124 auto *local = result.variable->AsLocalVariable();
125 VReg localReg = local->Vreg();
126
127 if (!isDecl) {
128 if (CheckTdz(node)) {
129 pg->LoadConst(node, Constant::JS_HOLE);
130 pg->ThrowUndefinedIfHole(node, local->Name());
131 }
132
133 CheckConstAssignment(pg, node, local);
134 }
135
136 pg->StoreAccumulator(node, localReg);
137 }
138
Expand(PandaGen * pg,const ir::AstNode * node,const binder::ScopeFindResult & result,bool isDecl)139 void VirtualStoreVar::Expand(PandaGen *pg, const ir::AstNode *node, const binder::ScopeFindResult &result, bool isDecl)
140 {
141 if (result.variable->LexicalBound()) {
142 ExpandStoreLexVar(pg, node, result, isDecl);
143 } else {
144 ExpandStoreNormalVar(pg, node, result, isDecl);
145 }
146 }
147
148 } // namespace panda::es2panda::compiler
149