| 1 | //===- llvm/TextAPI/Symbol.h - TAPI Symbol ----------------------*- 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_SYMBOL_H |
| 10 | #define LLVM_TEXTAPI_SYMBOL_H |
| 11 | |
| 12 | #include "llvm/ADT/BitmaskEnum.h" |
| 13 | #include "llvm/ADT/StringRef.h" |
| 14 | #include "llvm/Support/Compiler.h" |
| 15 | #include "llvm/Support/raw_ostream.h" |
| 16 | #include "llvm/TextAPI/ArchitectureSet.h" |
| 17 | #include "llvm/TextAPI/Target.h" |
| 18 | |
| 19 | namespace llvm { |
| 20 | namespace MachO { |
| 21 | |
| 22 | // clang-format off |
| 23 | |
| 24 | /// Symbol flags. |
| 25 | enum class SymbolFlags : uint8_t { |
| 26 | /// No flags |
| 27 | None = 0, |
| 28 | |
| 29 | /// Thread-local value symbol |
| 30 | ThreadLocalValue = 1U << 0, |
| 31 | |
| 32 | /// Weak defined symbol |
| 33 | WeakDefined = 1U << 1, |
| 34 | |
| 35 | /// Weak referenced symbol |
| 36 | WeakReferenced = 1U << 2, |
| 37 | |
| 38 | /// Undefined |
| 39 | Undefined = 1U << 3, |
| 40 | |
| 41 | /// Rexported |
| 42 | Rexported = 1U << 4, |
| 43 | |
| 44 | /// Data Segment |
| 45 | Data = 1U << 5, |
| 46 | |
| 47 | /// Text Segment |
| 48 | Text = 1U << 6, |
| 49 | |
| 50 | LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Text), |
| 51 | }; |
| 52 | |
| 53 | // clang-format on |
| 54 | |
| 55 | /// Mapping of entry types in TextStubs. |
| 56 | enum class EncodeKind : uint8_t { |
| 57 | GlobalSymbol, |
| 58 | ObjectiveCClass, |
| 59 | ObjectiveCClassEHType, |
| 60 | ObjectiveCInstanceVariable, |
| 61 | }; |
| 62 | |
| 63 | constexpr StringLiteral ObjC1ClassNamePrefix = ".objc_class_name_" ; |
| 64 | constexpr StringLiteral ObjC2ClassNamePrefix = "_OBJC_CLASS_$_" ; |
| 65 | constexpr StringLiteral ObjC2MetaClassNamePrefix = "_OBJC_METACLASS_$_" ; |
| 66 | constexpr StringLiteral ObjC2EHTypePrefix = "_OBJC_EHTYPE_$_" ; |
| 67 | constexpr StringLiteral ObjC2IVarPrefix = "_OBJC_IVAR_$_" ; |
| 68 | |
| 69 | /// ObjC Interface symbol mappings. |
| 70 | enum class ObjCIFSymbolKind : uint8_t { |
| 71 | None = 0, |
| 72 | /// Is OBJC_CLASS* symbol. |
| 73 | Class = 1U << 0, |
| 74 | /// Is OBJC_METACLASS* symbol. |
| 75 | MetaClass = 1U << 1, |
| 76 | /// Is OBJC_EHTYPE* symbol. |
| 77 | EHType = 1U << 2, |
| 78 | |
| 79 | LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/EHType), |
| 80 | }; |
| 81 | |
| 82 | using TargetList = SmallVector<Target, 5>; |
| 83 | |
| 84 | // Keep containers that hold Targets in sorted order and uniqued. |
| 85 | template <typename C> |
| 86 | typename C::iterator addEntry(C &Container, const Target &Targ) { |
| 87 | auto Iter = |
| 88 | lower_bound(Container, Targ, [](const Target &LHS, const Target &RHS) { |
| 89 | return LHS < RHS; |
| 90 | }); |
| 91 | if ((Iter != std::end(Container)) && !(Targ < *Iter)) |
| 92 | return Iter; |
| 93 | |
| 94 | return Container.insert(Iter, Targ); |
| 95 | } |
| 96 | |
| 97 | class Symbol { |
| 98 | public: |
| 99 | Symbol(EncodeKind Kind, StringRef Name, TargetList Targets, SymbolFlags Flags) |
| 100 | : Name(Name), Targets(std::move(Targets)), Kind(Kind), Flags(Flags) {} |
| 101 | |
| 102 | void addTarget(Target InputTarget) { addEntry(Container&: Targets, Targ: InputTarget); } |
| 103 | EncodeKind getKind() const { return Kind; } |
| 104 | StringRef getName() const { return Name; } |
| 105 | ArchitectureSet getArchitectures() const { |
| 106 | return mapToArchitectureSet(Targets); |
| 107 | } |
| 108 | SymbolFlags getFlags() const { return Flags; } |
| 109 | |
| 110 | bool isWeakDefined() const { |
| 111 | return (Flags & SymbolFlags::WeakDefined) == SymbolFlags::WeakDefined; |
| 112 | } |
| 113 | |
| 114 | bool isWeakReferenced() const { |
| 115 | return (Flags & SymbolFlags::WeakReferenced) == SymbolFlags::WeakReferenced; |
| 116 | } |
| 117 | |
| 118 | bool isThreadLocalValue() const { |
| 119 | return (Flags & SymbolFlags::ThreadLocalValue) == |
| 120 | SymbolFlags::ThreadLocalValue; |
| 121 | } |
| 122 | |
| 123 | bool isUndefined() const { |
| 124 | return (Flags & SymbolFlags::Undefined) == SymbolFlags::Undefined; |
| 125 | } |
| 126 | |
| 127 | bool isReexported() const { |
| 128 | return (Flags & SymbolFlags::Rexported) == SymbolFlags::Rexported; |
| 129 | } |
| 130 | |
| 131 | bool isData() const { |
| 132 | return (Flags & SymbolFlags::Data) == SymbolFlags::Data; |
| 133 | } |
| 134 | |
| 135 | bool isText() const { |
| 136 | return (Flags & SymbolFlags::Text) == SymbolFlags::Text; |
| 137 | } |
| 138 | |
| 139 | bool hasArchitecture(Architecture Arch) const { |
| 140 | return mapToArchitectureSet(Targets).contains(Archs: Arch); |
| 141 | } |
| 142 | |
| 143 | bool hasTarget(const Target &Targ) const { |
| 144 | return llvm::is_contained(Range: Targets, Element: Targ); |
| 145 | } |
| 146 | |
| 147 | using const_target_iterator = TargetList::const_iterator; |
| 148 | using const_target_range = llvm::iterator_range<const_target_iterator>; |
| 149 | const_target_range targets() const { return {Targets}; } |
| 150 | |
| 151 | using const_filtered_target_iterator = |
| 152 | llvm::filter_iterator<const_target_iterator, |
| 153 | std::function<bool(const Target &)>>; |
| 154 | using const_filtered_target_range = |
| 155 | llvm::iterator_range<const_filtered_target_iterator>; |
| 156 | LLVM_ABI const_filtered_target_range |
| 157 | targets(ArchitectureSet architectures) const; |
| 158 | |
| 159 | #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP) |
| 160 | void dump(raw_ostream &OS) const; |
| 161 | void dump() const { dump(llvm::errs()); } |
| 162 | #endif |
| 163 | |
| 164 | LLVM_ABI bool operator==(const Symbol &O) const; |
| 165 | |
| 166 | bool operator!=(const Symbol &O) const { return !(*this == O); } |
| 167 | |
| 168 | bool operator<(const Symbol &O) const { |
| 169 | return std::tie(args: Kind, args: Name) < std::tie(args: O.Kind, args: O.Name); |
| 170 | } |
| 171 | |
| 172 | private: |
| 173 | StringRef Name; |
| 174 | TargetList Targets; |
| 175 | EncodeKind Kind; |
| 176 | SymbolFlags Flags; |
| 177 | }; |
| 178 | |
| 179 | /// Lightweight struct for passing around symbol information. |
| 180 | struct SimpleSymbol { |
| 181 | StringRef Name; |
| 182 | EncodeKind Kind; |
| 183 | ObjCIFSymbolKind ObjCInterfaceType; |
| 184 | |
| 185 | bool operator<(const SimpleSymbol &O) const { |
| 186 | return std::tie(args: Name, args: Kind, args: ObjCInterfaceType) < |
| 187 | std::tie(args: O.Name, args: O.Kind, args: O.ObjCInterfaceType); |
| 188 | } |
| 189 | }; |
| 190 | |
| 191 | /// Get symbol classification by parsing the name of a symbol. |
| 192 | /// |
| 193 | /// \param SymName The name of symbol. |
| 194 | LLVM_ABI SimpleSymbol parseSymbol(StringRef SymName); |
| 195 | |
| 196 | } // end namespace MachO. |
| 197 | } // end namespace llvm. |
| 198 | |
| 199 | #endif // LLVM_TEXTAPI_SYMBOL_H |
| 200 | |