1//===- llvm/TextAPI/ArchitectureSet.h - ArchitectureSet ---------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Defines the architecture set.
10//
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_TEXTAPI_ARCHITECTURESET_H
14#define LLVM_TEXTAPI_ARCHITECTURESET_H
15
16#include "llvm/TextAPI/Architecture.h"
17#include <cstddef>
18#include <iterator>
19#include <limits>
20#include <string>
21#include <tuple>
22#include <vector>
23
24namespace llvm {
25class raw_ostream;
26
27namespace MachO {
28
29class ArchitectureSet {
30private:
31  using ArchSetType = uint32_t;
32
33  const static ArchSetType EndIndexVal =
34      std::numeric_limits<ArchSetType>::max();
35  ArchSetType ArchSet{0};
36
37public:
38  constexpr ArchitectureSet() = default;
39  constexpr ArchitectureSet(ArchSetType Raw) : ArchSet(Raw) {}
40  ArchitectureSet(Architecture Arch) : ArchitectureSet() { set(Arch); }
41  ArchitectureSet(const std::vector<Architecture> &Archs);
42
43  static ArchitectureSet All() { return ArchitectureSet(EndIndexVal); }
44
45  void set(Architecture Arch) {
46    if (Arch == AK_unknown)
47      return;
48    ArchSet |= 1U << static_cast<int>(Arch);
49  }
50
51  ArchitectureSet clear(Architecture Arch) {
52    ArchSet &= ~(1U << static_cast<int>(Arch));
53    return ArchSet;
54  }
55
56  bool has(Architecture Arch) const {
57    return ArchSet & (1U << static_cast<int>(Arch));
58  }
59
60  bool contains(ArchitectureSet Archs) const {
61    return (ArchSet & Archs.ArchSet) == Archs.ArchSet;
62  }
63
64  size_t count() const;
65
66  bool empty() const { return ArchSet == 0; }
67
68  ArchSetType rawValue() const { return ArchSet; }
69
70  bool hasX86() const {
71    return has(AK_i386) || has(AK_x86_64) || has(AK_x86_64h);
72  }
73
74  template <typename Ty> class arch_iterator {
75  public:
76    using iterator_category = std::forward_iterator_tag;
77    using value_type = Architecture;
78    using difference_type = std::size_t;
79    using pointer = value_type *;
80    using reference = value_type &;
81
82  private:
83    ArchSetType Index;
84    Ty *ArchSet;
85
86    void findNextSetBit() {
87      if (Index == EndIndexVal)
88        return;
89      while (++Index < sizeof(Ty) * 8) {
90        if (*ArchSet & (1UL << Index))
91          return;
92      }
93
94      Index = EndIndexVal;
95    }
96
97  public:
98    arch_iterator(Ty *ArchSet, ArchSetType Index = 0)
99        : Index(Index), ArchSet(ArchSet) {
100      if (Index != EndIndexVal && !(*ArchSet & (1UL << Index)))
101        findNextSetBit();
102    }
103
104    Architecture operator*() const { return static_cast<Architecture>(Index); }
105
106    arch_iterator &operator++() {
107      findNextSetBit();
108      return *this;
109    }
110
111    arch_iterator operator++(int) {
112      auto tmp = *this;
113      findNextSetBit();
114      return tmp;
115    }
116
117    bool operator==(const arch_iterator &o) const {
118      return std::tie(Index, ArchSet) == std::tie(o.Index, o.ArchSet);
119    }
120
121    bool operator!=(const arch_iterator &o) const { return !(*this == o); }
122  };
123
124  ArchitectureSet operator&(const ArchitectureSet &o) {
125    return {ArchSet & o.ArchSet};
126  }
127
128  ArchitectureSet operator|(const ArchitectureSet &o) {
129    return {ArchSet | o.ArchSet};
130  }
131
132  ArchitectureSet &operator|=(const ArchitectureSet &o) {
133    ArchSet |= o.ArchSet;
134    return *this;
135  }
136
137  ArchitectureSet &operator|=(const Architecture &Arch) {
138    set(Arch);
139    return *this;
140  }
141
142  bool operator==(const ArchitectureSet &o) const {
143    return ArchSet == o.ArchSet;
144  }
145
146  bool operator!=(const ArchitectureSet &o) const {
147    return ArchSet != o.ArchSet;
148  }
149
150  bool operator<(const ArchitectureSet &o) const { return ArchSet < o.ArchSet; }
151
152  using iterator = arch_iterator<ArchSetType>;
153  using const_iterator = arch_iterator<const ArchSetType>;
154
155  iterator begin() { return {&ArchSet}; }
156  iterator end() { return {&ArchSet, EndIndexVal}; }
157
158  const_iterator begin() const { return {&ArchSet}; }
159  const_iterator end() const { return {&ArchSet, EndIndexVal}; }
160
161  operator std::string() const;
162  operator std::vector<Architecture>() const;
163  void print(raw_ostream &OS) const;
164};
165
166inline ArchitectureSet operator|(const Architecture &lhs,
167                                 const Architecture &rhs) {
168  return ArchitectureSet(lhs) | ArchitectureSet(rhs);
169}
170
171raw_ostream &operator<<(raw_ostream &OS, ArchitectureSet Set);
172
173} // end namespace MachO.
174} // end namespace llvm.
175
176#endif // LLVM_TEXTAPI_ARCHITECTURESET_H
177