|  | //===- subzero/src/IceSwitchLowering.h - Switch lowering --------*- C++ -*-===// | 
|  | // | 
|  | //                     The LLVM Compiler Infrastructure | 
|  | // | 
|  | // This file is distributed under the University of Illinois Open Source | 
|  | // License. See LICENSE.TXT for details. | 
|  | // | 
|  | //===----------------------------------------------------------------------===// | 
|  | /// | 
|  | /// \file | 
|  | /// \brief Helpers for switch lowering. | 
|  | /// | 
|  | //===----------------------------------------------------------------------===// | 
|  |  | 
|  | #ifndef SUBZERO_SRC_ICESWITCHLOWERING_H | 
|  | #define SUBZERO_SRC_ICESWITCHLOWERING_H | 
|  |  | 
|  | #include "IceDefs.h" | 
|  | #include "IceStringPool.h" | 
|  |  | 
|  | #include <string> | 
|  |  | 
|  | namespace Ice { | 
|  |  | 
|  | class CaseCluster; | 
|  |  | 
|  | using CaseClusterArray = CfgVector<CaseCluster>; | 
|  |  | 
|  | /// A cluster of cases can be tested by a common method during switch lowering. | 
|  | class CaseCluster { | 
|  | CaseCluster() = delete; | 
|  |  | 
|  | public: | 
|  | enum CaseClusterKind { | 
|  | Range,     /// Numerically adjacent case values with same target. | 
|  | JumpTable, /// Different targets and possibly sparse. | 
|  | }; | 
|  |  | 
|  | CaseCluster(const CaseCluster &) = default; | 
|  | CaseCluster &operator=(const CaseCluster &) = default; | 
|  |  | 
|  | /// Create a cluster of a single case represented by a unitary range. | 
|  | CaseCluster(uint64_t Value, CfgNode *Target) | 
|  | : Kind(Range), Low(Value), High(Value), Target(Target) {} | 
|  | /// Create a case consisting of a jump table. | 
|  | CaseCluster(uint64_t Low, uint64_t High, InstJumpTable *JT) | 
|  | : Kind(JumpTable), Low(Low), High(High), JT(JT) {} | 
|  |  | 
|  | CaseClusterKind getKind() const { return Kind; } | 
|  | uint64_t getLow() const { return Low; } | 
|  | uint64_t getHigh() const { return High; } | 
|  | CfgNode *getTarget() const { | 
|  | assert(Kind == Range); | 
|  | return Target; | 
|  | } | 
|  | InstJumpTable *getJumpTable() const { | 
|  | assert(Kind == JumpTable); | 
|  | return JT; | 
|  | } | 
|  |  | 
|  | bool isUnitRange() const { return Low == High; } | 
|  | bool isPairRange() const { return Low == High - 1; } | 
|  |  | 
|  | /// Discover cases which can be clustered together and return the clusters | 
|  | /// ordered by case value. | 
|  | static CaseClusterArray clusterizeSwitch(Cfg *Func, const InstSwitch *Instr); | 
|  |  | 
|  | private: | 
|  | CaseClusterKind Kind; | 
|  | uint64_t Low; | 
|  | uint64_t High; | 
|  | union { | 
|  | CfgNode *Target;   /// Target for a range. | 
|  | InstJumpTable *JT; /// Jump table targets. | 
|  | }; | 
|  |  | 
|  | /// Try and append a cluster returning whether or not it was successful. | 
|  | bool tryAppend(const CaseCluster &New); | 
|  | }; | 
|  |  | 
|  | /// Store the jump table data so that it can be emitted later in the correct ELF | 
|  | /// section once the offsets from the start of the function are known. | 
|  | class JumpTableData { | 
|  | JumpTableData() = delete; | 
|  | JumpTableData &operator=(const JumpTableData &) = delete; | 
|  |  | 
|  | public: | 
|  | using TargetList = std::vector<intptr_t>; | 
|  |  | 
|  | JumpTableData(GlobalString Name, GlobalString FuncName, SizeT Id, | 
|  | const TargetList &TargetOffsets) | 
|  | : Name(Name), FuncName(FuncName), Id(Id), TargetOffsets(TargetOffsets) {} | 
|  | JumpTableData(const JumpTableData &) = default; | 
|  | JumpTableData(JumpTableData &&) = default; | 
|  | JumpTableData &operator=(JumpTableData &&) = default; | 
|  |  | 
|  | GlobalString getName() const { return Name; } | 
|  | GlobalString getFunctionName() const { return FuncName; } | 
|  | SizeT getId() const { return Id; } | 
|  | const TargetList &getTargetOffsets() const { return TargetOffsets; } | 
|  | static std::string createSectionName(const GlobalString Name) { | 
|  | if (Name.hasStdString()) { | 
|  | return Name.toString() + "$jumptable"; | 
|  | } | 
|  | return std::to_string(Name.getID()) + "$jumptable"; | 
|  | } | 
|  | std::string getSectionName() const { return createSectionName(FuncName); } | 
|  |  | 
|  | private: | 
|  | GlobalString Name; | 
|  | GlobalString FuncName; | 
|  | SizeT Id; | 
|  | TargetList TargetOffsets; | 
|  | }; | 
|  |  | 
|  | using JumpTableDataList = std::vector<JumpTableData>; | 
|  |  | 
|  | } // end of namespace Ice | 
|  |  | 
|  | #endif //  SUBZERO_SRC_ICESWITCHLOWERING_H |