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; |
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. |
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; |
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 | |
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 | |
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 | |
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: |
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 | |
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: |
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 | |
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: |
180 | ObjCCategoryRecord(StringRef ClassToExtend, StringRef Name) |
181 | : ObjCContainerRecord(Name, RecordLinkage::Unknown), |
182 | ClassToExtend(ClassToExtend) {} |
183 | |
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: |
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 | |
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(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 | |