#ifndef LLVM_MC_SUBTARGETFEATURE_H
#define LLVM_MC_SUBTARGETFEATURE_H
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/MathExtras.h"
#include <array>
#include <bitset>
#include <initializer_list>
#include <string>
#include <vector>
namespace llvm {
class raw_ostream;
class Triple;
const unsigned MAX_SUBTARGET_WORDS = 3;
const unsigned MAX_SUBTARGET_FEATURES = MAX_SUBTARGET_WORDS * 64;
class FeatureBitset {
static_assert((MAX_SUBTARGET_FEATURES % 64) == 0,
"Should be a multiple of 64!");
uint64_t Bits[MAX_SUBTARGET_WORDS] = {};
protected:
constexpr FeatureBitset(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B) {
for (unsigned I = 0; I != B.size(); ++I)
Bits[I] = B[I];
}
public:
constexpr FeatureBitset() = default;
constexpr FeatureBitset(std::initializer_list<unsigned> Init) {
for (auto I : Init)
set(I);
}
FeatureBitset &set() {
std::fill(std::begin(Bits), std::end(Bits), -1ULL);
return *this;
}
constexpr FeatureBitset &set(unsigned I) {
uint64_t NewBits = Bits[I / 64] | (uint64_t(1) << (I % 64));
Bits[I / 64] = NewBits;
return *this;
}
constexpr FeatureBitset &reset(unsigned I) {
uint64_t NewBits = Bits[I / 64] & ~(uint64_t(1) << (I % 64));
Bits[I / 64] = NewBits;
return *this;
}
constexpr FeatureBitset &flip(unsigned I) {
uint64_t NewBits = Bits[I / 64] ^ (uint64_t(1) << (I % 64));
Bits[I / 64] = NewBits;
return *this;
}
constexpr bool operator[](unsigned I) const {
uint64_t Mask = uint64_t(1) << (I % 64);
return (Bits[I / 64] & Mask) != 0;
}
constexpr bool test(unsigned I) const { return (*this)[I]; }
constexpr size_t size() const { return MAX_SUBTARGET_FEATURES; }
bool any() const {
return llvm::any_of(Bits, [](uint64_t I) { return I != 0; });
}
bool none() const { return !any(); }
size_t count() const {
size_t Count = 0;
for (auto B : Bits)
Count += countPopulation(B);
return Count;
}
constexpr FeatureBitset &operator^=(const FeatureBitset &RHS) {
for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
Bits[I] ^= RHS.Bits[I];
}
return *this;
}
constexpr FeatureBitset operator^(const FeatureBitset &RHS) const {
FeatureBitset Result = *this;
Result ^= RHS;
return Result;
}
constexpr FeatureBitset &operator&=(const FeatureBitset &RHS) {
for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
Bits[I] &= RHS.Bits[I];
}
return *this;
}
constexpr FeatureBitset operator&(const FeatureBitset &RHS) const {
FeatureBitset Result = *this;
Result &= RHS;
return Result;
}
constexpr FeatureBitset &operator|=(const FeatureBitset &RHS) {
for (unsigned I = 0, E = array_lengthof(Bits); I != E; ++I) {
Bits[I] |= RHS.Bits[I];
}
return *this;
}
constexpr FeatureBitset operator|(const FeatureBitset &RHS) const {
FeatureBitset Result = *this;
Result |= RHS;
return Result;
}
constexpr FeatureBitset operator~() const {
FeatureBitset Result = *this;
for (auto &B : Result.Bits)
B = ~B;
return Result;
}
bool operator==(const FeatureBitset &RHS) const {
return std::equal(std::begin(Bits), std::end(Bits), std::begin(RHS.Bits));
}
bool operator!=(const FeatureBitset &RHS) const { return !(*this == RHS); }
bool operator < (const FeatureBitset &Other) const {
for (unsigned I = 0, E = size(); I != E; ++I) {
bool LHS = test(I), RHS = Other.test(I);
if (LHS != RHS)
return LHS < RHS;
}
return false;
}
};
class FeatureBitArray : public FeatureBitset {
public:
constexpr FeatureBitArray(const std::array<uint64_t, MAX_SUBTARGET_WORDS> &B)
: FeatureBitset(B) {}
const FeatureBitset &getAsBitset() const { return *this; }
};
class SubtargetFeatures {
std::vector<std::string> Features;
public:
explicit SubtargetFeatures(StringRef Initial = "");
std::string getString() const;
void AddFeature(StringRef String, bool Enable = true);
const std::vector<std::string> &getFeatures() const { return Features; }
void print(raw_ostream &OS) const;
void dump() const;
void getDefaultSubtargetFeatures(const Triple& Triple);
static bool hasFlag(StringRef Feature) {
assert(!Feature.empty() && "Empty string");
char Ch = Feature[0];
return Ch == '+' || Ch =='-';
}
static std::string StripFlag(StringRef Feature) {
return hasFlag(Feature) ? Feature.substr(1) : Feature;
}
static inline bool isEnabled(StringRef Feature) {
assert(!Feature.empty() && "Empty string");
char Ch = Feature[0];
return Ch == '+';
}
static void Split(std::vector<std::string> &V, StringRef S);
};
}
#endif