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