1*03ce13f7SAndroid Build Coastguard Worker //===- subzero/src/IceSwitchLowering.h - Switch lowering --------*- C++ -*-===// 2*03ce13f7SAndroid Build Coastguard Worker // 3*03ce13f7SAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure 4*03ce13f7SAndroid Build Coastguard Worker // 5*03ce13f7SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source 6*03ce13f7SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details. 7*03ce13f7SAndroid Build Coastguard Worker // 8*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*03ce13f7SAndroid Build Coastguard Worker /// 10*03ce13f7SAndroid Build Coastguard Worker /// \file 11*03ce13f7SAndroid Build Coastguard Worker /// \brief Helpers for switch lowering. 12*03ce13f7SAndroid Build Coastguard Worker /// 13*03ce13f7SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 14*03ce13f7SAndroid Build Coastguard Worker 15*03ce13f7SAndroid Build Coastguard Worker #ifndef SUBZERO_SRC_ICESWITCHLOWERING_H 16*03ce13f7SAndroid Build Coastguard Worker #define SUBZERO_SRC_ICESWITCHLOWERING_H 17*03ce13f7SAndroid Build Coastguard Worker 18*03ce13f7SAndroid Build Coastguard Worker #include "IceDefs.h" 19*03ce13f7SAndroid Build Coastguard Worker #include "IceStringPool.h" 20*03ce13f7SAndroid Build Coastguard Worker 21*03ce13f7SAndroid Build Coastguard Worker #include <string> 22*03ce13f7SAndroid Build Coastguard Worker 23*03ce13f7SAndroid Build Coastguard Worker namespace Ice { 24*03ce13f7SAndroid Build Coastguard Worker 25*03ce13f7SAndroid Build Coastguard Worker class CaseCluster; 26*03ce13f7SAndroid Build Coastguard Worker 27*03ce13f7SAndroid Build Coastguard Worker using CaseClusterArray = CfgVector<CaseCluster>; 28*03ce13f7SAndroid Build Coastguard Worker 29*03ce13f7SAndroid Build Coastguard Worker /// A cluster of cases can be tested by a common method during switch lowering. 30*03ce13f7SAndroid Build Coastguard Worker class CaseCluster { 31*03ce13f7SAndroid Build Coastguard Worker CaseCluster() = delete; 32*03ce13f7SAndroid Build Coastguard Worker 33*03ce13f7SAndroid Build Coastguard Worker public: 34*03ce13f7SAndroid Build Coastguard Worker enum CaseClusterKind { 35*03ce13f7SAndroid Build Coastguard Worker Range, /// Numerically adjacent case values with same target. 36*03ce13f7SAndroid Build Coastguard Worker JumpTable, /// Different targets and possibly sparse. 37*03ce13f7SAndroid Build Coastguard Worker }; 38*03ce13f7SAndroid Build Coastguard Worker 39*03ce13f7SAndroid Build Coastguard Worker CaseCluster(const CaseCluster &) = default; 40*03ce13f7SAndroid Build Coastguard Worker CaseCluster &operator=(const CaseCluster &) = default; 41*03ce13f7SAndroid Build Coastguard Worker 42*03ce13f7SAndroid Build Coastguard Worker /// Create a cluster of a single case represented by a unitary range. CaseCluster(uint64_t Value,CfgNode * Target)43*03ce13f7SAndroid Build Coastguard Worker CaseCluster(uint64_t Value, CfgNode *Target) 44*03ce13f7SAndroid Build Coastguard Worker : Kind(Range), Low(Value), High(Value), Target(Target) {} 45*03ce13f7SAndroid Build Coastguard Worker /// Create a case consisting of a jump table. CaseCluster(uint64_t Low,uint64_t High,InstJumpTable * JT)46*03ce13f7SAndroid Build Coastguard Worker CaseCluster(uint64_t Low, uint64_t High, InstJumpTable *JT) 47*03ce13f7SAndroid Build Coastguard Worker : Kind(JumpTable), Low(Low), High(High), JT(JT) {} 48*03ce13f7SAndroid Build Coastguard Worker getKind()49*03ce13f7SAndroid Build Coastguard Worker CaseClusterKind getKind() const { return Kind; } getLow()50*03ce13f7SAndroid Build Coastguard Worker uint64_t getLow() const { return Low; } getHigh()51*03ce13f7SAndroid Build Coastguard Worker uint64_t getHigh() const { return High; } getTarget()52*03ce13f7SAndroid Build Coastguard Worker CfgNode *getTarget() const { 53*03ce13f7SAndroid Build Coastguard Worker assert(Kind == Range); 54*03ce13f7SAndroid Build Coastguard Worker return Target; 55*03ce13f7SAndroid Build Coastguard Worker } getJumpTable()56*03ce13f7SAndroid Build Coastguard Worker InstJumpTable *getJumpTable() const { 57*03ce13f7SAndroid Build Coastguard Worker assert(Kind == JumpTable); 58*03ce13f7SAndroid Build Coastguard Worker return JT; 59*03ce13f7SAndroid Build Coastguard Worker } 60*03ce13f7SAndroid Build Coastguard Worker isUnitRange()61*03ce13f7SAndroid Build Coastguard Worker bool isUnitRange() const { return Low == High; } isPairRange()62*03ce13f7SAndroid Build Coastguard Worker bool isPairRange() const { return Low == High - 1; } 63*03ce13f7SAndroid Build Coastguard Worker 64*03ce13f7SAndroid Build Coastguard Worker /// Discover cases which can be clustered together and return the clusters 65*03ce13f7SAndroid Build Coastguard Worker /// ordered by case value. 66*03ce13f7SAndroid Build Coastguard Worker static CaseClusterArray clusterizeSwitch(Cfg *Func, const InstSwitch *Instr); 67*03ce13f7SAndroid Build Coastguard Worker 68*03ce13f7SAndroid Build Coastguard Worker private: 69*03ce13f7SAndroid Build Coastguard Worker CaseClusterKind Kind; 70*03ce13f7SAndroid Build Coastguard Worker uint64_t Low; 71*03ce13f7SAndroid Build Coastguard Worker uint64_t High; 72*03ce13f7SAndroid Build Coastguard Worker union { 73*03ce13f7SAndroid Build Coastguard Worker CfgNode *Target; /// Target for a range. 74*03ce13f7SAndroid Build Coastguard Worker InstJumpTable *JT; /// Jump table targets. 75*03ce13f7SAndroid Build Coastguard Worker }; 76*03ce13f7SAndroid Build Coastguard Worker 77*03ce13f7SAndroid Build Coastguard Worker /// Try and append a cluster returning whether or not it was successful. 78*03ce13f7SAndroid Build Coastguard Worker bool tryAppend(const CaseCluster &New); 79*03ce13f7SAndroid Build Coastguard Worker }; 80*03ce13f7SAndroid Build Coastguard Worker 81*03ce13f7SAndroid Build Coastguard Worker /// Store the jump table data so that it can be emitted later in the correct ELF 82*03ce13f7SAndroid Build Coastguard Worker /// section once the offsets from the start of the function are known. 83*03ce13f7SAndroid Build Coastguard Worker class JumpTableData { 84*03ce13f7SAndroid Build Coastguard Worker JumpTableData() = delete; 85*03ce13f7SAndroid Build Coastguard Worker JumpTableData &operator=(const JumpTableData &) = delete; 86*03ce13f7SAndroid Build Coastguard Worker 87*03ce13f7SAndroid Build Coastguard Worker public: 88*03ce13f7SAndroid Build Coastguard Worker using TargetList = std::vector<intptr_t>; 89*03ce13f7SAndroid Build Coastguard Worker JumpTableData(GlobalString Name,GlobalString FuncName,SizeT Id,const TargetList & TargetOffsets)90*03ce13f7SAndroid Build Coastguard Worker JumpTableData(GlobalString Name, GlobalString FuncName, SizeT Id, 91*03ce13f7SAndroid Build Coastguard Worker const TargetList &TargetOffsets) 92*03ce13f7SAndroid Build Coastguard Worker : Name(Name), FuncName(FuncName), Id(Id), TargetOffsets(TargetOffsets) {} 93*03ce13f7SAndroid Build Coastguard Worker JumpTableData(const JumpTableData &) = default; 94*03ce13f7SAndroid Build Coastguard Worker JumpTableData(JumpTableData &&) = default; 95*03ce13f7SAndroid Build Coastguard Worker JumpTableData &operator=(JumpTableData &&) = default; 96*03ce13f7SAndroid Build Coastguard Worker getName()97*03ce13f7SAndroid Build Coastguard Worker GlobalString getName() const { return Name; } getFunctionName()98*03ce13f7SAndroid Build Coastguard Worker GlobalString getFunctionName() const { return FuncName; } getId()99*03ce13f7SAndroid Build Coastguard Worker SizeT getId() const { return Id; } getTargetOffsets()100*03ce13f7SAndroid Build Coastguard Worker const TargetList &getTargetOffsets() const { return TargetOffsets; } createSectionName(const GlobalString Name)101*03ce13f7SAndroid Build Coastguard Worker static std::string createSectionName(const GlobalString Name) { 102*03ce13f7SAndroid Build Coastguard Worker if (Name.hasStdString()) { 103*03ce13f7SAndroid Build Coastguard Worker return Name.toString() + "$jumptable"; 104*03ce13f7SAndroid Build Coastguard Worker } 105*03ce13f7SAndroid Build Coastguard Worker return std::to_string(Name.getID()) + "$jumptable"; 106*03ce13f7SAndroid Build Coastguard Worker } getSectionName()107*03ce13f7SAndroid Build Coastguard Worker std::string getSectionName() const { return createSectionName(FuncName); } 108*03ce13f7SAndroid Build Coastguard Worker 109*03ce13f7SAndroid Build Coastguard Worker private: 110*03ce13f7SAndroid Build Coastguard Worker GlobalString Name; 111*03ce13f7SAndroid Build Coastguard Worker GlobalString FuncName; 112*03ce13f7SAndroid Build Coastguard Worker SizeT Id; 113*03ce13f7SAndroid Build Coastguard Worker TargetList TargetOffsets; 114*03ce13f7SAndroid Build Coastguard Worker }; 115*03ce13f7SAndroid Build Coastguard Worker 116*03ce13f7SAndroid Build Coastguard Worker using JumpTableDataList = std::vector<JumpTableData>; 117*03ce13f7SAndroid Build Coastguard Worker 118*03ce13f7SAndroid Build Coastguard Worker } // end of namespace Ice 119*03ce13f7SAndroid Build Coastguard Worker 120*03ce13f7SAndroid Build Coastguard Worker #endif // SUBZERO_SRC_ICESWITCHLOWERING_H 121