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 #ifndef ES2PANDA_COMPILER_CORE_DYNAMIC_CONTEXT_H 17 #define ES2PANDA_COMPILER_CORE_DYNAMIC_CONTEXT_H 18 19 #include <util/ustring.h> 20 #include <ir/irnode.h> 21 #include <compiler/core/labelTarget.h> 22 #include <compiler/base/iterators.h> 23 24 namespace panda::es2panda::ir { 25 class TryStatement; 26 class ForOfStatement; 27 class LabelledStatement; 28 } // namespace panda::es2panda::ir 29 30 namespace panda::es2panda::compiler { 31 class PandaGen; 32 class VariableEnvScope; 33 class CatchTable; 34 class TryLabelSet; 35 36 enum class DynamicContextType { NONE, LABEL, LEX_ENV, ITERATOR, TRY }; 37 38 class DynamicContext { 39 public: 40 NO_COPY_SEMANTIC(DynamicContext); 41 NO_MOVE_SEMANTIC(DynamicContext); 42 virtual ~DynamicContext(); 43 44 void *operator new(size_t) = delete; 45 void *operator new[](size_t) = delete; 46 AbortContext(ControlFlowChange cfc,const util::StringView & targetLabel)47 virtual void AbortContext([[maybe_unused]] ControlFlowChange cfc, 48 [[maybe_unused]] const util::StringView &targetLabel) {}; 49 HasTryCatch()50 virtual bool HasTryCatch() const 51 { 52 return false; 53 } 54 HasFinalizer()55 virtual bool HasFinalizer() const 56 { 57 return HasTryCatch(); 58 } 59 60 virtual DynamicContextType Type() const = 0; 61 Prev()62 DynamicContext *Prev() 63 { 64 return prev_; 65 } 66 Prev()67 const DynamicContext *Prev() const 68 { 69 return prev_; 70 } 71 Target()72 const LabelTarget &Target() const 73 { 74 return target_; 75 } 76 77 protected: 78 explicit DynamicContext(PandaGen *pg, LabelTarget target); 79 80 PandaGen *pg_; 81 LabelTarget target_; 82 DynamicContext *prev_ {}; 83 }; 84 85 class LabelContext : public DynamicContext { 86 public: LabelContext(PandaGen * pg,LabelTarget target)87 explicit LabelContext(PandaGen *pg, LabelTarget target) : DynamicContext(pg, target) {} 88 explicit LabelContext(PandaGen *pg, const ir::LabelledStatement *labelledStmt); 89 NO_COPY_SEMANTIC(LabelContext); 90 NO_MOVE_SEMANTIC(LabelContext); 91 ~LabelContext(); 92 Type()93 DynamicContextType Type() const override 94 { 95 return DynamicContextType::LABEL; 96 } 97 98 private: 99 Label *label_ {}; 100 const ir::LabelledStatement *labelledStmt_ {}; 101 }; 102 103 class LexEnvContext : public DynamicContext { 104 public: 105 explicit LexEnvContext(VariableEnvScope *envScope, PandaGen *pg, LabelTarget target); 106 NO_COPY_SEMANTIC(LexEnvContext); 107 NO_MOVE_SEMANTIC(LexEnvContext); 108 ~LexEnvContext(); 109 Type()110 DynamicContextType Type() const override 111 { 112 return DynamicContextType::LEX_ENV; 113 } 114 115 bool HasTryCatch() const override; 116 void AbortContext([[maybe_unused]] ControlFlowChange cfc, 117 const util::StringView &targetLabel) override; 118 void SetTryEndLabel(const ir::AstNode *node); SetTryEndFlag(bool flag)119 void SetTryEndFlag(bool flag) 120 { 121 tryEndFlag = flag; 122 } 123 GetTryEndFlag()124 bool GetTryEndFlag() const 125 { 126 return tryEndFlag; 127 } 128 /** 129 * Handle for update direct return context 130 * If the lexical environment context is in for update statement, pop the lexical environment 131 */ 132 void HandleForUpdateDirectReturnContext(); 133 134 private: 135 VariableEnvScope *envScope_; 136 CatchTable *catchTable_ {}; 137 bool tryEndFlag {false}; 138 }; 139 140 class IteratorContext : public DynamicContext { 141 public: 142 explicit IteratorContext(PandaGen *pg, const Iterator &iterator, LabelTarget target); 143 NO_COPY_SEMANTIC(IteratorContext); 144 NO_MOVE_SEMANTIC(IteratorContext); 145 ~IteratorContext(); 146 Type()147 DynamicContextType Type() const override 148 { 149 return DynamicContextType::ITERATOR; 150 } 151 GetIterator()152 const Iterator &GetIterator() const 153 { 154 return iterator_; 155 } 156 HasTryCatch()157 bool HasTryCatch() const override 158 { 159 return true; 160 } 161 162 void AbortContext([[maybe_unused]] ControlFlowChange cfc, 163 [[maybe_unused]] const util::StringView &targetLabel) override; 164 165 private: 166 const Iterator &iterator_; 167 CatchTable *catchTable_; 168 }; 169 170 class DestructuringIteratorContext : public DynamicContext { 171 public: 172 explicit DestructuringIteratorContext(PandaGen *pg, const DestructuringIterator &iterator); 173 NO_COPY_SEMANTIC(DestructuringIteratorContext); 174 NO_MOVE_SEMANTIC(DestructuringIteratorContext); 175 ~DestructuringIteratorContext() override; 176 Type()177 DynamicContextType Type() const override 178 { 179 return DynamicContextType::ITERATOR; 180 } 181 GetIterator()182 const DestructuringIterator &GetIterator() const 183 { 184 return iterator_; 185 } 186 HasTryCatch()187 bool HasTryCatch() const override 188 { 189 return true; 190 } 191 192 void AbortContext(ControlFlowChange cfc, const util::StringView &targetLabel) override; 193 194 private: 195 const DestructuringIterator &iterator_; 196 CatchTable *catchTable_; 197 }; 198 199 class TryContext : public DynamicContext { 200 public: 201 explicit TryContext(PandaGen *pg, const ir::TryStatement *tryStmt, bool hasFinalizer = true) 202 : DynamicContext(pg, {}), tryStmt_(tryStmt), hasFinalizer_(hasFinalizer) 203 { 204 InitCatchTable(); 205 InitFinalizer(); 206 } 207 TryContext(PandaGen * pg)208 explicit TryContext(PandaGen *pg) : DynamicContext(pg, {}) 209 { 210 InitCatchTable(); 211 } 212 213 NO_COPY_SEMANTIC(TryContext); 214 NO_MOVE_SEMANTIC(TryContext); 215 ~TryContext() = default; 216 Type()217 DynamicContextType Type() const override 218 { 219 return DynamicContextType::TRY; 220 } 221 HasTryCatch()222 bool HasTryCatch() const override 223 { 224 return true; 225 } 226 FinalizerRun()227 VReg FinalizerRun() const 228 { 229 return finalizerRun_; 230 } 231 GetCatchTable()232 CatchTable *GetCatchTable() const 233 { 234 return catchTable_; 235 } 236 237 const TryLabelSet &LabelSet() const; 238 bool HasFinalizer() const override; 239 void InitFinalizer(); 240 void EmitFinalizer(); 241 242 void AbortContext([[maybe_unused]] ControlFlowChange cfc, 243 [[maybe_unused]] const util::StringView &targetLabel) override; 244 245 private: 246 void InitCatchTable(); 247 248 const ir::TryStatement *tryStmt_ {}; 249 CatchTable *catchTable_ {}; 250 VReg finalizerRun_ {}; 251 bool hasFinalizer_ {}; 252 bool inFinalizer_ {}; 253 }; 254 } // namespace panda::es2panda::compiler 255 256 #endif 257