1 /* 2 * Copyright (c) 2021-2025 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_LOWERING_PHASE_H 17 #define ES2PANDA_COMPILER_LOWERING_PHASE_H 18 19 #include "parser/program/program.h" 20 #include "public/public.h" 21 22 namespace ark::es2panda::compiler { 23 24 constexpr int32_t INVALID_PHASE_ID = -2; 25 constexpr int32_t PARSER_PHASE_ID = -1; 26 27 class Phase { 28 public: 29 /* If Apply returns false, processing is stopped. */ 30 bool Apply(public_lib::Context *ctx, parser::Program *program); 31 32 virtual std::string_view Name() const = 0; 33 Precondition(public_lib::Context * ctx,const parser::Program * program)34 virtual bool Precondition([[maybe_unused]] public_lib::Context *ctx, 35 [[maybe_unused]] const parser::Program *program) 36 { 37 return true; 38 } 39 virtual bool Perform(public_lib::Context *ctx, parser::Program *program) = 0; Postcondition(public_lib::Context * ctx,const parser::Program * program)40 virtual bool Postcondition([[maybe_unused]] public_lib::Context *ctx, 41 [[maybe_unused]] const parser::Program *program) 42 { 43 return true; 44 } 45 46 private: 47 friend class PhaseManager; 48 int32_t id_ {INVALID_PHASE_ID}; 49 }; 50 51 /* Phase that modifies declarations. Need to process external dependencies */ 52 class PhaseForDeclarations : public Phase { 53 bool Precondition(public_lib::Context *ctx, const parser::Program *program) override; 54 bool Perform(public_lib::Context *ctx, parser::Program *program) override; 55 bool Postcondition(public_lib::Context *ctx, const parser::Program *program) override; 56 57 /* Called from Perform, Pre/Postcondition */ PreconditionForModule(public_lib::Context * ctx,const parser::Program * program)58 virtual bool PreconditionForModule([[maybe_unused]] public_lib::Context *ctx, 59 [[maybe_unused]] const parser::Program *program) 60 { 61 return true; 62 } 63 virtual bool PerformForModule(public_lib::Context *ctx, parser::Program *program) = 0; PostconditionForModule(public_lib::Context * ctx,const parser::Program * program)64 virtual bool PostconditionForModule([[maybe_unused]] public_lib::Context *ctx, 65 [[maybe_unused]] const parser::Program *program) 66 { 67 return true; 68 } 69 }; 70 71 /* Phase that only modifies bodies. 72 No need to process external dependencies unless we are compiling stdlib. 73 */ 74 class PhaseForBodies : public Phase { 75 bool Precondition(public_lib::Context *ctx, const parser::Program *program) override; 76 bool Perform(public_lib::Context *ctx, parser::Program *program) override; 77 bool Postcondition(public_lib::Context *ctx, const parser::Program *program) override; 78 79 /* Called from Perform, Pre/Postcondition */ PreconditionForModule(public_lib::Context * ctx,const parser::Program * program)80 virtual bool PreconditionForModule([[maybe_unused]] public_lib::Context *ctx, 81 [[maybe_unused]] const parser::Program *program) 82 { 83 return true; 84 } 85 virtual bool PerformForModule(public_lib::Context *ctx, parser::Program *program) = 0; PostconditionForModule(public_lib::Context * ctx,const parser::Program * program)86 virtual bool PostconditionForModule([[maybe_unused]] public_lib::Context *ctx, 87 [[maybe_unused]] const parser::Program *program) 88 { 89 return true; 90 } 91 }; 92 93 class PhaseManager { 94 public: PhaseManager(ScriptExtension ext,ArenaAllocator * allocator)95 PhaseManager(ScriptExtension ext, ArenaAllocator *allocator) : allocator_ {allocator}, ext_ {ext} 96 { 97 InitializePhases(); 98 Restart(); 99 } 100 PreviousPhaseId()101 int32_t PreviousPhaseId() const 102 { 103 return prev_; 104 } 105 CurrentPhaseId()106 int32_t CurrentPhaseId() const 107 { 108 return curr_; 109 } 110 SetCurrentPhaseId(int32_t phaseId)111 void SetCurrentPhaseId(int32_t phaseId) 112 { 113 prev_ = curr_; 114 curr_ = phaseId; 115 } 116 Allocator()117 ArenaAllocator *Allocator() const 118 { 119 return allocator_; 120 } 121 IsInitialized()122 bool IsInitialized() const 123 { 124 return allocator_ != nullptr && ext_ != ScriptExtension::INVALID; 125 } 126 Restart()127 void Restart() 128 { 129 prev_ = INVALID_PHASE_ID; 130 curr_ = PARSER_PHASE_ID; 131 next_ = PARSER_PHASE_ID + 1; 132 ES2PANDA_ASSERT(next_ == 0); 133 } 134 NextPhase()135 Phase *NextPhase() 136 { 137 if (next_ < static_cast<int32_t>(phases_.size())) { 138 return phases_[next_++]; 139 } 140 return nullptr; 141 } 142 143 std::vector<Phase *> AllPhases(); 144 std::vector<Phase *> RebindPhases(); 145 std::vector<Phase *> RecheckPhases(); 146 147 private: 148 void InitializePhases(); 149 int32_t prev_ {INVALID_PHASE_ID}; 150 int32_t curr_ {INVALID_PHASE_ID}; 151 int32_t next_ {INVALID_PHASE_ID}; 152 153 ArenaAllocator *allocator_ {nullptr}; 154 ScriptExtension ext_ {ScriptExtension::INVALID}; 155 std::vector<Phase *> phases_; 156 }; 157 158 PhaseManager *GetPhaseManager(); 159 void SetPhaseManager(PhaseManager *phaseManager); 160 161 } // namespace ark::es2panda::compiler 162 163 #endif 164