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 | |
29 | 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(args: hash_value(value: Key.Kind), args: hash_value(S: Key.Name)); |
44 | } |
45 | |
46 | static bool isEqual(const SymbolsMapKey &LHS, const SymbolsMapKey &RHS) { |
47 | return std::tie(args: LHS.Kind, args: LHS.Name) == std::tie(args: RHS.Kind, args: 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(Size: String.size(), Alignment: 1); |
83 | memcpy(dest: Ptr, src: String.data(), n: 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(InputTarget: 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 | Range: make_range<const_symbol_iterator>(x: {Symbols.begin()}, y: {Symbols.end()}), |
149 | Pred: 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 | Range: make_range<const_symbol_iterator>(x: {Symbols.begin()}, y: {Symbols.end()}), |
159 | Pred: 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 | Range: make_range<const_symbol_iterator>(x: {Symbols.begin()}, y: {Symbols.end()}), |
169 | Pred: 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, Alignment: Align); |
178 | } |
179 | }; |
180 | |
181 | } // namespace MachO |
182 | } // namespace llvm |
183 | #endif // LLVM_TEXTAPI_SYMBOLSET_H |
184 | |