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