1 //===- llvm/TextAPI/Record.h - TAPI Record ----------------------*- 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 /// \file 10 /// \brief Implements the TAPI Record Types. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_TEXTAPI_RECORD_H 15 #define LLVM_TEXTAPI_RECORD_H 16 17 #include "llvm/ADT/MapVector.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/Support/Casting.h" 20 #include "llvm/TextAPI/Symbol.h" 21 #include <string> 22 23 namespace llvm { 24 namespace MachO { 25 26 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); 27 28 class RecordsSlice; 29 30 // Defines lightweight source location for records. 31 struct RecordLoc { 32 RecordLoc() = default; RecordLocRecordLoc33 RecordLoc(std::string File, unsigned Line) 34 : File(std::move(File)), Line(Line) {} 35 36 /// Whether there is source location tied to the RecordLoc object. isValidRecordLoc37 bool isValid() const { return !File.empty(); } 38 39 bool operator==(const RecordLoc &O) const { 40 return std::tie(File, Line) == std::tie(O.File, O.Line); 41 } 42 43 const std::string File; 44 const unsigned Line = 0; 45 }; 46 47 // Defines a list of linkage types. 48 enum class RecordLinkage : uint8_t { 49 // Unknown linkage. 50 Unknown = 0, 51 52 // Local, hidden or private extern linkage. 53 Internal = 1, 54 55 // Undefined linkage, it represents usage of external interface. 56 Undefined = 2, 57 58 // Re-exported linkage, record is defined in external interface. 59 Rexported = 3, 60 61 // Exported linkage. 62 Exported = 4, 63 }; 64 65 /// Define Record. They represent API's in binaries that could be linkable 66 /// symbols. 67 class Record { 68 public: 69 Record() = default; Record(StringRef Name,RecordLinkage Linkage,SymbolFlags Flags)70 Record(StringRef Name, RecordLinkage Linkage, SymbolFlags Flags) 71 : Name(Name), Linkage(Linkage), Flags(mergeFlags(Flags, Linkage)), 72 Verified(false) {} 73 isWeakDefined()74 bool isWeakDefined() const { 75 return (Flags & SymbolFlags::WeakDefined) == SymbolFlags::WeakDefined; 76 } 77 isWeakReferenced()78 bool isWeakReferenced() const { 79 return (Flags & SymbolFlags::WeakReferenced) == SymbolFlags::WeakReferenced; 80 } 81 isThreadLocalValue()82 bool isThreadLocalValue() const { 83 return (Flags & SymbolFlags::ThreadLocalValue) == 84 SymbolFlags::ThreadLocalValue; 85 } 86 isData()87 bool isData() const { 88 return (Flags & SymbolFlags::Data) == SymbolFlags::Data; 89 } 90 isText()91 bool isText() const { 92 return (Flags & SymbolFlags::Text) == SymbolFlags::Text; 93 } 94 isInternal()95 bool isInternal() const { return Linkage == RecordLinkage::Internal; } isUndefined()96 bool isUndefined() const { return Linkage == RecordLinkage::Undefined; } isExported()97 bool isExported() const { return Linkage >= RecordLinkage::Rexported; } isRexported()98 bool isRexported() const { return Linkage == RecordLinkage::Rexported; } 99 isVerified()100 bool isVerified() const { return Verified; } 101 void setVerify(bool V = true) { Verified = V; } 102 getName()103 StringRef getName() const { return Name; } getFlags()104 SymbolFlags getFlags() const { return Flags; } 105 106 private: 107 SymbolFlags mergeFlags(SymbolFlags Flags, RecordLinkage Linkage); 108 109 protected: 110 StringRef Name; 111 RecordLinkage Linkage; 112 SymbolFlags Flags; 113 bool Verified; 114 115 friend class RecordsSlice; 116 }; 117 118 // Defines broadly non-objc records, categorized as variables or functions. 119 class GlobalRecord : public Record { 120 public: 121 enum class Kind : uint8_t { 122 Unknown = 0, 123 Variable = 1, 124 Function = 2, 125 }; 126 GlobalRecord(StringRef Name,RecordLinkage Linkage,SymbolFlags Flags,Kind GV,bool Inlined)127 GlobalRecord(StringRef Name, RecordLinkage Linkage, SymbolFlags Flags, 128 Kind GV, bool Inlined) 129 : Record({Name, Linkage, Flags}), GV(GV), Inlined(Inlined) {} 130 isFunction()131 bool isFunction() const { return GV == Kind::Function; } isVariable()132 bool isVariable() const { return GV == Kind::Variable; } setKind(const Kind & V)133 void setKind(const Kind &V) { 134 if (GV == Kind::Unknown) 135 GV = V; 136 } isInlined()137 bool isInlined() const { return Inlined; } 138 139 private: 140 Kind GV; 141 bool Inlined = false; 142 }; 143 144 // Define Objective-C instance variable records. 145 class ObjCIVarRecord : public Record { 146 public: ObjCIVarRecord(StringRef Name,RecordLinkage Linkage)147 ObjCIVarRecord(StringRef Name, RecordLinkage Linkage) 148 : Record({Name, Linkage, SymbolFlags::Data}) {} 149 createScopedName(StringRef SuperClass,StringRef IVar)150 static std::string createScopedName(StringRef SuperClass, StringRef IVar) { 151 return (SuperClass + "." + IVar).str(); 152 } 153 }; 154 155 template <typename V, typename K = StringRef, 156 typename std::enable_if<std::is_base_of<Record, V>::value>::type * = 157 nullptr> 158 using RecordMap = llvm::MapVector<K, std::unique_ptr<V>>; 159 160 // Defines Objective-C record types that have assigned methods, properties, 161 // instance variable (ivars) and protocols. 162 class ObjCContainerRecord : public Record { 163 public: ObjCContainerRecord(StringRef Name,RecordLinkage Linkage)164 ObjCContainerRecord(StringRef Name, RecordLinkage Linkage) 165 : Record({Name, Linkage, SymbolFlags::Data}) {} 166 167 ObjCIVarRecord *addObjCIVar(StringRef IVar, RecordLinkage Linkage); 168 ObjCIVarRecord *findObjCIVar(StringRef IVar) const; 169 std::vector<ObjCIVarRecord *> getObjCIVars() const; getLinkage()170 RecordLinkage getLinkage() const { return Linkage; } 171 172 private: 173 RecordMap<ObjCIVarRecord> IVars; 174 }; 175 176 // Define Objective-C category types. They don't generate linkable symbols, but 177 // they have assigned ivars that do. 178 class ObjCCategoryRecord : public ObjCContainerRecord { 179 public: ObjCCategoryRecord(StringRef ClassToExtend,StringRef Name)180 ObjCCategoryRecord(StringRef ClassToExtend, StringRef Name) 181 : ObjCContainerRecord(Name, RecordLinkage::Unknown), 182 ClassToExtend(ClassToExtend) {} 183 getSuperClassName()184 StringRef getSuperClassName() const { return ClassToExtend; } 185 186 private: 187 StringRef ClassToExtend; 188 }; 189 190 // Define Objective-C Interfaces or class types. 191 class ObjCInterfaceRecord : public ObjCContainerRecord { 192 public: ObjCInterfaceRecord(StringRef Name,RecordLinkage Linkage,ObjCIFSymbolKind SymType)193 ObjCInterfaceRecord(StringRef Name, RecordLinkage Linkage, 194 ObjCIFSymbolKind SymType) 195 : ObjCContainerRecord(Name, Linkage) { 196 updateLinkageForSymbols(SymType, Linkage); 197 } 198 hasExceptionAttribute()199 bool hasExceptionAttribute() const { 200 return Linkages.EHType != RecordLinkage::Unknown; 201 } isCompleteInterface()202 bool isCompleteInterface() const { 203 return Linkages.Class >= RecordLinkage::Rexported && 204 Linkages.MetaClass >= RecordLinkage::Rexported; 205 } isExportedSymbol(ObjCIFSymbolKind CurrType)206 bool isExportedSymbol(ObjCIFSymbolKind CurrType) const { 207 return getLinkageForSymbol(CurrType) >= RecordLinkage::Rexported; 208 } 209 210 RecordLinkage getLinkageForSymbol(ObjCIFSymbolKind CurrType) const; 211 void updateLinkageForSymbols(ObjCIFSymbolKind SymType, RecordLinkage Link); 212 213 bool addObjCCategory(ObjCCategoryRecord *Record); 214 std::vector<ObjCCategoryRecord *> getObjCCategories() const; 215 216 private: 217 /// Linkage level for each symbol represented in ObjCInterfaceRecord. 218 struct Linkages { 219 RecordLinkage Class = RecordLinkage::Unknown; 220 RecordLinkage MetaClass = RecordLinkage::Unknown; 221 RecordLinkage EHType = RecordLinkage::Unknown; 222 bool operator==(const Linkages &other) const { 223 return std::tie(Class, MetaClass, EHType) == 224 std::tie(other.Class, other.MetaClass, other.EHType); 225 } 226 bool operator!=(const Linkages &other) const { return !(*this == other); } 227 }; 228 Linkages Linkages; 229 230 // Non-owning containers of categories that extend the class. 231 llvm::MapVector<StringRef, ObjCCategoryRecord *> Categories; 232 }; 233 234 } // end namespace MachO. 235 } // end namespace llvm. 236 237 #endif // LLVM_TEXTAPI_RECORD_H 238