1 /** 2 * Copyright (c) 2021-2024 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 ark::es2panda::ir { 25 class TryStatement; 26 class ForOfStatement; 27 class LabelledStatement; 28 } // namespace ark::es2panda::ir 29 30 namespace ark::es2panda::compiler { 31 class CodeGen; 32 class LoopEnvScope; 33 class CatchTable; 34 class TryLabelSet; 35 36 enum class DynamicContextType { NONE, LABEL, LEX_ENV, ITERATOR, TRY, TRAP }; 37 38 class DynamicContext { 39 public: 40 NO_COPY_SEMANTIC(DynamicContext); 41 NO_MOVE_SEMANTIC(DynamicContext); 42 ~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(CodeGen *cg, LabelTarget target); 79 Target()80 LabelTarget &Target() 81 { 82 return target_; 83 } 84 Cg()85 CodeGen *Cg() const 86 { 87 return cg_; 88 } 89 90 private: 91 CodeGen *cg_; 92 LabelTarget target_; 93 DynamicContext *prev_ {}; 94 }; 95 96 class LabelContext : public DynamicContext { 97 public: LabelContext(CodeGen * cg,LabelTarget target)98 explicit LabelContext(CodeGen *cg, LabelTarget target) : DynamicContext(cg, target) {} 99 explicit LabelContext(CodeGen *cg, const ir::LabelledStatement *labelledStmt); 100 NO_COPY_SEMANTIC(LabelContext); 101 NO_MOVE_SEMANTIC(LabelContext); 102 ~LabelContext(); 103 Type()104 DynamicContextType Type() const override 105 { 106 return DynamicContextType::LABEL; 107 } 108 109 private: 110 Label *label_ {}; 111 const ir::LabelledStatement *labelledStmt_ {}; 112 }; 113 114 class LexEnvContext : public DynamicContext { 115 public: 116 explicit LexEnvContext(LoopEnvScope *envScope, PandaGen *pg, LabelTarget target); 117 NO_COPY_SEMANTIC(LexEnvContext); 118 NO_MOVE_SEMANTIC(LexEnvContext); 119 ~LexEnvContext(); 120 Type()121 DynamicContextType Type() const override 122 { 123 return DynamicContextType::LEX_ENV; 124 } 125 126 bool HasTryCatch() const override; 127 void AbortContext([[maybe_unused]] ControlFlowChange cfc, 128 [[maybe_unused]] const util::StringView &targetLabel) override; 129 130 protected: 131 PandaGen *AsPandaGen() const; 132 133 private: 134 LoopEnvScope *envScope_; 135 CatchTable *catchTable_ {}; 136 }; 137 138 class IteratorContext : public DynamicContext { 139 public: 140 explicit IteratorContext(PandaGen *pg, const Iterator &iterator, LabelTarget target); 141 NO_COPY_SEMANTIC(IteratorContext); 142 NO_MOVE_SEMANTIC(IteratorContext); 143 ~IteratorContext(); 144 Type()145 DynamicContextType Type() const override 146 { 147 return DynamicContextType::ITERATOR; 148 } 149 GetIterator()150 const Iterator &GetIterator() const 151 { 152 return iterator_; 153 } 154 HasTryCatch()155 bool HasTryCatch() const override 156 { 157 return true; 158 } 159 160 void AbortContext([[maybe_unused]] ControlFlowChange cfc, 161 [[maybe_unused]] const util::StringView &targetLabel) override; 162 163 private: 164 const Iterator &iterator_; 165 CatchTable *catchTable_; 166 }; 167 168 class CatchContext : public DynamicContext { 169 public: 170 NO_COPY_SEMANTIC(CatchContext); 171 NO_MOVE_SEMANTIC(CatchContext); 172 ~CatchContext() = default; 173 GetCatchTable()174 CatchTable *GetCatchTable() const 175 { 176 return catchTable_; 177 } 178 179 const TryLabelSet &LabelSet() const; 180 HasTryCatch()181 bool HasTryCatch() const override 182 { 183 return true; 184 } 185 186 protected: CatchContext(CodeGen * cg)187 explicit CatchContext(CodeGen *cg) : DynamicContext(cg, {}) 188 { 189 InitCatchTable(); 190 } 191 192 private: 193 void InitCatchTable(); 194 CatchTable *catchTable_ {}; 195 }; 196 197 class TryContext : public CatchContext { 198 public: 199 explicit TryContext(CodeGen *cg, const ir::TryStatement *tryStmt, bool hasFinalizer = true) CatchContext(cg)200 : CatchContext(cg), tryStmt_(tryStmt), hasFinalizer_(hasFinalizer) 201 202 { 203 InitFinalizer(); 204 } 205 TryContext(CodeGen * cg)206 explicit TryContext(CodeGen *cg) : CatchContext(cg) {} 207 208 NO_COPY_SEMANTIC(TryContext); 209 NO_MOVE_SEMANTIC(TryContext); 210 ~TryContext() = default; 211 Type()212 DynamicContextType Type() const override 213 { 214 return DynamicContextType::TRY; 215 } 216 FinalizerRun()217 VReg FinalizerRun() const 218 { 219 return finalizerRun_; 220 } 221 222 bool HasFinalizer() const override; 223 void InitFinalizer(); 224 void EmitFinalizer(); 225 AbortContext(ControlFlowChange cfc,const util::StringView & targetLabel)226 void AbortContext([[maybe_unused]] ControlFlowChange cfc, 227 [[maybe_unused]] const util::StringView &targetLabel) override 228 { 229 EmitFinalizer(); 230 } 231 232 private: 233 const ir::TryStatement *tryStmt_ {}; 234 VReg finalizerRun_ {}; 235 bool hasFinalizer_ {}; 236 bool inFinalizer_ {}; 237 }; 238 239 class ETSCatchContext : public DynamicContext { 240 public: 241 NO_COPY_SEMANTIC(ETSCatchContext); 242 NO_MOVE_SEMANTIC(ETSCatchContext); 243 ~ETSCatchContext() = default; 244 GetETSCatchTable()245 ArenaVector<const CatchTable *> GetETSCatchTable() const 246 { 247 return catchTables_; 248 } 249 HasTryCatch()250 bool HasTryCatch() const override 251 { 252 return true; 253 } 254 255 CatchTable *AddNewCathTable(util::StringView assemblerType); 256 CatchTable *AddNewCathTable(util::StringView assemblerType, LabelPair tryLabelPair); 257 258 protected: ETSCatchContext(CodeGen * cg,ArenaAllocator * allocator)259 explicit ETSCatchContext(CodeGen *cg, ArenaAllocator *allocator) 260 : DynamicContext(cg, {}), catchTables_(allocator->Adapter()) 261 { 262 } 263 264 private: 265 ArenaVector<const CatchTable *> catchTables_; 266 }; 267 268 class ETSTryContext : public ETSCatchContext { 269 public: 270 explicit ETSTryContext(CodeGen *cg, ArenaAllocator *allocator, const ir::TryStatement *tryStmt, 271 bool hasFinalizer = true) ETSCatchContext(cg,allocator)272 : ETSCatchContext(cg, allocator), tryStmt_(tryStmt), hasFinalizer_(hasFinalizer) 273 274 { 275 } 276 ETSTryContext(CodeGen * cg,ArenaAllocator * allocator)277 explicit ETSTryContext(CodeGen *cg, ArenaAllocator *allocator) : ETSCatchContext(cg, allocator) {} 278 279 NO_COPY_SEMANTIC(ETSTryContext); 280 NO_MOVE_SEMANTIC(ETSTryContext); 281 ~ETSTryContext() = default; 282 Type()283 DynamicContextType Type() const override 284 { 285 return DynamicContextType::TRY; 286 } 287 288 void EmitFinalizer(LabelPair trycatchLabelPair, 289 const ArenaVector<std::pair<compiler::LabelPair, const ir::Statement *>> &finalizerInsertions); 290 void EmitFinalizerInsertion(ETSGen *etsg, compiler::LabelPair labelPair, const ir::Statement *statement); 291 292 private: 293 const ir::TryStatement *tryStmt_ {}; 294 const bool hasFinalizer_ {}; 295 }; 296 297 } // namespace ark::es2panda::compiler 298 299 #endif 300