1 /* 2 * Copyright (c) 2023 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 MAPLEBE_INCLUDE_EH_EH_FUNC_H 17 #define MAPLEBE_INCLUDE_EH_EH_FUNC_H 18 #include "mir_parser.h" 19 #include "mir_function.h" 20 #include "lsda.h" 21 #include "cg_phase.h" 22 #include "maple_phase.h" 23 24 namespace maplebe { 25 class EHTry { 26 public: EHTry(MapleAllocator & alloc,TryNode & tryNode)27 EHTry(MapleAllocator &alloc, TryNode &tryNode) : tryNode(&tryNode), catchVec(alloc.Adapter()) {} 28 ~EHTry() = default; 29 GetTryNode()30 TryNode *GetTryNode() const 31 { 32 return tryNode; 33 } 34 SetEndtryNode(StmtNode & endtryNode)35 void SetEndtryNode(StmtNode &endtryNode) 36 { 37 this->endTryNode = &endtryNode; 38 } 39 GetEndtryNode()40 StmtNode *GetEndtryNode() 41 { 42 return endTryNode; 43 } 44 SetFallthruGoto(StmtNode * fallthruGoto)45 void SetFallthruGoto(StmtNode *fallthruGoto) 46 { 47 this->fallThroughGoto = fallthruGoto; 48 } 49 GetFallthruGoto()50 StmtNode *GetFallthruGoto() 51 { 52 return fallThroughGoto; 53 } 54 GetCatchVecSize()55 size_t GetCatchVecSize() const 56 { 57 return catchVec.size(); 58 } 59 PushBackCatchVec(CatchNode & catchNode)60 void PushBackCatchVec(CatchNode &catchNode) 61 { 62 catchVec.emplace_back(&catchNode); 63 } 64 GetCatchNodeAt(size_t pos)65 CatchNode *GetCatchNodeAt(size_t pos) const 66 { 67 CHECK_FATAL(pos < GetCatchVecSize(), "pos is out of range."); 68 return catchVec.at(pos); 69 } 70 SetLSDACallSite(LSDACallSite & lsdaCallSite)71 void SetLSDACallSite(LSDACallSite &lsdaCallSite) 72 { 73 this->lsdaCallSite = &lsdaCallSite; 74 } 75 SetCSAction(uint32 action)76 void SetCSAction(uint32 action) const 77 { 78 lsdaCallSite->csAction = action; 79 } 80 81 void DumpEHTry(const MIRModule &mirModule); 82 83 private: 84 TryNode *tryNode; 85 StmtNode *endTryNode = nullptr; 86 StmtNode *fallThroughGoto = nullptr; /* no throw in the try block, the goto stmt to the fall through */ 87 MapleVector<CatchNode *> catchVec; 88 LSDACallSite *lsdaCallSite = nullptr; /* one try has a callsite */ 89 }; 90 91 class EHThrow { 92 public: EHThrow(UnaryStmtNode & rtNode)93 explicit EHThrow(UnaryStmtNode &rtNode) : rethrow(&rtNode) {} 94 ~EHThrow() = default; 95 IsUnderTry()96 bool IsUnderTry() const 97 { 98 return javaTry != nullptr; 99 } 100 HasLSDA()101 bool HasLSDA() const 102 { 103 return startLabel != nullptr; 104 } 105 GetRethrow()106 const UnaryStmtNode *GetRethrow() const 107 { 108 return rethrow; 109 } 110 SetJavaTry(EHTry * javaTry)111 void SetJavaTry(EHTry *javaTry) 112 { 113 this->javaTry = javaTry; 114 } 115 GetStartLabel()116 LabelNode *GetStartLabel() 117 { 118 return startLabel; 119 } 120 GetEndLabel()121 LabelNode *GetEndLabel() 122 { 123 return endLabel; 124 } 125 126 void Lower(CGFunc &cgFunc); 127 void ConvertThrowToRethrow(CGFunc &cgFunc); 128 void ConvertThrowToRuntime(CGFunc &cgFunc, BaseNode &arg); 129 130 private: 131 UnaryStmtNode *rethrow; /* must be a throw stmt */ 132 EHTry *javaTry = nullptr; /* the try statement wrapping this throw */ 133 LabelNode *startLabel = nullptr; /* the label that "MCC_RethrowException" or "MCC_ThrowException" begin */ 134 LabelNode *endLabel = nullptr; /* the label that "MCC_RethrowException" or "MCC_ThrowException" end */ 135 }; 136 137 class EHFunc { 138 public: 139 static constexpr uint8 kTypeEncoding = 0x9b; /* same thing as LSDAHeader.kTypeEncoding */ 140 explicit EHFunc(CGFunc &func); 141 ~EHFunc() = default; 142 143 void CollectEHInformation(std::vector<std::pair<LabelIdx, CatchNode *>> &catchVec); 144 void InsertEHSwitchTable(); 145 void CreateLSDA(); 146 bool NeedFullLSDA() const; 147 bool NeedFastLSDA() const; 148 void InsertCxaAfterEachCatch(const std::vector<std::pair<LabelIdx, CatchNode *>> &catchVec); 149 void GenerateCleanupLabel(); 150 void MergeCatchToTry(const std::vector<std::pair<LabelIdx, CatchNode *>> &catchVec); 151 void BuildEHTypeTable(const std::vector<std::pair<LabelIdx, CatchNode *>> &catchVec); 152 void LowerThrow(); /* for non-personality function */ 153 void CreateTypeInfoSt(); 154 void DumpEHFunc() const; 155 HasThrow()156 bool HasThrow() const 157 { 158 return !rethrowVec.empty(); 159 } 160 AddTry(EHTry & ehTry)161 void AddTry(EHTry &ehTry) 162 { 163 tryVec.emplace_back(&ehTry); 164 } 165 GetEHTyTableSize()166 size_t GetEHTyTableSize() const 167 { 168 return ehTyTable.size(); 169 } 170 GetEHTyTableMember(int32 index)171 TyIdx &GetEHTyTableMember(int32 index) 172 { 173 CHECK_FATAL(static_cast<size_t>(index) < ehTyTable.size(), "out of ehTyTable"); 174 return ehTyTable[index]; 175 } 176 GetLSDAHeader()177 LSDAHeader *GetLSDAHeader() 178 { 179 return lsdaHeader; 180 } 181 GetLSDACallSiteTable()182 LSDACallSiteTable *GetLSDACallSiteTable() 183 { 184 return lsdaCallSiteTable; 185 } 186 GetLSDACallSiteTable()187 const LSDACallSiteTable *GetLSDACallSiteTable() const 188 { 189 return lsdaCallSiteTable; 190 } 191 GetLSDAActionTable()192 const LSDAActionTable *GetLSDAActionTable() const 193 { 194 return lsdaActionTable; 195 } 196 AddRethrow(EHThrow & rethrow)197 void AddRethrow(EHThrow &rethrow) 198 { 199 rethrowVec.emplace_back(&rethrow); 200 } 201 202 private: 203 void CreateLSDAAction(); 204 void InsertDefaultLabelAndAbortFunc(BlockNode &blkNode, SwitchNode &switchNode, const StmtNode &beforeEndLabel); 205 void FillSwitchTable(SwitchNode &switchNode, const EHTry &ehTry); 206 void CreateLSDAHeader(); 207 void FillLSDACallSiteTable(); 208 LabelIdx CreateLabel(const std::string &cstr); 209 bool HasTry() const; 210 211 CGFunc *cgFunc; 212 LabelIdx labelIdx = 0; 213 MapleVector<EHTry *> tryVec; /* try stmt node */ 214 MapleVector<TyIdx> ehTyTable; /* the type that would emit in LSDA */ 215 MapleMap<TyIdx, uint32> ty2IndexTable; /* use the TyIdx to get the index of ehTyTable; */ 216 LSDAHeader *lsdaHeader = nullptr; 217 LSDACallSiteTable *lsdaCallSiteTable = nullptr; 218 LSDAActionTable *lsdaActionTable = nullptr; 219 MapleVector<EHThrow *> rethrowVec; /* EHRethrow */ 220 }; 221 222 MAPLE_FUNC_PHASE_DECLARE_BEGIN(CgBuildEHFunc, maplebe::CGFunc) 223 MAPLE_FUNC_PHASE_DECLARE_END 224 } /* namespace maplebe */ 225 226 #endif /* MAPLEBE_INCLUDE_EH_EH_FUNC_H */