//===- llvm/TextAPI/ArchitectureSet.h - ArchitectureSet ---------*- C++ -*-===//
 
//
 
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 
// See https://llvm.org/LICENSE.txt for license information.
 
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
//
 
//===----------------------------------------------------------------------===//
 
//
 
// Defines the architecture set.
 
//
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_TEXTAPI_ARCHITECTURESET_H
 
#define LLVM_TEXTAPI_ARCHITECTURESET_H
 
 
 
#include "llvm/TextAPI/Architecture.h"
 
#include <cstddef>
 
#include <iterator>
 
#include <limits>
 
#include <string>
 
#include <tuple>
 
#include <vector>
 
 
 
namespace llvm {
 
class raw_ostream;
 
 
 
namespace MachO {
 
 
 
class ArchitectureSet {
 
private:
 
  using ArchSetType = uint32_t;
 
 
 
  const static ArchSetType EndIndexVal =
 
      std::numeric_limits<ArchSetType>::max();
 
  ArchSetType ArchSet{0};
 
 
 
public:
 
  constexpr ArchitectureSet() = default;
 
  constexpr ArchitectureSet(ArchSetType Raw) : ArchSet(Raw) {}
 
  ArchitectureSet(Architecture Arch) : ArchitectureSet() { set(Arch); }
 
  ArchitectureSet(const std::vector<Architecture> &Archs);
 
 
 
  void set(Architecture Arch) {
 
    if (Arch == AK_unknown)
 
      return;
 
    ArchSet |= 1U << static_cast<int>(Arch);
 
  }
 
 
 
  void clear(Architecture Arch) { ArchSet &= ~(1U << static_cast<int>(Arch)); }
 
 
 
  bool has(Architecture Arch) const {
 
    return ArchSet & (1U << static_cast<int>(Arch));
 
  }
 
 
 
  bool contains(ArchitectureSet Archs) const {
 
    return (ArchSet & Archs.ArchSet) == Archs.ArchSet;
 
  }
 
 
 
  size_t count() const;
 
 
 
  bool empty() const { return ArchSet == 0; }
 
 
 
  ArchSetType rawValue() const { return ArchSet; }
 
 
 
  bool hasX86() const {
 
    return has(AK_i386) || has(AK_x86_64) || has(AK_x86_64h);
 
  }
 
 
 
  template <typename Ty> class arch_iterator {
 
  public:
 
    using iterator_category = std::forward_iterator_tag;
 
    using value_type = Architecture;
 
    using difference_type = std::size_t;
 
    using pointer = value_type *;
 
    using reference = value_type &;
 
 
 
  private:
 
    ArchSetType Index;
 
    Ty *ArchSet;
 
 
 
    void findNextSetBit() {
 
      if (Index == EndIndexVal)
 
        return;
 
      while (++Index < sizeof(Ty) * 8) {
 
        if (*ArchSet & (1UL << Index))
 
          return;
 
      }
 
 
 
      Index = EndIndexVal;
 
    }
 
 
 
  public:
 
    arch_iterator(Ty *ArchSet, ArchSetType Index = 0)
 
        : Index(Index), ArchSet(ArchSet) {
 
      if (Index != EndIndexVal && !(*ArchSet & (1UL << Index)))
 
        findNextSetBit();
 
    }
 
 
 
    Architecture operator*() const { return static_cast<Architecture>(Index); }
 
 
 
    arch_iterator &operator++() {
 
      findNextSetBit();
 
      return *this;
 
    }
 
 
 
    arch_iterator operator++(int) {
 
      auto tmp = *this;
 
      findNextSetBit();
 
      return tmp;
 
    }
 
 
 
    bool operator==(const arch_iterator &o) const {
 
      return std::tie(Index, ArchSet) == std::tie(o.Index, o.ArchSet);
 
    }
 
 
 
    bool operator!=(const arch_iterator &o) const { return !(*this == o); }
 
  };
 
 
 
  ArchitectureSet operator&(const ArchitectureSet &o) {
 
    return {ArchSet & o.ArchSet};
 
  }
 
 
 
  ArchitectureSet operator|(const ArchitectureSet &o) {
 
    return {ArchSet | o.ArchSet};
 
  }
 
 
 
  ArchitectureSet &operator|=(const ArchitectureSet &o) {
 
    ArchSet |= o.ArchSet;
 
    return *this;
 
  }
 
 
 
  ArchitectureSet &operator|=(const Architecture &Arch) {
 
    set(Arch);
 
    return *this;
 
  }
 
 
 
  bool operator==(const ArchitectureSet &o) const {
 
    return ArchSet == o.ArchSet;
 
  }
 
 
 
  bool operator!=(const ArchitectureSet &o) const {
 
    return ArchSet != o.ArchSet;
 
  }
 
 
 
  bool operator<(const ArchitectureSet &o) const { return ArchSet < o.ArchSet; }
 
 
 
  using iterator = arch_iterator<ArchSetType>;
 
  using const_iterator = arch_iterator<const ArchSetType>;
 
 
 
  iterator begin() { return {&ArchSet}; }
 
  iterator end() { return {&ArchSet, EndIndexVal}; }
 
 
 
  const_iterator begin() const { return {&ArchSet}; }
 
  const_iterator end() const { return {&ArchSet, EndIndexVal}; }
 
 
 
  operator std::string() const;
 
  operator std::vector<Architecture>() const;
 
  void print(raw_ostream &OS) const;
 
};
 
 
 
inline ArchitectureSet operator|(const Architecture &lhs,
 
                                 const Architecture &rhs) {
 
  return ArchitectureSet(lhs) | ArchitectureSet(rhs);
 
}
 
 
 
raw_ostream &operator<<(raw_ostream &OS, ArchitectureSet Set);
 
 
 
} // end namespace MachO.
 
} // end namespace llvm.
 
 
 
#endif // LLVM_TEXTAPI_ARCHITECTURESET_H