1 //===- llvm/TextAPI/RecordSlice.h - TAPI RecordSlice ------------*- 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 Collection Type.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_TEXTAPI_RECORDSLICE_H
15 #define LLVM_TEXTAPI_RECORDSLICE_H
16 
17 #include "llvm/Support/Allocator.h"
18 #include "llvm/TextAPI/InterfaceFile.h"
19 #include "llvm/TextAPI/PackedVersion.h"
20 #include "llvm/TextAPI/Record.h"
21 #include "llvm/TextAPI/RecordVisitor.h"
22 
23 namespace llvm {
24 namespace MachO {
25 
26 // Define collection of records for a library that are tied to a darwin target
27 // triple.
28 class RecordsSlice {
29 public:
RecordsSlice(const llvm::Triple & T)30   RecordsSlice(const llvm::Triple &T) : TargetTriple(T), TAPITarget(T) {}
31   /// Get target triple.
getTriple()32   const llvm::Triple &getTriple() const { return TargetTriple; }
33   /// Get TAPI converted target.
getTarget()34   const Target &getTarget() const { return TAPITarget; }
35 
36   /// Add unspecified record to slice.
37   ///
38   /// Assign specific record type based on properties and symbol name.
39   ///
40   /// \param Name The name of symbol.
41   /// \param Flags The flags that describe attributes of the symbol.
42   /// \param GV The kind of global, if this represents a non obj-c global
43   /// symbol.
44   /// \param Linkage The linkage of symbol.
45   /// \return The non-owning pointer to added record in slice.
46   Record *addRecord(StringRef Name, SymbolFlags Flags,
47                     GlobalRecord::Kind GV = GlobalRecord::Kind::Unknown,
48                     RecordLinkage Linkage = RecordLinkage::Unknown);
49 
50   /// Add non-ObjC global record.
51   ///
52   /// \param Name The name of symbol.
53   /// \param Flags The flags that describe attributes of the symbol.
54   /// \param GV The kind of global.
55   /// \param Linkage The linkage of symbol.
56   /// \return The non-owning pointer to added record in slice.
57   GlobalRecord *addGlobal(StringRef Name, RecordLinkage Linkage,
58                           GlobalRecord::Kind GV,
59                           SymbolFlags Flags = SymbolFlags::None);
60 
61   /// Add ObjC Class record.
62   ///
63   /// \param Name The name of class, not symbol.
64   /// \param Linkage The linkage of symbol.
65   /// \param HasEHType Whether symbol represents an eh_type.
66   /// \return The non-owning pointer to added record in slice.
67   ObjCInterfaceRecord *addObjCInterface(StringRef Name, RecordLinkage Linkage,
68                                         bool HasEHType = false);
69 
70   /// Add ObjC IVar record.
71   ///
72   /// \param Name The name of ivar, not symbol.
73   /// \param Linkage The linkage of symbol.
74   /// \return The non-owning pointer to added record in slice.
75   ObjCIVarRecord *addObjCIVar(ObjCContainerRecord *Container, StringRef Name,
76                               RecordLinkage Linkage);
77 
78   /// Add ObjC Category record.
79   ///
80   /// \param ClassToExtend The name of class that is being extended by the
81   /// category, not symbol.
82   /// \param Category The name of category.
83   /// \return The non-owning pointer to added record in slice.
84   ObjCCategoryRecord *addObjCCategory(StringRef ClassToExtend,
85                                       StringRef Category);
86 
87   /// Find ObjC Class.
88   ///
89   /// \param Name name of class, not full symbol name.
90   /// \return The non-owning pointer to record in slice.
91   ObjCInterfaceRecord *findObjCInterface(StringRef Name) const;
92 
93   /// Find ObjC Category.
94   ///
95   /// \param ClassToExtend The name of class, not full symbol name.
96   /// \param Categories The name of category.
97   /// \return The non-owning pointer to record in slice.
98   ObjCCategoryRecord *findObjCCategory(StringRef ClassToExtend,
99                                        StringRef Category) const;
100 
101   /// Find ObjC Container. This is commonly used for assigning for looking up
102   /// instance variables that are assigned to either a category or class.
103   ///
104   /// \param IsIVar If true, the name is the name of the IVar, otherwise it will
105   /// be looked up as the name of the container.
106   /// \param Name Either the name of ivar or name of container.
107   /// \return The non-owning pointer to record in
108   /// slice.
109   ObjCContainerRecord *findContainer(bool IsIVar, StringRef Name) const;
110 
111   /// Find ObjC instance variable.
112   ///
113   /// \param IsScopedName This is used to determine how to parse the name.
114   /// \param Name Either the full name of the symbol or just the ivar.
115   /// \return The non-owning pointer to record in slice.
116   ObjCIVarRecord *findObjCIVar(bool IsScopedName, StringRef Name) const;
117 
118   /// Find non-objc global.
119   ///
120   /// \param Name The name of symbol.
121   /// \param GV The Kind of global to find.
122   /// \return The non-owning pointer to record in slice.
123   GlobalRecord *
124   findGlobal(StringRef Name,
125              GlobalRecord::Kind GV = GlobalRecord::Kind::Unknown) const;
126 
127   // Determine if library attributes were assigned.
hasBinaryAttrs()128   bool hasBinaryAttrs() const { return BA.get(); }
129 
130   // Determine if record slice is unassigned.
empty()131   bool empty() const {
132     return !hasBinaryAttrs() && Globals.empty() && Classes.empty() &&
133            Categories.empty();
134   }
135 
136   // Visit all records known to RecordsSlice.
137   void visit(RecordVisitor &V) const;
138 
139   struct BinaryAttrs {
140     std::vector<StringRef> AllowableClients;
141     std::vector<StringRef> RexportedLibraries;
142     std::vector<StringRef> RPaths;
143     StringRef ParentUmbrella;
144     StringRef InstallName;
145     StringRef UUID;
146     StringRef Path;
147     FileType File = FileType::Invalid;
148     llvm::MachO::PackedVersion CurrentVersion;
149     llvm::MachO::PackedVersion CompatVersion;
150     uint8_t SwiftABI = 0;
151     bool TwoLevelNamespace = false;
152     bool AppExtensionSafe = false;
153     bool OSLibNotForSharedCache = false;
154   };
155 
156   /// Return reference to BinaryAttrs.
157   BinaryAttrs &getBinaryAttrs();
158 
159   /// Store any strings owned by RecordSlice into allocator and return back
160   /// reference to that.
161   StringRef copyString(StringRef String);
162 
163 private:
164   const llvm::Triple TargetTriple;
165   // Hold tapi converted triple to avoid unecessary casts.
166   const Target TAPITarget;
167 
168   /// BumpPtrAllocator to store generated/copied strings.
169   llvm::BumpPtrAllocator StringAllocator;
170 
171   /// Promote linkage of requested record. It is no-op if linkage type is lower
172   /// than the current assignment.
173   ///
174   /// \param R The record to update.
175   /// \param L Linkage type to update to.
updateLinkage(Record * R,RecordLinkage L)176   void updateLinkage(Record *R, RecordLinkage L) {
177     R->Linkage = std::max(R->Linkage, L);
178   }
179 
180   /// Update set flags of requested record.
181   ///
182   /// \param R The global record to update.
183   /// \param F Flags to update to.
updateFlags(GlobalRecord * R,SymbolFlags F)184   void updateFlags(GlobalRecord *R, SymbolFlags F) { R->Flags = F; }
185 
186   RecordMap<GlobalRecord> Globals;
187   RecordMap<ObjCInterfaceRecord> Classes;
188   RecordMap<ObjCCategoryRecord, std::pair<StringRef, StringRef>> Categories;
189 
190   std::unique_ptr<BinaryAttrs> BA{nullptr};
191 };
192 
193 using Records = llvm::SmallVector<std::shared_ptr<RecordsSlice>, 4>;
194 std::unique_ptr<InterfaceFile> convertToInterfaceFile(const Records &Slices);
195 
196 } // namespace MachO
197 } // namespace llvm
198 #endif // LLVM_TEXTAPI_RECORDSLICE_H
199