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