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