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