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 a list of linkage types.
31enum 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.
50class Record {
51public:
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
85private:
86  SymbolFlags mergeFlags(SymbolFlags Flags, RecordLinkage Linkage);
87
88protected:
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.
97class GlobalRecord : public Record {
98public:
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
116private:
117  Kind GV;
118};
119
120// Define Objective-C instance variable records.
121class ObjCIVarRecord : public Record {
122public:
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
131template <typename V, typename K = StringRef,
132          typename std::enable_if<std::is_base_of<Record, V>::value>::type * =
133              nullptr>
134using 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.
138class ObjCContainerRecord : public Record {
139public:
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
147private:
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.
153class ObjCCategoryRecord : public ObjCContainerRecord {
154public:
155  ObjCCategoryRecord(StringRef ClassToExtend, StringRef Name)
156      : ObjCContainerRecord(Name, RecordLinkage::Unknown),
157        ClassToExtend(ClassToExtend) {}
158
159private:
160  StringRef ClassToExtend;
161};
162
163// Define Objective-C Interfaces or class types.
164class ObjCInterfaceRecord : public ObjCContainerRecord {
165public:
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
174private:
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