xref: /llvm-project/llvm/include/llvm/TextAPI/Record.h (revision a4de589d117a4fd52554da3c61ae6eb26c90a0c8)
1b04b8975SCyndy Ishida //===- llvm/TextAPI/Record.h - TAPI Record ----------------------*- C++ -*-===//
2b04b8975SCyndy Ishida //
3b04b8975SCyndy Ishida // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4b04b8975SCyndy Ishida // See https://llvm.org/LICENSE.txt for license information.
5b04b8975SCyndy Ishida // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6b04b8975SCyndy Ishida //
7b04b8975SCyndy Ishida //===----------------------------------------------------------------------===//
8b04b8975SCyndy Ishida ///
9b04b8975SCyndy Ishida /// \file
10b04b8975SCyndy Ishida /// \brief Implements the TAPI Record Types.
11b04b8975SCyndy Ishida ///
12b04b8975SCyndy Ishida //===----------------------------------------------------------------------===//
13b04b8975SCyndy Ishida 
14b04b8975SCyndy Ishida #ifndef LLVM_TEXTAPI_RECORD_H
15b04b8975SCyndy Ishida #define LLVM_TEXTAPI_RECORD_H
16b04b8975SCyndy Ishida 
175ea15fabSCyndy Ishida #include "llvm/ADT/MapVector.h"
18b04b8975SCyndy Ishida #include "llvm/ADT/StringRef.h"
19b04b8975SCyndy Ishida #include "llvm/Support/Casting.h"
20b04b8975SCyndy Ishida #include "llvm/TextAPI/Symbol.h"
21b04b8975SCyndy Ishida #include <string>
22b04b8975SCyndy Ishida 
23b04b8975SCyndy Ishida namespace llvm {
24b04b8975SCyndy Ishida namespace MachO {
25b04b8975SCyndy Ishida 
26b04b8975SCyndy Ishida LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
27b04b8975SCyndy Ishida 
28b04b8975SCyndy Ishida class RecordsSlice;
29b04b8975SCyndy Ishida 
30*a4de589dSCyndy Ishida // Defines lightweight source location for records.
31*a4de589dSCyndy Ishida struct RecordLoc {
32*a4de589dSCyndy Ishida   RecordLoc() = default;
RecordLocRecordLoc33*a4de589dSCyndy Ishida   RecordLoc(std::string File, unsigned Line)
34*a4de589dSCyndy Ishida       : File(std::move(File)), Line(Line) {}
35*a4de589dSCyndy Ishida 
36*a4de589dSCyndy Ishida   /// Whether there is source location tied to the RecordLoc object.
isValidRecordLoc37*a4de589dSCyndy Ishida   bool isValid() const { return !File.empty(); }
38*a4de589dSCyndy Ishida 
39*a4de589dSCyndy Ishida   bool operator==(const RecordLoc &O) const {
40*a4de589dSCyndy Ishida     return std::tie(File, Line) == std::tie(O.File, O.Line);
41*a4de589dSCyndy Ishida   }
42*a4de589dSCyndy Ishida 
43*a4de589dSCyndy Ishida   const std::string File;
44*a4de589dSCyndy Ishida   const unsigned Line = 0;
45*a4de589dSCyndy Ishida };
46*a4de589dSCyndy Ishida 
47b04b8975SCyndy Ishida // Defines a list of linkage types.
48b04b8975SCyndy Ishida enum class RecordLinkage : uint8_t {
49b04b8975SCyndy Ishida   // Unknown linkage.
50b04b8975SCyndy Ishida   Unknown = 0,
51b04b8975SCyndy Ishida 
52b04b8975SCyndy Ishida   // Local, hidden or private extern linkage.
53b04b8975SCyndy Ishida   Internal = 1,
54b04b8975SCyndy Ishida 
55b04b8975SCyndy Ishida   // Undefined linkage, it represents usage of external interface.
56b04b8975SCyndy Ishida   Undefined = 2,
57b04b8975SCyndy Ishida 
58b04b8975SCyndy Ishida   // Re-exported linkage, record is defined in external interface.
59b04b8975SCyndy Ishida   Rexported = 3,
60b04b8975SCyndy Ishida 
61b04b8975SCyndy Ishida   // Exported linkage.
62b04b8975SCyndy Ishida   Exported = 4,
63b04b8975SCyndy Ishida };
64b04b8975SCyndy Ishida 
65b04b8975SCyndy Ishida /// Define Record. They represent API's in binaries that could be linkable
66b04b8975SCyndy Ishida /// symbols.
67b04b8975SCyndy Ishida class Record {
68b04b8975SCyndy Ishida public:
69b04b8975SCyndy Ishida   Record() = default;
Record(StringRef Name,RecordLinkage Linkage,SymbolFlags Flags)70b04b8975SCyndy Ishida   Record(StringRef Name, RecordLinkage Linkage, SymbolFlags Flags)
71f2794cceSCyndy Ishida       : Name(Name), Linkage(Linkage), Flags(mergeFlags(Flags, Linkage)),
72f2794cceSCyndy Ishida         Verified(false) {}
73b04b8975SCyndy Ishida 
isWeakDefined()74b04b8975SCyndy Ishida   bool isWeakDefined() const {
75b04b8975SCyndy Ishida     return (Flags & SymbolFlags::WeakDefined) == SymbolFlags::WeakDefined;
76b04b8975SCyndy Ishida   }
77b04b8975SCyndy Ishida 
isWeakReferenced()78b04b8975SCyndy Ishida   bool isWeakReferenced() const {
79b04b8975SCyndy Ishida     return (Flags & SymbolFlags::WeakReferenced) == SymbolFlags::WeakReferenced;
80b04b8975SCyndy Ishida   }
81b04b8975SCyndy Ishida 
isThreadLocalValue()82b04b8975SCyndy Ishida   bool isThreadLocalValue() const {
83b04b8975SCyndy Ishida     return (Flags & SymbolFlags::ThreadLocalValue) ==
84b04b8975SCyndy Ishida            SymbolFlags::ThreadLocalValue;
85b04b8975SCyndy Ishida   }
86b04b8975SCyndy Ishida 
isData()87b04b8975SCyndy Ishida   bool isData() const {
88b04b8975SCyndy Ishida     return (Flags & SymbolFlags::Data) == SymbolFlags::Data;
89b04b8975SCyndy Ishida   }
90b04b8975SCyndy Ishida 
isText()91b04b8975SCyndy Ishida   bool isText() const {
92b04b8975SCyndy Ishida     return (Flags & SymbolFlags::Text) == SymbolFlags::Text;
93b04b8975SCyndy Ishida   }
94b04b8975SCyndy Ishida 
isInternal()95b04b8975SCyndy Ishida   bool isInternal() const { return Linkage == RecordLinkage::Internal; }
isUndefined()96b04b8975SCyndy Ishida   bool isUndefined() const { return Linkage == RecordLinkage::Undefined; }
isExported()97b04b8975SCyndy Ishida   bool isExported() const { return Linkage >= RecordLinkage::Rexported; }
isRexported()98b04b8975SCyndy Ishida   bool isRexported() const { return Linkage == RecordLinkage::Rexported; }
99b04b8975SCyndy Ishida 
isVerified()100f2794cceSCyndy Ishida   bool isVerified() const { return Verified; }
101f2794cceSCyndy Ishida   void setVerify(bool V = true) { Verified = V; }
102f2794cceSCyndy Ishida 
getName()103b04b8975SCyndy Ishida   StringRef getName() const { return Name; }
getFlags()1045ea15fabSCyndy Ishida   SymbolFlags getFlags() const { return Flags; }
1055ea15fabSCyndy Ishida 
1065ea15fabSCyndy Ishida private:
1075ea15fabSCyndy Ishida   SymbolFlags mergeFlags(SymbolFlags Flags, RecordLinkage Linkage);
108b04b8975SCyndy Ishida 
109b04b8975SCyndy Ishida protected:
110b04b8975SCyndy Ishida   StringRef Name;
111b04b8975SCyndy Ishida   RecordLinkage Linkage;
112b04b8975SCyndy Ishida   SymbolFlags Flags;
113f2794cceSCyndy Ishida   bool Verified;
114b04b8975SCyndy Ishida 
115b04b8975SCyndy Ishida   friend class RecordsSlice;
116b04b8975SCyndy Ishida };
117b04b8975SCyndy Ishida 
118b04b8975SCyndy Ishida // Defines broadly non-objc records, categorized as variables or functions.
119b04b8975SCyndy Ishida class GlobalRecord : public Record {
120b04b8975SCyndy Ishida public:
121b04b8975SCyndy Ishida   enum class Kind : uint8_t {
122b04b8975SCyndy Ishida     Unknown = 0,
123b04b8975SCyndy Ishida     Variable = 1,
124b04b8975SCyndy Ishida     Function = 2,
125b04b8975SCyndy Ishida   };
126b04b8975SCyndy Ishida 
GlobalRecord(StringRef Name,RecordLinkage Linkage,SymbolFlags Flags,Kind GV,bool Inlined)127b04b8975SCyndy Ishida   GlobalRecord(StringRef Name, RecordLinkage Linkage, SymbolFlags Flags,
12850ae8a2aSCyndy Ishida                Kind GV, bool Inlined)
12950ae8a2aSCyndy Ishida       : Record({Name, Linkage, Flags}), GV(GV), Inlined(Inlined) {}
130b04b8975SCyndy Ishida 
isFunction()131b04b8975SCyndy Ishida   bool isFunction() const { return GV == Kind::Function; }
isVariable()132b04b8975SCyndy Ishida   bool isVariable() const { return GV == Kind::Variable; }
setKind(const Kind & V)133e3627e26SCyndy Ishida   void setKind(const Kind &V) {
134e3627e26SCyndy Ishida     if (GV == Kind::Unknown)
135e3627e26SCyndy Ishida       GV = V;
136e3627e26SCyndy Ishida   }
isInlined()13750ae8a2aSCyndy Ishida   bool isInlined() const { return Inlined; }
138b04b8975SCyndy Ishida 
139b04b8975SCyndy Ishida private:
140b04b8975SCyndy Ishida   Kind GV;
14150ae8a2aSCyndy Ishida   bool Inlined = false;
142b04b8975SCyndy Ishida };
143b04b8975SCyndy Ishida 
144b04b8975SCyndy Ishida // Define Objective-C instance variable records.
145b04b8975SCyndy Ishida class ObjCIVarRecord : public Record {
146b04b8975SCyndy Ishida public:
ObjCIVarRecord(StringRef Name,RecordLinkage Linkage)147b04b8975SCyndy Ishida   ObjCIVarRecord(StringRef Name, RecordLinkage Linkage)
148b04b8975SCyndy Ishida       : Record({Name, Linkage, SymbolFlags::Data}) {}
149b04b8975SCyndy Ishida 
createScopedName(StringRef SuperClass,StringRef IVar)150b04b8975SCyndy Ishida   static std::string createScopedName(StringRef SuperClass, StringRef IVar) {
151b04b8975SCyndy Ishida     return (SuperClass + "." + IVar).str();
152b04b8975SCyndy Ishida   }
153b04b8975SCyndy Ishida };
154b04b8975SCyndy Ishida 
155b04b8975SCyndy Ishida template <typename V, typename K = StringRef,
156b04b8975SCyndy Ishida           typename std::enable_if<std::is_base_of<Record, V>::value>::type * =
157b04b8975SCyndy Ishida               nullptr>
158b04b8975SCyndy Ishida using RecordMap = llvm::MapVector<K, std::unique_ptr<V>>;
159b04b8975SCyndy Ishida 
160b04b8975SCyndy Ishida // Defines Objective-C record types that have assigned methods, properties,
161b04b8975SCyndy Ishida // instance variable (ivars) and protocols.
162b04b8975SCyndy Ishida class ObjCContainerRecord : public Record {
163b04b8975SCyndy Ishida public:
ObjCContainerRecord(StringRef Name,RecordLinkage Linkage)164b04b8975SCyndy Ishida   ObjCContainerRecord(StringRef Name, RecordLinkage Linkage)
165b04b8975SCyndy Ishida       : Record({Name, Linkage, SymbolFlags::Data}) {}
166b04b8975SCyndy Ishida 
167b04b8975SCyndy Ishida   ObjCIVarRecord *addObjCIVar(StringRef IVar, RecordLinkage Linkage);
168b04b8975SCyndy Ishida   ObjCIVarRecord *findObjCIVar(StringRef IVar) const;
1695ea15fabSCyndy Ishida   std::vector<ObjCIVarRecord *> getObjCIVars() const;
getLinkage()17010ccde30SCyndy Ishida   RecordLinkage getLinkage() const { return Linkage; }
171b04b8975SCyndy Ishida 
172b04b8975SCyndy Ishida private:
173b04b8975SCyndy Ishida   RecordMap<ObjCIVarRecord> IVars;
174b04b8975SCyndy Ishida };
175b04b8975SCyndy Ishida 
176b04b8975SCyndy Ishida // Define Objective-C category types. They don't generate linkable symbols, but
177b04b8975SCyndy Ishida // they have assigned ivars that do.
178b04b8975SCyndy Ishida class ObjCCategoryRecord : public ObjCContainerRecord {
179b04b8975SCyndy Ishida public:
ObjCCategoryRecord(StringRef ClassToExtend,StringRef Name)180b04b8975SCyndy Ishida   ObjCCategoryRecord(StringRef ClassToExtend, StringRef Name)
181b04b8975SCyndy Ishida       : ObjCContainerRecord(Name, RecordLinkage::Unknown),
182b04b8975SCyndy Ishida         ClassToExtend(ClassToExtend) {}
183b04b8975SCyndy Ishida 
getSuperClassName()184346766eaSCyndy Ishida   StringRef getSuperClassName() const { return ClassToExtend; }
185346766eaSCyndy Ishida 
186b04b8975SCyndy Ishida private:
187b04b8975SCyndy Ishida   StringRef ClassToExtend;
188b04b8975SCyndy Ishida };
189b04b8975SCyndy Ishida 
190b04b8975SCyndy Ishida // Define Objective-C Interfaces or class types.
191b04b8975SCyndy Ishida class ObjCInterfaceRecord : public ObjCContainerRecord {
192b04b8975SCyndy Ishida public:
ObjCInterfaceRecord(StringRef Name,RecordLinkage Linkage,ObjCIFSymbolKind SymType)193b04b8975SCyndy Ishida   ObjCInterfaceRecord(StringRef Name, RecordLinkage Linkage,
1944460fa88SCyndy Ishida                       ObjCIFSymbolKind SymType)
1954460fa88SCyndy Ishida       : ObjCContainerRecord(Name, Linkage) {
1964460fa88SCyndy Ishida     updateLinkageForSymbols(SymType, Linkage);
1974460fa88SCyndy Ishida   }
198b04b8975SCyndy Ishida 
hasExceptionAttribute()1994460fa88SCyndy Ishida   bool hasExceptionAttribute() const {
2004460fa88SCyndy Ishida     return Linkages.EHType != RecordLinkage::Unknown;
2014460fa88SCyndy Ishida   }
isCompleteInterface()2024460fa88SCyndy Ishida   bool isCompleteInterface() const {
2034460fa88SCyndy Ishida     return Linkages.Class >= RecordLinkage::Rexported &&
2044460fa88SCyndy Ishida            Linkages.MetaClass >= RecordLinkage::Rexported;
2054460fa88SCyndy Ishida   }
isExportedSymbol(ObjCIFSymbolKind CurrType)2064460fa88SCyndy Ishida   bool isExportedSymbol(ObjCIFSymbolKind CurrType) const {
2074460fa88SCyndy Ishida     return getLinkageForSymbol(CurrType) >= RecordLinkage::Rexported;
2084460fa88SCyndy Ishida   }
2094460fa88SCyndy Ishida 
2104460fa88SCyndy Ishida   RecordLinkage getLinkageForSymbol(ObjCIFSymbolKind CurrType) const;
2114460fa88SCyndy Ishida   void updateLinkageForSymbols(ObjCIFSymbolKind SymType, RecordLinkage Link);
2124460fa88SCyndy Ishida 
213b04b8975SCyndy Ishida   bool addObjCCategory(ObjCCategoryRecord *Record);
2145ea15fabSCyndy Ishida   std::vector<ObjCCategoryRecord *> getObjCCategories() const;
215b04b8975SCyndy Ishida 
216b04b8975SCyndy Ishida private:
2174460fa88SCyndy Ishida   /// Linkage level for each symbol represented in ObjCInterfaceRecord.
2184460fa88SCyndy Ishida   struct Linkages {
2194460fa88SCyndy Ishida     RecordLinkage Class = RecordLinkage::Unknown;
2204460fa88SCyndy Ishida     RecordLinkage MetaClass = RecordLinkage::Unknown;
2214460fa88SCyndy Ishida     RecordLinkage EHType = RecordLinkage::Unknown;
2224460fa88SCyndy Ishida     bool operator==(const Linkages &other) const {
2234460fa88SCyndy Ishida       return std::tie(Class, MetaClass, EHType) ==
2244460fa88SCyndy Ishida              std::tie(other.Class, other.MetaClass, other.EHType);
2254460fa88SCyndy Ishida     }
2264460fa88SCyndy Ishida     bool operator!=(const Linkages &other) const { return !(*this == other); }
2274460fa88SCyndy Ishida   };
2284460fa88SCyndy Ishida   Linkages Linkages;
2294460fa88SCyndy Ishida 
230b04b8975SCyndy Ishida   // Non-owning containers of categories that extend the class.
231b04b8975SCyndy Ishida   llvm::MapVector<StringRef, ObjCCategoryRecord *> Categories;
232b04b8975SCyndy Ishida };
233b04b8975SCyndy Ishida 
234b04b8975SCyndy Ishida } // end namespace MachO.
235b04b8975SCyndy Ishida } // end namespace llvm.
236b04b8975SCyndy Ishida 
237b04b8975SCyndy Ishida #endif // LLVM_TEXTAPI_RECORD_H
238