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