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 
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;
ArchitectureSet(ArchSetType Raw)39   constexpr ArchitectureSet(ArchSetType Raw) : ArchSet(Raw) {}
ArchitectureSet(Architecture Arch)40   ArchitectureSet(Architecture Arch) : ArchitectureSet() { set(Arch); }
41   ArchitectureSet(const std::vector<Architecture> &Archs);
42 
All()43   static ArchitectureSet All() { return ArchitectureSet(EndIndexVal); }
44 
set(Architecture Arch)45   void set(Architecture Arch) {
46     if (Arch == AK_unknown)
47       return;
48     ArchSet |= 1U << static_cast<int>(Arch);
49   }
50 
clear(Architecture Arch)51   ArchitectureSet clear(Architecture Arch) {
52     ArchSet &= ~(1U << static_cast<int>(Arch));
53     return ArchSet;
54   }
55 
has(Architecture Arch)56   bool has(Architecture Arch) const {
57     return ArchSet & (1U << static_cast<int>(Arch));
58   }
59 
contains(ArchitectureSet Archs)60   bool contains(ArchitectureSet Archs) const {
61     return (ArchSet & Archs.ArchSet) == Archs.ArchSet;
62   }
63 
64   size_t count() const;
65 
empty()66   bool empty() const { return ArchSet == 0; }
67 
rawValue()68   ArchSetType rawValue() const { return ArchSet; }
69 
hasX86()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 
findNextSetBit()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)
Index(Index)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 
begin()155   iterator begin() { return {&ArchSet}; }
end()156   iterator end() { return {&ArchSet, EndIndexVal}; }
157 
begin()158   const_iterator begin() const { return {&ArchSet}; }
end()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 
166 inline ArchitectureSet operator|(const Architecture &lhs,
167                                  const Architecture &rhs) {
168   return ArchitectureSet(lhs) | ArchitectureSet(rhs);
169 }
170 
171 raw_ostream &operator<<(raw_ostream &OS, ArchitectureSet Set);
172 
173 } // end namespace MachO.
174 } // end namespace llvm.
175 
176 #endif // LLVM_TEXTAPI_ARCHITECTURESET_H
177