xref: /freebsd/contrib/llvm-project/llvm/include/llvm/TextAPI/SymbolSet.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===- llvm/TextAPI/SymbolSet.h - TAPI Symbol Set --------------*- 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 #ifndef LLVM_TEXTAPI_SYMBOLSET_H
10 #define LLVM_TEXTAPI_SYMBOLSET_H
11 
12 #include "llvm/ADT/DenseMap.h"
13 #include "llvm/ADT/Hashing.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/ADT/iterator.h"
16 #include "llvm/ADT/iterator_range.h"
17 #include "llvm/Support/Allocator.h"
18 #include "llvm/TextAPI/Architecture.h"
19 #include "llvm/TextAPI/ArchitectureSet.h"
20 #include "llvm/TextAPI/Symbol.h"
21 #include <stddef.h>
22 
23 namespace llvm {
24 
25 struct SymbolsMapKey {
26   MachO::EncodeKind Kind;
27   StringRef Name;
28 
SymbolsMapKeySymbolsMapKey29   SymbolsMapKey(MachO::EncodeKind Kind, StringRef Name)
30       : Kind(Kind), Name(Name) {}
31 };
32 template <> struct DenseMapInfo<SymbolsMapKey> {
33   static inline SymbolsMapKey getEmptyKey() {
34     return SymbolsMapKey(MachO::EncodeKind::GlobalSymbol, StringRef{});
35   }
36 
37   static inline SymbolsMapKey getTombstoneKey() {
38     return SymbolsMapKey(MachO::EncodeKind::ObjectiveCInstanceVariable,
39                          StringRef{});
40   }
41 
42   static unsigned getHashValue(const SymbolsMapKey &Key) {
43     return hash_combine(hash_value(Key.Kind), hash_value(Key.Name));
44   }
45 
46   static bool isEqual(const SymbolsMapKey &LHS, const SymbolsMapKey &RHS) {
47     return std::tie(LHS.Kind, LHS.Name) == std::tie(RHS.Kind, RHS.Name);
48   }
49 };
50 
51 template <typename DerivedT, typename KeyInfoT, typename BucketT>
52 bool operator==(const DenseMapBase<DerivedT, SymbolsMapKey, MachO::Symbol *,
53                                    KeyInfoT, BucketT> &LHS,
54                 const DenseMapBase<DerivedT, SymbolsMapKey, MachO::Symbol *,
55                                    KeyInfoT, BucketT> &RHS) {
56   if (LHS.size() != RHS.size())
57     return false;
58   for (const auto &KV : LHS) {
59     auto I = RHS.find(KV.first);
60     if (I == RHS.end() || *I->second != *KV.second)
61       return false;
62   }
63   return true;
64 }
65 
66 template <typename DerivedT, typename KeyInfoT, typename BucketT>
67 bool operator!=(const DenseMapBase<DerivedT, SymbolsMapKey, MachO::Symbol *,
68                                    KeyInfoT, BucketT> &LHS,
69                 const DenseMapBase<DerivedT, SymbolsMapKey, MachO::Symbol *,
70                                    KeyInfoT, BucketT> &RHS) {
71   return !(LHS == RHS);
72 }
73 
74 namespace MachO {
75 
76 class SymbolSet {
77 private:
78   llvm::BumpPtrAllocator Allocator;
79   StringRef copyString(StringRef String) {
80     if (String.empty())
81       return {};
82     void *Ptr = Allocator.Allocate(String.size(), 1);
83     memcpy(Ptr, String.data(), String.size());
84     return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
85   }
86 
87   using SymbolsMapType = llvm::DenseMap<SymbolsMapKey, Symbol *>;
88   SymbolsMapType Symbols;
89 
90   Symbol *addGlobalImpl(EncodeKind, StringRef Name, SymbolFlags Flags);
91 
92 public:
93   SymbolSet() = default;
94   Symbol *addGlobal(EncodeKind Kind, StringRef Name, SymbolFlags Flags,
95                     const Target &Targ);
96   size_t size() const { return Symbols.size(); }
97 
98   template <typename RangeT, typename ElT = std::remove_reference_t<
99                                  decltype(*std::begin(std::declval<RangeT>()))>>
100   Symbol *addGlobal(EncodeKind Kind, StringRef Name, SymbolFlags Flags,
101                     RangeT &&Targets) {
102     auto *Global = addGlobalImpl(Kind, Name, Flags);
103     for (const auto &Targ : Targets)
104       Global->addTarget(Targ);
105     if (Kind == EncodeKind::ObjectiveCClassEHType)
106       addGlobal(EncodeKind::ObjectiveCClass, Name, Flags, Targets);
107     return Global;
108   }
109 
110   const Symbol *
111   findSymbol(EncodeKind Kind, StringRef Name,
112              ObjCIFSymbolKind ObjCIF = ObjCIFSymbolKind::None) const;
113 
114   struct const_symbol_iterator
115       : public iterator_adaptor_base<
116             const_symbol_iterator, SymbolsMapType::const_iterator,
117             std::forward_iterator_tag, const Symbol *, ptrdiff_t,
118             const Symbol *, const Symbol *> {
119     const_symbol_iterator() = default;
120 
121     template <typename U>
122     const_symbol_iterator(U &&u)
123         : iterator_adaptor_base(std::forward<U &&>(u)) {}
124 
125     reference operator*() const { return I->second; }
126     pointer operator->() const { return I->second; }
127   };
128 
129   using const_symbol_range = iterator_range<const_symbol_iterator>;
130 
131   using const_filtered_symbol_iterator =
132       filter_iterator<const_symbol_iterator,
133                       std::function<bool(const Symbol *)>>;
134   using const_filtered_symbol_range =
135       iterator_range<const_filtered_symbol_iterator>;
136 
137   // Range that contains all symbols.
138   const_symbol_range symbols() const {
139     return {Symbols.begin(), Symbols.end()};
140   }
141 
142   // Range that contains all defined and exported symbols.
143   const_filtered_symbol_range exports() const {
144     std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) {
145       return !Symbol->isUndefined() && !Symbol->isReexported();
146     };
147     return make_filter_range(
148         make_range<const_symbol_iterator>({Symbols.begin()}, {Symbols.end()}),
149         fn);
150   }
151 
152   // Range that contains all reexported symbols.
153   const_filtered_symbol_range reexports() const {
154     std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) {
155       return Symbol->isReexported();
156     };
157     return make_filter_range(
158         make_range<const_symbol_iterator>({Symbols.begin()}, {Symbols.end()}),
159         fn);
160   }
161 
162   // Range that contains all undefined and exported symbols.
163   const_filtered_symbol_range undefineds() const {
164     std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) {
165       return Symbol->isUndefined();
166     };
167     return make_filter_range(
168         make_range<const_symbol_iterator>({Symbols.begin()}, {Symbols.end()}),
169         fn);
170   }
171 
172   bool operator==(const SymbolSet &O) const;
173 
174   bool operator!=(const SymbolSet &O) const { return !(Symbols == O.Symbols); }
175 
176   void *allocate(size_t Size, unsigned Align = 8) {
177     return Allocator.Allocate(Size, Align);
178   }
179 };
180 
181 } // namespace MachO
182 } // namespace llvm
183 #endif // LLVM_TEXTAPI_SYMBOLSET_H
184