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::SymbolKind Kind;
27   StringRef Name;
28 
29   SymbolsMapKey(MachO::SymbolKind Kind, StringRef Name)
30       : Kind(Kind), Name(Name) {}
31 };
32 template <> struct DenseMapInfo<SymbolsMapKey> {
33   static inline SymbolsMapKey getEmptyKey() {
34     return SymbolsMapKey(MachO::SymbolKind::GlobalSymbol, StringRef{});
35   }
36 
37   static inline SymbolsMapKey getTombstoneKey() {
38     return SymbolsMapKey(MachO::SymbolKind::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(SymbolKind, StringRef Name, SymbolFlags Flags);
91 
92 public:
93   SymbolSet() = default;
94   Symbol *addGlobal(SymbolKind Kind, StringRef Name, SymbolFlags Flags,
95                     const Target &Targ);
96   size_t size() const { return Symbols.size(); }
97 
98   template <typename RangeT,
99             typename ElT = typename std::remove_reference<
100                 decltype(*std::begin(std::declval<RangeT>()))>::type>
101   Symbol *addGlobal(SymbolKind 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 == SymbolKind::ObjectiveCClassEHType)
107       addGlobal(SymbolKind::ObjectiveCClass, Name, Flags, Targets);
108     return Global;
109   }
110 
111   const Symbol *findSymbol(SymbolKind Kind, StringRef Name) const;
112 
113   struct const_symbol_iterator
114       : public iterator_adaptor_base<
115             const_symbol_iterator, SymbolsMapType::const_iterator,
116             std::forward_iterator_tag, const Symbol *, ptrdiff_t,
117             const Symbol *, const Symbol *> {
118     const_symbol_iterator() = default;
119 
120     template <typename U>
121     const_symbol_iterator(U &&u)
122         : iterator_adaptor_base(std::forward<U &&>(u)) {}
123 
124     reference operator*() const { return I->second; }
125     pointer operator->() const { return I->second; }
126   };
127 
128   using const_symbol_range = iterator_range<const_symbol_iterator>;
129 
130   using const_filtered_symbol_iterator =
131       filter_iterator<const_symbol_iterator,
132                       std::function<bool(const Symbol *)>>;
133   using const_filtered_symbol_range =
134       iterator_range<const_filtered_symbol_iterator>;
135 
136   // Range that contains all symbols.
137   const_symbol_range symbols() const {
138     return {Symbols.begin(), Symbols.end()};
139   }
140 
141   // Range that contains all defined and exported symbols.
142   const_filtered_symbol_range exports() const {
143     std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) {
144       return !Symbol->isUndefined() && !Symbol->isReexported();
145     };
146     return make_filter_range(
147         make_range<const_symbol_iterator>({Symbols.begin()}, {Symbols.end()}),
148         fn);
149   }
150 
151   // Range that contains all reexported symbols.
152   const_filtered_symbol_range reexports() const {
153     std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) {
154       return Symbol->isReexported();
155     };
156     return make_filter_range(
157         make_range<const_symbol_iterator>({Symbols.begin()}, {Symbols.end()}),
158         fn);
159   }
160 
161   // Range that contains all undefined and exported symbols.
162   const_filtered_symbol_range undefineds() const {
163     std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) {
164       return Symbol->isUndefined();
165     };
166     return make_filter_range(
167         make_range<const_symbol_iterator>({Symbols.begin()}, {Symbols.end()}),
168         fn);
169   }
170 
171   bool operator==(const SymbolSet &O) const;
172 
173   bool operator!=(const SymbolSet &O) const { return !(Symbols == O.Symbols); }
174 
175   void *allocate(size_t Size, unsigned Align = 8) {
176     return Allocator.Allocate(Size, Align);
177   }
178 };
179 
180 } // namespace MachO
181 } // namespace llvm
182 #endif // LLVM_TEXTAPI_SYMBOLSET_H
183