Skip to content

Commit b04b897

Browse files
authored
[TextAPI] Introduce Records & RecordSlice Types (llvm#74115)
`Record`'s hold target triple specific information about APIs and symbols. This holds information about the relationship between ObjC symbols and their linkage properties. It will be used to compare and run significant operations between the frontend representation of symbols in AST and symbol information extracted from Mach-O binaries. This differs from the lighter weight Symbol and SymbolSet class where they are deduplicated across targets and only represent exported symbols, that class is mostly used for serializing.
1 parent bb6497f commit b04b897

File tree

8 files changed

+741
-0
lines changed

8 files changed

+741
-0
lines changed

llvm/include/llvm/TextAPI/Record.h

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
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/StringRef.h"
18+
#include "llvm/Support/Casting.h"
19+
#include "llvm/TextAPI/Symbol.h"
20+
#include <string>
21+
22+
namespace llvm {
23+
namespace MachO {
24+
25+
LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
26+
27+
class RecordsSlice;
28+
29+
// Defines a list of linkage types.
30+
enum class RecordLinkage : uint8_t {
31+
// Unknown linkage.
32+
Unknown = 0,
33+
34+
// Local, hidden or private extern linkage.
35+
Internal = 1,
36+
37+
// Undefined linkage, it represents usage of external interface.
38+
Undefined = 2,
39+
40+
// Re-exported linkage, record is defined in external interface.
41+
Rexported = 3,
42+
43+
// Exported linkage.
44+
Exported = 4,
45+
};
46+
47+
/// Define Record. They represent API's in binaries that could be linkable
48+
/// symbols.
49+
class Record {
50+
public:
51+
Record() = default;
52+
Record(StringRef Name, RecordLinkage Linkage, SymbolFlags Flags)
53+
: Name(Name), Linkage(Linkage), Flags(Flags) {}
54+
55+
bool isWeakDefined() const {
56+
return (Flags & SymbolFlags::WeakDefined) == SymbolFlags::WeakDefined;
57+
}
58+
59+
bool isWeakReferenced() const {
60+
return (Flags & SymbolFlags::WeakReferenced) == SymbolFlags::WeakReferenced;
61+
}
62+
63+
bool isThreadLocalValue() const {
64+
return (Flags & SymbolFlags::ThreadLocalValue) ==
65+
SymbolFlags::ThreadLocalValue;
66+
}
67+
68+
bool isData() const {
69+
return (Flags & SymbolFlags::Data) == SymbolFlags::Data;
70+
}
71+
72+
bool isText() const {
73+
return (Flags & SymbolFlags::Text) == SymbolFlags::Text;
74+
}
75+
76+
bool isInternal() const { return Linkage == RecordLinkage::Internal; }
77+
bool isUndefined() const { return Linkage == RecordLinkage::Undefined; }
78+
bool isExported() const { return Linkage >= RecordLinkage::Rexported; }
79+
bool isRexported() const { return Linkage == RecordLinkage::Rexported; }
80+
81+
StringRef getName() const { return Name; }
82+
83+
protected:
84+
StringRef Name;
85+
RecordLinkage Linkage;
86+
SymbolFlags Flags;
87+
88+
friend class RecordsSlice;
89+
};
90+
91+
// Defines broadly non-objc records, categorized as variables or functions.
92+
class GlobalRecord : public Record {
93+
public:
94+
enum class Kind : uint8_t {
95+
Unknown = 0,
96+
Variable = 1,
97+
Function = 2,
98+
};
99+
100+
GlobalRecord(StringRef Name, RecordLinkage Linkage, SymbolFlags Flags,
101+
Kind GV)
102+
: Record({Name, Linkage, Flags}), GV(GV) {}
103+
104+
bool isFunction() const { return GV == Kind::Function; }
105+
bool isVariable() const { return GV == Kind::Variable; }
106+
107+
private:
108+
Kind GV;
109+
};
110+
111+
// Define Objective-C instance variable records.
112+
class ObjCIVarRecord : public Record {
113+
public:
114+
ObjCIVarRecord(StringRef Name, RecordLinkage Linkage)
115+
: Record({Name, Linkage, SymbolFlags::Data}) {}
116+
117+
static std::string createScopedName(StringRef SuperClass, StringRef IVar) {
118+
return (SuperClass + "." + IVar).str();
119+
}
120+
};
121+
122+
template <typename V, typename K = StringRef,
123+
typename std::enable_if<std::is_base_of<Record, V>::value>::type * =
124+
nullptr>
125+
using RecordMap = llvm::MapVector<K, std::unique_ptr<V>>;
126+
127+
// Defines Objective-C record types that have assigned methods, properties,
128+
// instance variable (ivars) and protocols.
129+
class ObjCContainerRecord : public Record {
130+
public:
131+
ObjCContainerRecord(StringRef Name, RecordLinkage Linkage)
132+
: Record({Name, Linkage, SymbolFlags::Data}) {}
133+
134+
ObjCIVarRecord *addObjCIVar(StringRef IVar, RecordLinkage Linkage);
135+
ObjCIVarRecord *findObjCIVar(StringRef IVar) const;
136+
137+
private:
138+
RecordMap<ObjCIVarRecord> IVars;
139+
};
140+
141+
// Define Objective-C category types. They don't generate linkable symbols, but
142+
// they have assigned ivars that do.
143+
class ObjCCategoryRecord : public ObjCContainerRecord {
144+
public:
145+
ObjCCategoryRecord(StringRef ClassToExtend, StringRef Name)
146+
: ObjCContainerRecord(Name, RecordLinkage::Unknown),
147+
ClassToExtend(ClassToExtend) {}
148+
149+
private:
150+
StringRef ClassToExtend;
151+
};
152+
153+
// Define Objective-C Interfaces or class types.
154+
class ObjCInterfaceRecord : public ObjCContainerRecord {
155+
public:
156+
ObjCInterfaceRecord(StringRef Name, RecordLinkage Linkage,
157+
bool HasEHType = false)
158+
: ObjCContainerRecord(Name, Linkage), HasEHType(HasEHType) {}
159+
160+
bool hasExceptionAttribute() const { return HasEHType; }
161+
bool addObjCCategory(ObjCCategoryRecord *Record);
162+
163+
private:
164+
bool HasEHType;
165+
// Non-owning containers of categories that extend the class.
166+
llvm::MapVector<StringRef, ObjCCategoryRecord *> Categories;
167+
};
168+
169+
} // end namespace MachO.
170+
} // end namespace llvm.
171+
172+
#endif // LLVM_TEXTAPI_RECORD_H
Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
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/ADT/MapVector.h"
18+
#include "llvm/Support/Allocator.h"
19+
#include "llvm/TextAPI/InterfaceFile.h"
20+
#include "llvm/TextAPI/PackedVersion.h"
21+
#include "llvm/TextAPI/Record.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:
30+
RecordsSlice(const llvm::Triple &T) : TargetTriple(T), Target(T) {}
31+
/// Get target triple.
32+
const llvm::Triple &getTriple() const { return TargetTriple; }
33+
/// Get TAPI converted target.
34+
const Target &getTarget() const { return Target; }
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.
128+
bool hasBinaryAttrs() const { return BA.get(); }
129+
130+
// Determine if record slice is unassigned.
131+
bool isEmpty() const {
132+
return !hasBinaryAttrs() && Globals.empty() && Classes.empty() &&
133+
Categories.empty();
134+
}
135+
136+
struct BinaryAttrs {
137+
std::vector<StringRef> AllowableClients;
138+
std::vector<StringRef> RexportedLibraries;
139+
std::vector<StringRef> RPaths;
140+
StringRef ParentUmbrella;
141+
StringRef InstallName;
142+
StringRef UUID;
143+
StringRef Path;
144+
FileType fileType = FileType::Invalid;
145+
llvm::MachO::PackedVersion CurrentVersion;
146+
llvm::MachO::PackedVersion CompatVersion;
147+
uint8_t SwiftABI = 0;
148+
bool TwoLevelNamespace = false;
149+
bool AppExtensionSafe = false;
150+
bool OSLibNotForSharedCache = false;
151+
};
152+
153+
/// Return reference to BinaryAttrs.
154+
BinaryAttrs &getBinaryAttrs();
155+
156+
private:
157+
const llvm::Triple TargetTriple;
158+
// Hold tapi converted triple to avoid unecessary casts.
159+
const Target Target;
160+
161+
/// BumpPtrAllocator to store generated/copied strings.
162+
llvm::BumpPtrAllocator StringAllocator;
163+
StringRef copyString(StringRef String);
164+
165+
/// Promote linkage of requested record. It is no-op if linkage type is lower
166+
/// than the current assignment.
167+
///
168+
/// \param R The record to update.
169+
/// \param L Linkage type to update to.
170+
void updateLinkage(Record *R, RecordLinkage L) {
171+
R->Linkage = std::max(R->Linkage, L);
172+
}
173+
174+
RecordMap<GlobalRecord> Globals;
175+
RecordMap<ObjCInterfaceRecord> Classes;
176+
RecordMap<ObjCCategoryRecord, std::pair<StringRef, StringRef>> Categories;
177+
178+
std::unique_ptr<BinaryAttrs> BA{nullptr};
179+
};
180+
181+
} // namespace MachO
182+
} // namespace llvm
183+
#endif // LLVM_TEXTAPI_RECORDSLICE_H

llvm/include/llvm/TextAPI/Symbol.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,23 @@ class Symbol {
160160
SymbolFlags Flags;
161161
};
162162

163+
/// Lightweight struct for passing around symbol information.
164+
struct SimpleSymbol {
165+
StringRef Name;
166+
SymbolKind Kind;
167+
168+
bool operator<(const SimpleSymbol &O) const {
169+
return std::tie(Name, Kind) < std::tie(O.Name, O.Kind);
170+
}
171+
};
172+
173+
/// Determine SymbolKind from Flags and parsing Name.
174+
///
175+
/// \param Name The name of symbol.
176+
/// \param Flags The flags pre-determined for the symbol.
177+
SimpleSymbol parseSymbol(StringRef SymName,
178+
const SymbolFlags Flags = SymbolFlags::None);
179+
163180
} // end namespace MachO.
164181
} // end namespace llvm.
165182

llvm/lib/TextAPI/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ add_llvm_component_library(LLVMTextAPI
55
TextStubV5.cpp
66
PackedVersion.cpp
77
Platform.cpp
8+
RecordsSlice.cpp
89
Symbol.cpp
910
SymbolSet.cpp
1011
Target.cpp

0 commit comments

Comments
 (0)