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 a list of linkage types.
31 enum class RecordLinkage : uint8_t {
32   // Unknown linkage.
33   Unknown = 0,
34 
35   // Local, hidden or private extern linkage.
36   Internal = 1,
37 
38   // Undefined linkage, it represents usage of external interface.
39   Undefined = 2,
40 
41   // Re-exported linkage, record is defined in external interface.
42   Rexported = 3,
43 
44   // Exported linkage.
45   Exported = 4,
46 };
47 
48 /// Define Record. They represent API's in binaries that could be linkable
49 /// symbols.
50 class Record {
51 public:
52   Record() = default;
53   Record(StringRef Name, RecordLinkage Linkage, SymbolFlags Flags)
54       : Name(Name), Linkage(Linkage), Flags(mergeFlags(Flags, Linkage)) {}
55 
56   bool isWeakDefined() const {
57     return (Flags & SymbolFlags::WeakDefined) == SymbolFlags::WeakDefined;
58   }
59 
60   bool isWeakReferenced() const {
61     return (Flags & SymbolFlags::WeakReferenced) == SymbolFlags::WeakReferenced;
62   }
63 
64   bool isThreadLocalValue() const {
65     return (Flags & SymbolFlags::ThreadLocalValue) ==
66            SymbolFlags::ThreadLocalValue;
67   }
68 
69   bool isData() const {
70     return (Flags & SymbolFlags::Data) == SymbolFlags::Data;
71   }
72 
73   bool isText() const {
74     return (Flags & SymbolFlags::Text) == SymbolFlags::Text;
75   }
76 
77   bool isInternal() const { return Linkage == RecordLinkage::Internal; }
78   bool isUndefined() const { return Linkage == RecordLinkage::Undefined; }
79   bool isExported() const { return Linkage >= RecordLinkage::Rexported; }
80   bool isRexported() const { return Linkage == RecordLinkage::Rexported; }
81 
82   StringRef getName() const { return Name; }
83   SymbolFlags getFlags() const { return Flags; }
84 
85 private:
86   SymbolFlags mergeFlags(SymbolFlags Flags, RecordLinkage Linkage);
87 
88 protected:
89   StringRef Name;
90   RecordLinkage Linkage;
91   SymbolFlags Flags;
92 
93   friend class RecordsSlice;
94 };
95 
96 // Defines broadly non-objc records, categorized as variables or functions.
97 class GlobalRecord : public Record {
98 public:
99   enum class Kind : uint8_t {
100     Unknown = 0,
101     Variable = 1,
102     Function = 2,
103   };
104 
105   GlobalRecord(StringRef Name, RecordLinkage Linkage, SymbolFlags Flags,
106                Kind GV)
107       : Record({Name, Linkage, Flags}), GV(GV) {}
108 
109   bool isFunction() const { return GV == Kind::Function; }
110   bool isVariable() const { return GV == Kind::Variable; }
111   void setKind(const Kind &V) {
112     if (GV == Kind::Unknown)
113       GV = V;
114   }
115 
116 private:
117   Kind GV;
118 };
119 
120 // Define Objective-C instance variable records.
121 class ObjCIVarRecord : public Record {
122 public:
123   ObjCIVarRecord(StringRef Name, RecordLinkage Linkage)
124       : Record({Name, Linkage, SymbolFlags::Data}) {}
125 
126   static std::string createScopedName(StringRef SuperClass, StringRef IVar) {
127     return (SuperClass + "." + IVar).str();
128   }
129 };
130 
131 template <typename V, typename K = StringRef,
132           typename std::enable_if<std::is_base_of<Record, V>::value>::type * =
133               nullptr>
134 using RecordMap = llvm::MapVector<K, std::unique_ptr<V>>;
135 
136 // Defines Objective-C record types that have assigned methods, properties,
137 // instance variable (ivars) and protocols.
138 class ObjCContainerRecord : public Record {
139 public:
140   ObjCContainerRecord(StringRef Name, RecordLinkage Linkage)
141       : Record({Name, Linkage, SymbolFlags::Data}) {}
142 
143   ObjCIVarRecord *addObjCIVar(StringRef IVar, RecordLinkage Linkage);
144   ObjCIVarRecord *findObjCIVar(StringRef IVar) const;
145   std::vector<ObjCIVarRecord *> getObjCIVars() const;
146 
147 private:
148   RecordMap<ObjCIVarRecord> IVars;
149 };
150 
151 // Define Objective-C category types. They don't generate linkable symbols, but
152 // they have assigned ivars that do.
153 class ObjCCategoryRecord : public ObjCContainerRecord {
154 public:
155   ObjCCategoryRecord(StringRef ClassToExtend, StringRef Name)
156       : ObjCContainerRecord(Name, RecordLinkage::Unknown),
157         ClassToExtend(ClassToExtend) {}
158 
159 private:
160   StringRef ClassToExtend;
161 };
162 
163 // Define Objective-C Interfaces or class types.
164 class ObjCInterfaceRecord : public ObjCContainerRecord {
165 public:
166   ObjCInterfaceRecord(StringRef Name, RecordLinkage Linkage,
167                       bool HasEHType = false)
168       : ObjCContainerRecord(Name, Linkage), HasEHType(HasEHType) {}
169 
170   bool hasExceptionAttribute() const { return HasEHType; }
171   bool addObjCCategory(ObjCCategoryRecord *Record);
172   std::vector<ObjCCategoryRecord *> getObjCCategories() const;
173 
174 private:
175   bool HasEHType;
176   // Non-owning containers of categories that extend the class.
177   llvm::MapVector<StringRef, ObjCCategoryRecord *> Categories;
178 };
179 
180 } // end namespace MachO.
181 } // end namespace llvm.
182 
183 #endif // LLVM_TEXTAPI_RECORD_H
184