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_MACHO_ARCHITECTURESET_H
14 #define LLVM_TEXTAPI_MACHO_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 
24 namespace llvm {
25 class raw_ostream;
26 
27 namespace MachO {
28 
29 class ArchitectureSet {
30 private:
31   using ArchSetType = uint32_t;
32 
33   const static ArchSetType EndIndexVal =
34       std::numeric_limits<ArchSetType>::max();
35   ArchSetType ArchSet{0};
36 
37 public:
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   void set(Architecture Arch) {
44     if (Arch == AK_unknown)
45       return;
46     ArchSet |= 1U << static_cast<int>(Arch);
47   }
48 
49   void clear(Architecture Arch) { ArchSet &= ~(1U << static_cast<int>(Arch)); }
50 
51   bool has(Architecture Arch) const {
52     return ArchSet & (1U << static_cast<int>(Arch));
53   }
54 
55   bool contains(ArchitectureSet Archs) const {
56     return (ArchSet & Archs.ArchSet) == Archs.ArchSet;
57   }
58 
59   size_t count() const;
60 
61   bool empty() const { return ArchSet == 0; }
62 
63   ArchSetType rawValue() const { return ArchSet; }
64 
65   bool hasX86() const {
66     return has(AK_i386) || has(AK_x86_64) || has(AK_x86_64h);
67   }
68 
69   template <typename Ty>
70   class arch_iterator
71       : public std::iterator<std::forward_iterator_tag, Architecture, size_t> {
72   private:
73     ArchSetType Index;
74     Ty *ArchSet;
75 
76     void findNextSetBit() {
77       if (Index == EndIndexVal)
78         return;
79       while (++Index < sizeof(Ty) * 8) {
80         if (*ArchSet & (1UL << Index))
81           return;
82       }
83 
84       Index = EndIndexVal;
85     }
86 
87   public:
88     arch_iterator(Ty *ArchSet, ArchSetType Index = 0)
89         : Index(Index), ArchSet(ArchSet) {
90       if (Index != EndIndexVal && !(*ArchSet & (1UL << Index)))
91         findNextSetBit();
92     }
93 
94     Architecture operator*() const { return static_cast<Architecture>(Index); }
95 
96     arch_iterator &operator++() {
97       findNextSetBit();
98       return *this;
99     }
100 
101     arch_iterator operator++(int) {
102       auto tmp = *this;
103       findNextSetBit();
104       return tmp;
105     }
106 
107     bool operator==(const arch_iterator &o) const {
108       return std::tie(Index, ArchSet) == std::tie(o.Index, o.ArchSet);
109     }
110 
111     bool operator!=(const arch_iterator &o) const { return !(*this == o); }
112   };
113 
114   ArchitectureSet operator&(const ArchitectureSet &o) {
115     return {ArchSet & o.ArchSet};
116   }
117 
118   ArchitectureSet operator|(const ArchitectureSet &o) {
119     return {ArchSet | o.ArchSet};
120   }
121 
122   ArchitectureSet &operator|=(const ArchitectureSet &o) {
123     ArchSet |= o.ArchSet;
124     return *this;
125   }
126 
127   ArchitectureSet &operator|=(const Architecture &Arch) {
128     set(Arch);
129     return *this;
130   }
131 
132   bool operator==(const ArchitectureSet &o) const {
133     return ArchSet == o.ArchSet;
134   }
135 
136   bool operator!=(const ArchitectureSet &o) const {
137     return ArchSet != o.ArchSet;
138   }
139 
140   bool operator<(const ArchitectureSet &o) const { return ArchSet < o.ArchSet; }
141 
142   using iterator = arch_iterator<ArchSetType>;
143   using const_iterator = arch_iterator<const ArchSetType>;
144 
145   iterator begin() { return {&ArchSet}; }
146   iterator end() { return {&ArchSet, EndIndexVal}; }
147 
148   const_iterator begin() const { return {&ArchSet}; }
149   const_iterator end() const { return {&ArchSet, EndIndexVal}; }
150 
151   operator std::string() const;
152   operator std::vector<Architecture>() const;
153   void print(raw_ostream &OS) const;
154 };
155 
156 inline ArchitectureSet operator|(const Architecture &lhs,
157                                  const Architecture &rhs) {
158   return ArchitectureSet(lhs) | ArchitectureSet(rhs);
159 }
160 
161 raw_ostream &operator<<(raw_ostream &OS, ArchitectureSet Set);
162 
163 } // end namespace MachO.
164 } // end namespace llvm.
165 
166 #endif // LLVM_TEXTAPI_MACHO_ARCHITECTURESET_H
167