10116d04dSCyndy Ishida //===- llvm/TextAPI/Symbol.h - TAPI Symbol ----------------------*- C++ -*-===//
20116d04dSCyndy Ishida //
30116d04dSCyndy Ishida // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40116d04dSCyndy Ishida // See https://llvm.org/LICENSE.txt for license information.
50116d04dSCyndy Ishida // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60116d04dSCyndy Ishida //
70116d04dSCyndy Ishida //===----------------------------------------------------------------------===//
80116d04dSCyndy Ishida
9eec96db1SKazu Hirata #ifndef LLVM_TEXTAPI_SYMBOL_H
10eec96db1SKazu Hirata #define LLVM_TEXTAPI_SYMBOL_H
110116d04dSCyndy Ishida
120116d04dSCyndy Ishida #include "llvm/ADT/BitmaskEnum.h"
130116d04dSCyndy Ishida #include "llvm/ADT/StringRef.h"
140116d04dSCyndy Ishida #include "llvm/Support/raw_ostream.h"
150116d04dSCyndy Ishida #include "llvm/TextAPI/ArchitectureSet.h"
160116d04dSCyndy Ishida #include "llvm/TextAPI/Target.h"
170116d04dSCyndy Ishida
180116d04dSCyndy Ishida namespace llvm {
190116d04dSCyndy Ishida namespace MachO {
200116d04dSCyndy Ishida
210116d04dSCyndy Ishida // clang-format off
220116d04dSCyndy Ishida
230116d04dSCyndy Ishida /// Symbol flags.
240116d04dSCyndy Ishida enum class SymbolFlags : uint8_t {
250116d04dSCyndy Ishida /// No flags
260116d04dSCyndy Ishida None = 0,
270116d04dSCyndy Ishida
280116d04dSCyndy Ishida /// Thread-local value symbol
290116d04dSCyndy Ishida ThreadLocalValue = 1U << 0,
300116d04dSCyndy Ishida
310116d04dSCyndy Ishida /// Weak defined symbol
320116d04dSCyndy Ishida WeakDefined = 1U << 1,
330116d04dSCyndy Ishida
340116d04dSCyndy Ishida /// Weak referenced symbol
350116d04dSCyndy Ishida WeakReferenced = 1U << 2,
360116d04dSCyndy Ishida
370116d04dSCyndy Ishida /// Undefined
380116d04dSCyndy Ishida Undefined = 1U << 3,
390116d04dSCyndy Ishida
400116d04dSCyndy Ishida /// Rexported
410116d04dSCyndy Ishida Rexported = 1U << 4,
420116d04dSCyndy Ishida
43b70d87bcSCyndy Ishida /// Data Segment
44b70d87bcSCyndy Ishida Data = 1U << 5,
45b70d87bcSCyndy Ishida
46b70d87bcSCyndy Ishida /// Text Segment
47b70d87bcSCyndy Ishida Text = 1U << 6,
48b70d87bcSCyndy Ishida
49b70d87bcSCyndy Ishida LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/Text),
500116d04dSCyndy Ishida };
510116d04dSCyndy Ishida
520116d04dSCyndy Ishida // clang-format on
530116d04dSCyndy Ishida
54d9a9872eSCyndy Ishida /// Mapping of entry types in TextStubs.
55d9a9872eSCyndy Ishida enum class EncodeKind : uint8_t {
560116d04dSCyndy Ishida GlobalSymbol,
570116d04dSCyndy Ishida ObjectiveCClass,
580116d04dSCyndy Ishida ObjectiveCClassEHType,
590116d04dSCyndy Ishida ObjectiveCInstanceVariable,
600116d04dSCyndy Ishida };
610116d04dSCyndy Ishida
6256709b86SCyndy Ishida constexpr StringLiteral ObjC1ClassNamePrefix = ".objc_class_name_";
6356709b86SCyndy Ishida constexpr StringLiteral ObjC2ClassNamePrefix = "_OBJC_CLASS_$_";
6456709b86SCyndy Ishida constexpr StringLiteral ObjC2MetaClassNamePrefix = "_OBJC_METACLASS_$_";
6556709b86SCyndy Ishida constexpr StringLiteral ObjC2EHTypePrefix = "_OBJC_EHTYPE_$_";
6656709b86SCyndy Ishida constexpr StringLiteral ObjC2IVarPrefix = "_OBJC_IVAR_$_";
6756709b86SCyndy Ishida
684460fa88SCyndy Ishida /// ObjC Interface symbol mappings.
694460fa88SCyndy Ishida enum class ObjCIFSymbolKind : uint8_t {
704460fa88SCyndy Ishida None = 0,
714460fa88SCyndy Ishida /// Is OBJC_CLASS* symbol.
724460fa88SCyndy Ishida Class = 1U << 0,
734460fa88SCyndy Ishida /// Is OBJC_METACLASS* symbol.
744460fa88SCyndy Ishida MetaClass = 1U << 1,
754460fa88SCyndy Ishida /// Is OBJC_EHTYPE* symbol.
764460fa88SCyndy Ishida EHType = 1U << 2,
774460fa88SCyndy Ishida
784460fa88SCyndy Ishida LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/EHType),
794460fa88SCyndy Ishida };
804460fa88SCyndy Ishida
810116d04dSCyndy Ishida using TargetList = SmallVector<Target, 5>;
820882c70dSCyndy Ishida
830882c70dSCyndy Ishida // Keep containers that hold Targets in sorted order and uniqued.
840882c70dSCyndy Ishida template <typename C>
addEntry(C & Container,const Target & Targ)850882c70dSCyndy Ishida typename C::iterator addEntry(C &Container, const Target &Targ) {
860882c70dSCyndy Ishida auto Iter =
870882c70dSCyndy Ishida lower_bound(Container, Targ, [](const Target &LHS, const Target &RHS) {
880882c70dSCyndy Ishida return LHS < RHS;
890882c70dSCyndy Ishida });
900882c70dSCyndy Ishida if ((Iter != std::end(Container)) && !(Targ < *Iter))
910882c70dSCyndy Ishida return Iter;
920882c70dSCyndy Ishida
930882c70dSCyndy Ishida return Container.insert(Iter, Targ);
940882c70dSCyndy Ishida }
950882c70dSCyndy Ishida
960116d04dSCyndy Ishida class Symbol {
970116d04dSCyndy Ishida public:
Symbol(EncodeKind Kind,StringRef Name,TargetList Targets,SymbolFlags Flags)98d9a9872eSCyndy Ishida Symbol(EncodeKind Kind, StringRef Name, TargetList Targets, SymbolFlags Flags)
990116d04dSCyndy Ishida : Name(Name), Targets(std::move(Targets)), Kind(Kind), Flags(Flags) {}
1000116d04dSCyndy Ishida
addTarget(Target InputTarget)1010882c70dSCyndy Ishida void addTarget(Target InputTarget) { addEntry(Targets, InputTarget); }
getKind()102d9a9872eSCyndy Ishida EncodeKind getKind() const { return Kind; }
getName()1030116d04dSCyndy Ishida StringRef getName() const { return Name; }
getArchitectures()1040116d04dSCyndy Ishida ArchitectureSet getArchitectures() const {
1050116d04dSCyndy Ishida return mapToArchitectureSet(Targets);
1060116d04dSCyndy Ishida }
getFlags()1070116d04dSCyndy Ishida SymbolFlags getFlags() const { return Flags; }
1080116d04dSCyndy Ishida
isWeakDefined()1090116d04dSCyndy Ishida bool isWeakDefined() const {
1100116d04dSCyndy Ishida return (Flags & SymbolFlags::WeakDefined) == SymbolFlags::WeakDefined;
1110116d04dSCyndy Ishida }
1120116d04dSCyndy Ishida
isWeakReferenced()1130116d04dSCyndy Ishida bool isWeakReferenced() const {
1140116d04dSCyndy Ishida return (Flags & SymbolFlags::WeakReferenced) == SymbolFlags::WeakReferenced;
1150116d04dSCyndy Ishida }
1160116d04dSCyndy Ishida
isThreadLocalValue()1170116d04dSCyndy Ishida bool isThreadLocalValue() const {
1180116d04dSCyndy Ishida return (Flags & SymbolFlags::ThreadLocalValue) ==
1190116d04dSCyndy Ishida SymbolFlags::ThreadLocalValue;
1200116d04dSCyndy Ishida }
1210116d04dSCyndy Ishida
isUndefined()1220116d04dSCyndy Ishida bool isUndefined() const {
1230116d04dSCyndy Ishida return (Flags & SymbolFlags::Undefined) == SymbolFlags::Undefined;
1240116d04dSCyndy Ishida }
1250116d04dSCyndy Ishida
isReexported()1260116d04dSCyndy Ishida bool isReexported() const {
1270116d04dSCyndy Ishida return (Flags & SymbolFlags::Rexported) == SymbolFlags::Rexported;
1280116d04dSCyndy Ishida }
1290116d04dSCyndy Ishida
isData()130b70d87bcSCyndy Ishida bool isData() const {
131b70d87bcSCyndy Ishida return (Flags & SymbolFlags::Data) == SymbolFlags::Data;
132b70d87bcSCyndy Ishida }
133b70d87bcSCyndy Ishida
isText()134b70d87bcSCyndy Ishida bool isText() const {
135b70d87bcSCyndy Ishida return (Flags & SymbolFlags::Text) == SymbolFlags::Text;
136b70d87bcSCyndy Ishida }
137b70d87bcSCyndy Ishida
hasArchitecture(Architecture Arch)13816c1f436SCyndy Ishida bool hasArchitecture(Architecture Arch) const {
13916c1f436SCyndy Ishida return mapToArchitectureSet(Targets).contains(Arch);
14016c1f436SCyndy Ishida }
14116c1f436SCyndy Ishida
hasTarget(const Target & Targ)14227459a3aSCyndy Ishida bool hasTarget(const Target &Targ) const {
14327459a3aSCyndy Ishida return llvm::is_contained(Targets, Targ);
14427459a3aSCyndy Ishida }
14527459a3aSCyndy Ishida
1460116d04dSCyndy Ishida using const_target_iterator = TargetList::const_iterator;
1470116d04dSCyndy Ishida using const_target_range = llvm::iterator_range<const_target_iterator>;
targets()1480116d04dSCyndy Ishida const_target_range targets() const { return {Targets}; }
1490116d04dSCyndy Ishida
1500116d04dSCyndy Ishida using const_filtered_target_iterator =
1510116d04dSCyndy Ishida llvm::filter_iterator<const_target_iterator,
1520116d04dSCyndy Ishida std::function<bool(const Target &)>>;
1530116d04dSCyndy Ishida using const_filtered_target_range =
1540116d04dSCyndy Ishida llvm::iterator_range<const_filtered_target_iterator>;
1550116d04dSCyndy Ishida const_filtered_target_range targets(ArchitectureSet architectures) const;
1560116d04dSCyndy Ishida
1570116d04dSCyndy Ishida #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
1580116d04dSCyndy Ishida void dump(raw_ostream &OS) const;
dump()1590116d04dSCyndy Ishida void dump() const { dump(llvm::errs()); }
1600116d04dSCyndy Ishida #endif
1610116d04dSCyndy Ishida
162bc85cf16SCyndy Ishida bool operator==(const Symbol &O) const;
1630116d04dSCyndy Ishida
1640116d04dSCyndy Ishida bool operator!=(const Symbol &O) const { return !(*this == O); }
1650116d04dSCyndy Ishida
1665b5ab80eSSam Powell bool operator<(const Symbol &O) const {
16727459a3aSCyndy Ishida return std::tie(Kind, Name) < std::tie(O.Kind, O.Name);
1685b5ab80eSSam Powell }
1695b5ab80eSSam Powell
1700116d04dSCyndy Ishida private:
1710116d04dSCyndy Ishida StringRef Name;
1720116d04dSCyndy Ishida TargetList Targets;
173d9a9872eSCyndy Ishida EncodeKind Kind;
1740116d04dSCyndy Ishida SymbolFlags Flags;
1750116d04dSCyndy Ishida };
1760116d04dSCyndy Ishida
177b04b8975SCyndy Ishida /// Lightweight struct for passing around symbol information.
178b04b8975SCyndy Ishida struct SimpleSymbol {
179b04b8975SCyndy Ishida StringRef Name;
180d9a9872eSCyndy Ishida EncodeKind Kind;
1814460fa88SCyndy Ishida ObjCIFSymbolKind ObjCInterfaceType;
182b04b8975SCyndy Ishida
183b04b8975SCyndy Ishida bool operator<(const SimpleSymbol &O) const {
1844460fa88SCyndy Ishida return std::tie(Name, Kind, ObjCInterfaceType) <
1854460fa88SCyndy Ishida std::tie(O.Name, O.Kind, O.ObjCInterfaceType);
186b04b8975SCyndy Ishida }
187b04b8975SCyndy Ishida };
188b04b8975SCyndy Ishida
1894460fa88SCyndy Ishida /// Get symbol classification by parsing the name of a symbol.
190b04b8975SCyndy Ishida ///
191*97d72839SCyndy Ishida /// \param SymName The name of symbol.
1924460fa88SCyndy Ishida SimpleSymbol parseSymbol(StringRef SymName);
193b04b8975SCyndy Ishida
1940116d04dSCyndy Ishida } // end namespace MachO.
1950116d04dSCyndy Ishida } // end namespace llvm.
1960116d04dSCyndy Ishida
197eec96db1SKazu Hirata #endif // LLVM_TEXTAPI_SYMBOL_H
198