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 24namespace ark::es2panda::ir { 25class TryStatement; 26class ForOfStatement; 27class LabelledStatement; 28} // namespace ark::es2panda::ir 29 30namespace ark::es2panda::compiler { 31class CodeGen; 32class LoopEnvScope; 33class CatchTable; 34class TryLabelSet; 35 36enum class DynamicContextType { NONE, LABEL, LEX_ENV, ITERATOR, TRY, TRAP }; 37 38class DynamicContext { 39public: 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 47 virtual void AbortContext([[maybe_unused]] ControlFlowChange cfc, 48 [[maybe_unused]] const util::StringView &targetLabel) {}; 49 50 virtual bool HasTryCatch() const 51 { 52 return false; 53 } 54 55 virtual bool HasFinalizer() const 56 { 57 return HasTryCatch(); 58 } 59 60 virtual DynamicContextType Type() const = 0; 61 62 DynamicContext *Prev() 63 { 64 return prev_; 65 } 66 67 const DynamicContext *Prev() const 68 { 69 return prev_; 70 } 71 72 const LabelTarget &Target() const 73 { 74 return target_; 75 } 76 77protected: 78 explicit DynamicContext(CodeGen *cg, LabelTarget target); 79 80 LabelTarget &Target() 81 { 82 return target_; 83 } 84 85 CodeGen *Cg() const 86 { 87 return cg_; 88 } 89 90private: 91 CodeGen *cg_; 92 LabelTarget target_; 93 DynamicContext *prev_ {}; 94}; 95 96class LabelContext : public DynamicContext { 97public: 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 104 DynamicContextType Type() const override 105 { 106 return DynamicContextType::LABEL; 107 } 108 109private: 110 Label *label_ {}; 111 const ir::LabelledStatement *labelledStmt_ {}; 112}; 113 114class LexEnvContext : public DynamicContext { 115public: 116 explicit LexEnvContext(LoopEnvScope *envScope, PandaGen *pg, LabelTarget target); 117 NO_COPY_SEMANTIC(LexEnvContext); 118 NO_MOVE_SEMANTIC(LexEnvContext); 119 ~LexEnvContext(); 120 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 130protected: 131 PandaGen *AsPandaGen() const; 132 133private: 134 LoopEnvScope *envScope_; 135 CatchTable *catchTable_ {}; 136}; 137 138class IteratorContext : public DynamicContext { 139public: 140 explicit IteratorContext(PandaGen *pg, const Iterator &iterator, LabelTarget target); 141 NO_COPY_SEMANTIC(IteratorContext); 142 NO_MOVE_SEMANTIC(IteratorContext); 143 ~IteratorContext(); 144 145 DynamicContextType Type() const override 146 { 147 return DynamicContextType::ITERATOR; 148 } 149 150 const Iterator &GetIterator() const 151 { 152 return iterator_; 153 } 154 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 163private: 164 const Iterator &iterator_; 165 CatchTable *catchTable_; 166}; 167 168class CatchContext : public DynamicContext { 169public: 170 NO_COPY_SEMANTIC(CatchContext); 171 NO_MOVE_SEMANTIC(CatchContext); 172 ~CatchContext() = default; 173 174 CatchTable *GetCatchTable() const 175 { 176 return catchTable_; 177 } 178 179 const TryLabelSet &LabelSet() const; 180 181 bool HasTryCatch() const override 182 { 183 return true; 184 } 185 186protected: 187 explicit CatchContext(CodeGen *cg) : DynamicContext(cg, {}) 188 { 189 InitCatchTable(); 190 } 191 192private: 193 void InitCatchTable(); 194 CatchTable *catchTable_ {}; 195}; 196 197class TryContext : public CatchContext { 198public: 199 explicit TryContext(CodeGen *cg, const ir::TryStatement *tryStmt, bool hasFinalizer = true) 200 : CatchContext(cg), tryStmt_(tryStmt), hasFinalizer_(hasFinalizer) 201 202 { 203 InitFinalizer(); 204 } 205 206 explicit TryContext(CodeGen *cg) : CatchContext(cg) {} 207 208 NO_COPY_SEMANTIC(TryContext); 209 NO_MOVE_SEMANTIC(TryContext); 210 ~TryContext() = default; 211 212 DynamicContextType Type() const override 213 { 214 return DynamicContextType::TRY; 215 } 216 217 VReg FinalizerRun() const 218 { 219 return finalizerRun_; 220 } 221 222 bool HasFinalizer() const override; 223 void InitFinalizer(); 224 void EmitFinalizer(); 225 226 void AbortContext([[maybe_unused]] ControlFlowChange cfc, 227 [[maybe_unused]] const util::StringView &targetLabel) override 228 { 229 EmitFinalizer(); 230 } 231 232private: 233 const ir::TryStatement *tryStmt_ {}; 234 VReg finalizerRun_ {}; 235 bool hasFinalizer_ {}; 236 bool inFinalizer_ {}; 237}; 238 239class ETSCatchContext : public DynamicContext { 240public: 241 NO_COPY_SEMANTIC(ETSCatchContext); 242 NO_MOVE_SEMANTIC(ETSCatchContext); 243 ~ETSCatchContext() = default; 244 245 ArenaVector<const CatchTable *> GetETSCatchTable() const 246 { 247 return catchTables_; 248 } 249 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 258protected: 259 explicit ETSCatchContext(CodeGen *cg, ArenaAllocator *allocator) 260 : DynamicContext(cg, {}), catchTables_(allocator->Adapter()) 261 { 262 } 263 264private: 265 ArenaVector<const CatchTable *> catchTables_; 266}; 267 268class ETSTryContext : public ETSCatchContext { 269public: 270 explicit ETSTryContext(CodeGen *cg, ArenaAllocator *allocator, const ir::TryStatement *tryStmt, 271 bool hasFinalizer = true) 272 : ETSCatchContext(cg, allocator), tryStmt_(tryStmt), hasFinalizer_(hasFinalizer) 273 274 { 275 } 276 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 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 292private: 293 const ir::TryStatement *tryStmt_ {}; 294 const bool hasFinalizer_ {}; 295}; 296 297} // namespace ark::es2panda::compiler 298 299#endif 300