xref: /freebsd/contrib/llvm-project/llvm/include/llvm/TextAPI/Record.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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