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