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
23namespace llvm {
24namespace MachO {
25
26LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
27
28class RecordsSlice;
29
30// Defines lightweight source location for records.
31struct RecordLoc {
32 RecordLoc() = default;
33 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.
37 bool isValid() const { return !File.empty(); }
38
39 bool operator==(const RecordLoc &O) const {
40 return std::tie(args: File, args: Line) == std::tie(args: O.File, args: O.Line);
41 }
42
43 const std::string File;
44 const unsigned Line = 0;
45};
46
47// Defines a list of linkage types.
48enum 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.
67class Record {
68public:
69 Record() = default;
70 Record(StringRef Name, RecordLinkage Linkage, SymbolFlags Flags)
71 : Name(Name), Linkage(Linkage), Flags(mergeFlags(Flags, Linkage)),
72 Verified(false) {}
73
74 bool isWeakDefined() const {
75 return (Flags & SymbolFlags::WeakDefined) == SymbolFlags::WeakDefined;
76 }
77
78 bool isWeakReferenced() const {
79 return (Flags & SymbolFlags::WeakReferenced) == SymbolFlags::WeakReferenced;
80 }
81
82 bool isThreadLocalValue() const {
83 return (Flags & SymbolFlags::ThreadLocalValue) ==
84 SymbolFlags::ThreadLocalValue;
85 }
86
87 bool isData() const {
88 return (Flags & SymbolFlags::Data) == SymbolFlags::Data;
89 }
90
91 bool isText() const {
92 return (Flags & SymbolFlags::Text) == SymbolFlags::Text;
93 }
94
95 bool isInternal() const { return Linkage == RecordLinkage::Internal; }
96 bool isUndefined() const { return Linkage == RecordLinkage::Undefined; }
97 bool isExported() const { return Linkage >= RecordLinkage::Rexported; }
98 bool isRexported() const { return Linkage == RecordLinkage::Rexported; }
99
100 bool isVerified() const { return Verified; }
101 void setVerify(bool V = true) { Verified = V; }
102
103 StringRef getName() const { return Name; }
104 SymbolFlags getFlags() const { return Flags; }
105
106private:
107 SymbolFlags mergeFlags(SymbolFlags Flags, RecordLinkage Linkage);
108
109protected:
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.
119class GlobalRecord : public Record {
120public:
121 enum class Kind : uint8_t {
122 Unknown = 0,
123 Variable = 1,
124 Function = 2,
125 };
126
127 GlobalRecord(StringRef Name, RecordLinkage Linkage, SymbolFlags Flags,
128 Kind GV, bool Inlined)
129 : Record({Name, Linkage, Flags}), GV(GV), Inlined(Inlined) {}
130
131 bool isFunction() const { return GV == Kind::Function; }
132 bool isVariable() const { return GV == Kind::Variable; }
133 void setKind(const Kind &V) {
134 if (GV == Kind::Unknown)
135 GV = V;
136 }
137 bool isInlined() const { return Inlined; }
138
139private:
140 Kind GV;
141 bool Inlined = false;
142};
143
144// Define Objective-C instance variable records.
145class ObjCIVarRecord : public Record {
146public:
147 ObjCIVarRecord(StringRef Name, RecordLinkage Linkage)
148 : Record({Name, Linkage, SymbolFlags::Data}) {}
149
150 static std::string createScopedName(StringRef SuperClass, StringRef IVar) {
151 return (SuperClass + "." + IVar).str();
152 }
153};
154
155template <typename V, typename K = StringRef,
156 typename std::enable_if<std::is_base_of<Record, V>::value>::type * =
157 nullptr>
158using 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.
162class ObjCContainerRecord : public Record {
163public:
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;
170 RecordLinkage getLinkage() const { return Linkage; }
171
172private:
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.
178class ObjCCategoryRecord : public ObjCContainerRecord {
179public:
180 ObjCCategoryRecord(StringRef ClassToExtend, StringRef Name)
181 : ObjCContainerRecord(Name, RecordLinkage::Unknown),
182 ClassToExtend(ClassToExtend) {}
183
184 StringRef getSuperClassName() const { return ClassToExtend; }
185
186private:
187 StringRef ClassToExtend;
188};
189
190// Define Objective-C Interfaces or class types.
191class ObjCInterfaceRecord : public ObjCContainerRecord {
192public:
193 ObjCInterfaceRecord(StringRef Name, RecordLinkage Linkage,
194 ObjCIFSymbolKind SymType)
195 : ObjCContainerRecord(Name, Linkage) {
196 updateLinkageForSymbols(SymType, Link: Linkage);
197 }
198
199 bool hasExceptionAttribute() const {
200 return Linkages.EHType != RecordLinkage::Unknown;
201 }
202 bool isCompleteInterface() const {
203 return Linkages.Class >= RecordLinkage::Rexported &&
204 Linkages.MetaClass >= RecordLinkage::Rexported;
205 }
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
216private:
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(args: Class, args: MetaClass, args: EHType) ==
224 std::tie(args: other.Class, args: other.MetaClass, args: 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

source code of llvm/include/llvm/TextAPI/Record.h