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_SWITCH_BUILDER_H 17 #define ES2PANDA_COMPILER_CORE_SWITCH_BUILDER_H 18 19 #include "ir/irnode.h" 20 #include "ir/statements/switchStatement.h" 21 #include "ir/statements/switchCaseStatement.h" 22 #include "compiler/core/dynamicContext.h" 23 #include "compiler/core/ETSGen.h" 24 #include "checker/checker.h" 25 26 namespace ark::es2panda::ir { 27 class SwitchStatement; 28 } // namespace ark::es2panda::ir 29 30 namespace ark::es2panda::compiler { 31 class PandaGen; 32 class Label; 33 34 template <typename CodeGen> 35 class SwitchBuilder { 36 public: SwitchBuilder(CodeGen * cg,const ir::SwitchStatement * stmt)37 SwitchBuilder(CodeGen *cg, const ir::SwitchStatement *stmt) 38 : cg_(cg), end_(cg->AllocLabel()), labelCtx_(cg, LabelTarget(end_, LabelTarget::BREAK_LABEL)), stmt_(stmt) 39 { 40 for (size_t i = 0; i < stmt_->Cases().size(); i++) { 41 caseLabels_.push_back(cg_->AllocLabel()); 42 } 43 } 44 45 NO_COPY_SEMANTIC(SwitchBuilder); 46 NO_MOVE_SEMANTIC(SwitchBuilder); ~SwitchBuilder()47 ~SwitchBuilder() 48 { 49 cg_->SetLabel(stmt_, end_); 50 } 51 SetCaseTarget(uint32_t index)52 void SetCaseTarget(uint32_t index) 53 { 54 cg_->SetLabel(stmt_->Cases()[index], caseLabels_[index]); 55 } 56 CompileTagOfSwitch(const VReg tag)57 void CompileTagOfSwitch(const VReg tag) 58 { 59 stmt_->Discriminant()->Compile(cg_); 60 if constexpr (std::is_same_v<CodeGen, ETSGen>) { 61 cg_->ApplyConversion(stmt_->Discriminant(), stmt_->Discriminant()->TsType()); 62 } 63 cg_->StoreAccumulator(stmt_->Discriminant(), tag); 64 } 65 CompileCaseStatements(uint32_t index)66 void CompileCaseStatements(uint32_t index) 67 { 68 for (const auto *stmt : stmt_->Cases()[index]->Consequent()) { 69 stmt->Compile(cg_); 70 } 71 } 72 JumpIfCase(const VReg tag,const uint32_t index)73 void JumpIfCase(const VReg tag, const uint32_t index) 74 { 75 const auto *const caseTarget = stmt_->Cases()[index]; 76 caseTarget->Test()->Compile(cg_); 77 78 if constexpr (std::is_same_v<CodeGen, PandaGen>) { 79 cg_->Condition(caseTarget, lexer::TokenType::PUNCTUATOR_NOT_STRICT_EQUAL, tag, caseLabels_[index]); 80 } else { 81 const compiler::TargetTypeContext ttctx(cg_, cg_->GetVRegType(tag)); 82 cg_->Condition(caseTarget, lexer::TokenType::PUNCTUATOR_NOT_EQUAL, tag, caseLabels_[index]); 83 } 84 } 85 JumpToDefault(uint32_t defaultIndex)86 void JumpToDefault(uint32_t defaultIndex) 87 { 88 const ir::SwitchCaseStatement *defaultTarget = stmt_->Cases()[defaultIndex]; 89 cg_->Branch(defaultTarget, caseLabels_[defaultIndex]); 90 } 91 Break()92 void Break() 93 { 94 cg_->Branch(stmt_, end_); 95 } 96 97 private: 98 CodeGen *cg_; 99 Label *end_; 100 LabelContext labelCtx_; 101 const ir::SwitchStatement *stmt_; 102 std::vector<Label *> caseLabels_; 103 }; 104 } // namespace ark::es2panda::compiler 105 106 #endif 107