1b04b8975SCyndy Ishida //===- llvm/TextAPI/Record.h - TAPI Record ----------------------*- C++ -*-===// 2b04b8975SCyndy Ishida // 3b04b8975SCyndy Ishida // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4b04b8975SCyndy Ishida // See https://llvm.org/LICENSE.txt for license information. 5b04b8975SCyndy Ishida // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6b04b8975SCyndy Ishida // 7b04b8975SCyndy Ishida //===----------------------------------------------------------------------===// 8b04b8975SCyndy Ishida /// 9b04b8975SCyndy Ishida /// \file 10b04b8975SCyndy Ishida /// \brief Implements the TAPI Record Types. 11b04b8975SCyndy Ishida /// 12b04b8975SCyndy Ishida //===----------------------------------------------------------------------===// 13b04b8975SCyndy Ishida 14b04b8975SCyndy Ishida #ifndef LLVM_TEXTAPI_RECORD_H 15b04b8975SCyndy Ishida #define LLVM_TEXTAPI_RECORD_H 16b04b8975SCyndy Ishida 175ea15fabSCyndy Ishida #include "llvm/ADT/MapVector.h" 18b04b8975SCyndy Ishida #include "llvm/ADT/StringRef.h" 19b04b8975SCyndy Ishida #include "llvm/Support/Casting.h" 20b04b8975SCyndy Ishida #include "llvm/TextAPI/Symbol.h" 21b04b8975SCyndy Ishida #include <string> 22b04b8975SCyndy Ishida 23b04b8975SCyndy Ishida namespace llvm { 24b04b8975SCyndy Ishida namespace MachO { 25b04b8975SCyndy Ishida 26b04b8975SCyndy Ishida LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 27b04b8975SCyndy Ishida 28b04b8975SCyndy Ishida class RecordsSlice; 29b04b8975SCyndy Ishida 30*a4de589dSCyndy Ishida // Defines lightweight source location for records. 31*a4de589dSCyndy Ishida struct RecordLoc { 32*a4de589dSCyndy Ishida RecordLoc() = default; RecordLocRecordLoc33*a4de589dSCyndy Ishida RecordLoc(std::string File, unsigned Line) 34*a4de589dSCyndy Ishida : File(std::move(File)), Line(Line) {} 35*a4de589dSCyndy Ishida 36*a4de589dSCyndy Ishida /// Whether there is source location tied to the RecordLoc object. isValidRecordLoc37*a4de589dSCyndy Ishida bool isValid() const { return !File.empty(); } 38*a4de589dSCyndy Ishida 39*a4de589dSCyndy Ishida bool operator==(const RecordLoc &O) const { 40*a4de589dSCyndy Ishida return std::tie(File, Line) == std::tie(O.File, O.Line); 41*a4de589dSCyndy Ishida } 42*a4de589dSCyndy Ishida 43*a4de589dSCyndy Ishida const std::string File; 44*a4de589dSCyndy Ishida const unsigned Line = 0; 45*a4de589dSCyndy Ishida }; 46*a4de589dSCyndy Ishida 47b04b8975SCyndy Ishida // Defines a list of linkage types. 48b04b8975SCyndy Ishida enum class RecordLinkage : uint8_t { 49b04b8975SCyndy Ishida // Unknown linkage. 50b04b8975SCyndy Ishida Unknown = 0, 51b04b8975SCyndy Ishida 52b04b8975SCyndy Ishida // Local, hidden or private extern linkage. 53b04b8975SCyndy Ishida Internal = 1, 54b04b8975SCyndy Ishida 55b04b8975SCyndy Ishida // Undefined linkage, it represents usage of external interface. 56b04b8975SCyndy Ishida Undefined = 2, 57b04b8975SCyndy Ishida 58b04b8975SCyndy Ishida // Re-exported linkage, record is defined in external interface. 59b04b8975SCyndy Ishida Rexported = 3, 60b04b8975SCyndy Ishida 61b04b8975SCyndy Ishida // Exported linkage. 62b04b8975SCyndy Ishida Exported = 4, 63b04b8975SCyndy Ishida }; 64b04b8975SCyndy Ishida 65b04b8975SCyndy Ishida /// Define Record. They represent API's in binaries that could be linkable 66b04b8975SCyndy Ishida /// symbols. 67b04b8975SCyndy Ishida class Record { 68b04b8975SCyndy Ishida public: 69b04b8975SCyndy Ishida Record() = default; Record(StringRef Name,RecordLinkage Linkage,SymbolFlags Flags)70b04b8975SCyndy Ishida Record(StringRef Name, RecordLinkage Linkage, SymbolFlags Flags) 71f2794cceSCyndy Ishida : Name(Name), Linkage(Linkage), Flags(mergeFlags(Flags, Linkage)), 72f2794cceSCyndy Ishida Verified(false) {} 73b04b8975SCyndy Ishida isWeakDefined()74b04b8975SCyndy Ishida bool isWeakDefined() const { 75b04b8975SCyndy Ishida return (Flags & SymbolFlags::WeakDefined) == SymbolFlags::WeakDefined; 76b04b8975SCyndy Ishida } 77b04b8975SCyndy Ishida isWeakReferenced()78b04b8975SCyndy Ishida bool isWeakReferenced() const { 79b04b8975SCyndy Ishida return (Flags & SymbolFlags::WeakReferenced) == SymbolFlags::WeakReferenced; 80b04b8975SCyndy Ishida } 81b04b8975SCyndy Ishida isThreadLocalValue()82b04b8975SCyndy Ishida bool isThreadLocalValue() const { 83b04b8975SCyndy Ishida return (Flags & SymbolFlags::ThreadLocalValue) == 84b04b8975SCyndy Ishida SymbolFlags::ThreadLocalValue; 85b04b8975SCyndy Ishida } 86b04b8975SCyndy Ishida isData()87b04b8975SCyndy Ishida bool isData() const { 88b04b8975SCyndy Ishida return (Flags & SymbolFlags::Data) == SymbolFlags::Data; 89b04b8975SCyndy Ishida } 90b04b8975SCyndy Ishida isText()91b04b8975SCyndy Ishida bool isText() const { 92b04b8975SCyndy Ishida return (Flags & SymbolFlags::Text) == SymbolFlags::Text; 93b04b8975SCyndy Ishida } 94b04b8975SCyndy Ishida isInternal()95b04b8975SCyndy Ishida bool isInternal() const { return Linkage == RecordLinkage::Internal; } isUndefined()96b04b8975SCyndy Ishida bool isUndefined() const { return Linkage == RecordLinkage::Undefined; } isExported()97b04b8975SCyndy Ishida bool isExported() const { return Linkage >= RecordLinkage::Rexported; } isRexported()98b04b8975SCyndy Ishida bool isRexported() const { return Linkage == RecordLinkage::Rexported; } 99b04b8975SCyndy Ishida isVerified()100f2794cceSCyndy Ishida bool isVerified() const { return Verified; } 101f2794cceSCyndy Ishida void setVerify(bool V = true) { Verified = V; } 102f2794cceSCyndy Ishida getName()103b04b8975SCyndy Ishida StringRef getName() const { return Name; } getFlags()1045ea15fabSCyndy Ishida SymbolFlags getFlags() const { return Flags; } 1055ea15fabSCyndy Ishida 1065ea15fabSCyndy Ishida private: 1075ea15fabSCyndy Ishida SymbolFlags mergeFlags(SymbolFlags Flags, RecordLinkage Linkage); 108b04b8975SCyndy Ishida 109b04b8975SCyndy Ishida protected: 110b04b8975SCyndy Ishida StringRef Name; 111b04b8975SCyndy Ishida RecordLinkage Linkage; 112b04b8975SCyndy Ishida SymbolFlags Flags; 113f2794cceSCyndy Ishida bool Verified; 114b04b8975SCyndy Ishida 115b04b8975SCyndy Ishida friend class RecordsSlice; 116b04b8975SCyndy Ishida }; 117b04b8975SCyndy Ishida 118b04b8975SCyndy Ishida // Defines broadly non-objc records, categorized as variables or functions. 119b04b8975SCyndy Ishida class GlobalRecord : public Record { 120b04b8975SCyndy Ishida public: 121b04b8975SCyndy Ishida enum class Kind : uint8_t { 122b04b8975SCyndy Ishida Unknown = 0, 123b04b8975SCyndy Ishida Variable = 1, 124b04b8975SCyndy Ishida Function = 2, 125b04b8975SCyndy Ishida }; 126b04b8975SCyndy Ishida GlobalRecord(StringRef Name,RecordLinkage Linkage,SymbolFlags Flags,Kind GV,bool Inlined)127b04b8975SCyndy Ishida GlobalRecord(StringRef Name, RecordLinkage Linkage, SymbolFlags Flags, 12850ae8a2aSCyndy Ishida Kind GV, bool Inlined) 12950ae8a2aSCyndy Ishida : Record({Name, Linkage, Flags}), GV(GV), Inlined(Inlined) {} 130b04b8975SCyndy Ishida isFunction()131b04b8975SCyndy Ishida bool isFunction() const { return GV == Kind::Function; } isVariable()132b04b8975SCyndy Ishida bool isVariable() const { return GV == Kind::Variable; } setKind(const Kind & V)133e3627e26SCyndy Ishida void setKind(const Kind &V) { 134e3627e26SCyndy Ishida if (GV == Kind::Unknown) 135e3627e26SCyndy Ishida GV = V; 136e3627e26SCyndy Ishida } isInlined()13750ae8a2aSCyndy Ishida bool isInlined() const { return Inlined; } 138b04b8975SCyndy Ishida 139b04b8975SCyndy Ishida private: 140b04b8975SCyndy Ishida Kind GV; 14150ae8a2aSCyndy Ishida bool Inlined = false; 142b04b8975SCyndy Ishida }; 143b04b8975SCyndy Ishida 144b04b8975SCyndy Ishida // Define Objective-C instance variable records. 145b04b8975SCyndy Ishida class ObjCIVarRecord : public Record { 146b04b8975SCyndy Ishida public: ObjCIVarRecord(StringRef Name,RecordLinkage Linkage)147b04b8975SCyndy Ishida ObjCIVarRecord(StringRef Name, RecordLinkage Linkage) 148b04b8975SCyndy Ishida : Record({Name, Linkage, SymbolFlags::Data}) {} 149b04b8975SCyndy Ishida createScopedName(StringRef SuperClass,StringRef IVar)150b04b8975SCyndy Ishida static std::string createScopedName(StringRef SuperClass, StringRef IVar) { 151b04b8975SCyndy Ishida return (SuperClass + "." + IVar).str(); 152b04b8975SCyndy Ishida } 153b04b8975SCyndy Ishida }; 154b04b8975SCyndy Ishida 155b04b8975SCyndy Ishida template <typename V, typename K = StringRef, 156b04b8975SCyndy Ishida typename std::enable_if<std::is_base_of<Record, V>::value>::type * = 157b04b8975SCyndy Ishida nullptr> 158b04b8975SCyndy Ishida using RecordMap = llvm::MapVector<K, std::unique_ptr<V>>; 159b04b8975SCyndy Ishida 160b04b8975SCyndy Ishida // Defines Objective-C record types that have assigned methods, properties, 161b04b8975SCyndy Ishida // instance variable (ivars) and protocols. 162b04b8975SCyndy Ishida class ObjCContainerRecord : public Record { 163b04b8975SCyndy Ishida public: ObjCContainerRecord(StringRef Name,RecordLinkage Linkage)164b04b8975SCyndy Ishida ObjCContainerRecord(StringRef Name, RecordLinkage Linkage) 165b04b8975SCyndy Ishida : Record({Name, Linkage, SymbolFlags::Data}) {} 166b04b8975SCyndy Ishida 167b04b8975SCyndy Ishida ObjCIVarRecord *addObjCIVar(StringRef IVar, RecordLinkage Linkage); 168b04b8975SCyndy Ishida ObjCIVarRecord *findObjCIVar(StringRef IVar) const; 1695ea15fabSCyndy Ishida std::vector<ObjCIVarRecord *> getObjCIVars() const; getLinkage()17010ccde30SCyndy Ishida RecordLinkage getLinkage() const { return Linkage; } 171b04b8975SCyndy Ishida 172b04b8975SCyndy Ishida private: 173b04b8975SCyndy Ishida RecordMap<ObjCIVarRecord> IVars; 174b04b8975SCyndy Ishida }; 175b04b8975SCyndy Ishida 176b04b8975SCyndy Ishida // Define Objective-C category types. They don't generate linkable symbols, but 177b04b8975SCyndy Ishida // they have assigned ivars that do. 178b04b8975SCyndy Ishida class ObjCCategoryRecord : public ObjCContainerRecord { 179b04b8975SCyndy Ishida public: ObjCCategoryRecord(StringRef ClassToExtend,StringRef Name)180b04b8975SCyndy Ishida ObjCCategoryRecord(StringRef ClassToExtend, StringRef Name) 181b04b8975SCyndy Ishida : ObjCContainerRecord(Name, RecordLinkage::Unknown), 182b04b8975SCyndy Ishida ClassToExtend(ClassToExtend) {} 183b04b8975SCyndy Ishida getSuperClassName()184346766eaSCyndy Ishida StringRef getSuperClassName() const { return ClassToExtend; } 185346766eaSCyndy Ishida 186b04b8975SCyndy Ishida private: 187b04b8975SCyndy Ishida StringRef ClassToExtend; 188b04b8975SCyndy Ishida }; 189b04b8975SCyndy Ishida 190b04b8975SCyndy Ishida // Define Objective-C Interfaces or class types. 191b04b8975SCyndy Ishida class ObjCInterfaceRecord : public ObjCContainerRecord { 192b04b8975SCyndy Ishida public: ObjCInterfaceRecord(StringRef Name,RecordLinkage Linkage,ObjCIFSymbolKind SymType)193b04b8975SCyndy Ishida ObjCInterfaceRecord(StringRef Name, RecordLinkage Linkage, 1944460fa88SCyndy Ishida ObjCIFSymbolKind SymType) 1954460fa88SCyndy Ishida : ObjCContainerRecord(Name, Linkage) { 1964460fa88SCyndy Ishida updateLinkageForSymbols(SymType, Linkage); 1974460fa88SCyndy Ishida } 198b04b8975SCyndy Ishida hasExceptionAttribute()1994460fa88SCyndy Ishida bool hasExceptionAttribute() const { 2004460fa88SCyndy Ishida return Linkages.EHType != RecordLinkage::Unknown; 2014460fa88SCyndy Ishida } isCompleteInterface()2024460fa88SCyndy Ishida bool isCompleteInterface() const { 2034460fa88SCyndy Ishida return Linkages.Class >= RecordLinkage::Rexported && 2044460fa88SCyndy Ishida Linkages.MetaClass >= RecordLinkage::Rexported; 2054460fa88SCyndy Ishida } isExportedSymbol(ObjCIFSymbolKind CurrType)2064460fa88SCyndy Ishida bool isExportedSymbol(ObjCIFSymbolKind CurrType) const { 2074460fa88SCyndy Ishida return getLinkageForSymbol(CurrType) >= RecordLinkage::Rexported; 2084460fa88SCyndy Ishida } 2094460fa88SCyndy Ishida 2104460fa88SCyndy Ishida RecordLinkage getLinkageForSymbol(ObjCIFSymbolKind CurrType) const; 2114460fa88SCyndy Ishida void updateLinkageForSymbols(ObjCIFSymbolKind SymType, RecordLinkage Link); 2124460fa88SCyndy Ishida 213b04b8975SCyndy Ishida bool addObjCCategory(ObjCCategoryRecord *Record); 2145ea15fabSCyndy Ishida std::vector<ObjCCategoryRecord *> getObjCCategories() const; 215b04b8975SCyndy Ishida 216b04b8975SCyndy Ishida private: 2174460fa88SCyndy Ishida /// Linkage level for each symbol represented in ObjCInterfaceRecord. 2184460fa88SCyndy Ishida struct Linkages { 2194460fa88SCyndy Ishida RecordLinkage Class = RecordLinkage::Unknown; 2204460fa88SCyndy Ishida RecordLinkage MetaClass = RecordLinkage::Unknown; 2214460fa88SCyndy Ishida RecordLinkage EHType = RecordLinkage::Unknown; 2224460fa88SCyndy Ishida bool operator==(const Linkages &other) const { 2234460fa88SCyndy Ishida return std::tie(Class, MetaClass, EHType) == 2244460fa88SCyndy Ishida std::tie(other.Class, other.MetaClass, other.EHType); 2254460fa88SCyndy Ishida } 2264460fa88SCyndy Ishida bool operator!=(const Linkages &other) const { return !(*this == other); } 2274460fa88SCyndy Ishida }; 2284460fa88SCyndy Ishida Linkages Linkages; 2294460fa88SCyndy Ishida 230b04b8975SCyndy Ishida // Non-owning containers of categories that extend the class. 231b04b8975SCyndy Ishida llvm::MapVector<StringRef, ObjCCategoryRecord *> Categories; 232b04b8975SCyndy Ishida }; 233b04b8975SCyndy Ishida 234b04b8975SCyndy Ishida } // end namespace MachO. 235b04b8975SCyndy Ishida } // end namespace llvm. 236b04b8975SCyndy Ishida 237b04b8975SCyndy Ishida #endif // LLVM_TEXTAPI_RECORD_H 238