121 lines
3.7 KiB
C++
121 lines
3.7 KiB
C++
//===- 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
|