• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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