Skip to content

Commit f24f445

Browse files
committed
Merge pull request #2274 from apple/closure-metadata
Start emitting capture descriptors for closure metadata
2 parents 7062f21 + e4d71eb commit f24f445

22 files changed

+1430
-492
lines changed

include/swift/Reflection/MetadataSource.h

Lines changed: 261 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#ifndef SWIFT_REFLECTION_METADATASOURCE_H
2323
#define SWIFT_REFLECTION_METADATASOURCE_H
2424

25+
#include "llvm/ADT/Optional.h"
2526
#include "llvm/Support/Casting.h"
2627

2728
using llvm::cast;
@@ -39,6 +40,156 @@ enum class MetadataSourceKind {
3940

4041
class MetadataSource {
4142
MetadataSourceKind Kind;
43+
44+
static bool decodeNatural(std::string::const_iterator &it,
45+
const std::string::const_iterator &end,
46+
unsigned &result) {
47+
auto begin = it;
48+
while (it != end) {
49+
if (*it >= '0' && *it <= '9')
50+
++it;
51+
else
52+
break;
53+
}
54+
55+
std::string natural(begin, it);
56+
if (natural.empty())
57+
return false;
58+
59+
result = std::stoi(natural);
60+
return true;
61+
}
62+
63+
template <typename Allocator>
64+
static const MetadataSource *
65+
decodeClosureBinding(Allocator &A,
66+
std::string::const_iterator &it,
67+
const std::string::const_iterator &end) {
68+
if (it == end)
69+
return nullptr;
70+
71+
if (*it == 'B')
72+
++it;
73+
else
74+
return nullptr;
75+
76+
unsigned Index;
77+
if (!decodeNatural(it, end, Index))
78+
return nullptr;
79+
return A.template createClosureBinding(Index);
80+
}
81+
82+
template <typename Allocator>
83+
static const MetadataSource *
84+
decodeReferenceCapture(Allocator &A,
85+
std::string::const_iterator &it,
86+
const std::string::const_iterator &end) {
87+
if (it == end)
88+
return nullptr;
89+
90+
if (*it == 'R')
91+
++it;
92+
else
93+
return nullptr;
94+
95+
unsigned Index;
96+
if (!decodeNatural(it, end, Index))
97+
return nullptr;
98+
return A.template createReferenceCapture(Index);
99+
}
100+
101+
template <typename Allocator>
102+
static const MetadataSource *
103+
decodeMetadataCapture(Allocator &A,
104+
std::string::const_iterator &it,
105+
const std::string::const_iterator &end) {
106+
if (it == end)
107+
return nullptr;
108+
109+
if (*it == 'M')
110+
++it;
111+
else
112+
return nullptr;
113+
114+
unsigned Index;
115+
if (!decodeNatural(it, end, Index))
116+
return nullptr;
117+
return A.template createMetadataCapture(Index);
118+
}
119+
120+
template <typename Allocator>
121+
static const MetadataSource *
122+
decodeGenericArgument(Allocator &A,
123+
std::string::const_iterator &it,
124+
const std::string::const_iterator &end) {
125+
if (it == end)
126+
return nullptr;
127+
128+
if (*it == 'G')
129+
++it;
130+
else
131+
return nullptr;
132+
133+
unsigned Index;
134+
if (!decodeNatural(it, end, Index))
135+
return nullptr;
136+
137+
auto Source = decode(A, it, end);
138+
if (!Source)
139+
return nullptr;
140+
141+
if (it == end || *it != '_')
142+
return nullptr;
143+
144+
++it;
145+
146+
return A.template createGenericArgument(Index, Source);
147+
}
148+
149+
template <typename Allocator>
150+
static const MetadataSource*
151+
decodeParent(Allocator &A,
152+
std::string::const_iterator &it,
153+
const std::string::const_iterator &end) {
154+
if (it == end || *it != 'P')
155+
return nullptr;
156+
157+
++it;
158+
auto Child = decode(A, it, end);
159+
if (!Child)
160+
return nullptr;
161+
162+
if (it == end || *it != '_')
163+
return nullptr;
164+
165+
return A.template createParent(Child);
166+
}
167+
168+
template <typename Allocator>
169+
static const MetadataSource *decode(Allocator &A,
170+
std::string::const_iterator &it,
171+
const std::string::const_iterator &end) {
172+
if (it == end) return nullptr;
173+
174+
switch (*it) {
175+
case 'B':
176+
return decodeClosureBinding(A, it, end);
177+
case 'R':
178+
return decodeReferenceCapture(A, it, end);
179+
case 'M':
180+
return decodeMetadataCapture(A, it, end);
181+
case 'G':
182+
return decodeGenericArgument(A, it, end);
183+
case 'P':
184+
return decodeParent(A, it, end);
185+
case 'S':
186+
++it;
187+
return A.template createSelf();
188+
default:
189+
return nullptr;
190+
}
191+
}
192+
42193
public:
43194
MetadataSource(MetadataSourceKind Kind) : Kind(Kind) {}
44195

@@ -48,6 +199,11 @@ class MetadataSource {
48199

49200
void dump() const;
50201
void dump(std::ostream &OS, unsigned Indent = 0) const;
202+
template <typename Allocator>
203+
static const MetadataSource *decode(Allocator &A, const std::string &str) {
204+
auto begin = str.begin();
205+
return MetadataSource::decode<Allocator>(A, begin, str.end());
206+
}
51207

52208
virtual ~MetadataSource() = default;
53209
};
@@ -59,8 +215,15 @@ class ClosureBindingMetadataSource final : public MetadataSource {
59215
unsigned Index;
60216

61217
public:
62-
ClosureBindingMetadataSource(unsigned Index) :
63-
MetadataSource(MetadataSourceKind::ClosureBinding) {}
218+
219+
ClosureBindingMetadataSource(unsigned Index)
220+
: MetadataSource(MetadataSourceKind::ClosureBinding), Index(Index) {}
221+
222+
template <typename Allocator>
223+
static const ClosureBindingMetadataSource *
224+
create(Allocator &A, unsigned Index) {
225+
return A.template make_source<ClosureBindingMetadataSource>(Index);
226+
}
64227

65228
unsigned getIndex() const {
66229
return Index;
@@ -75,9 +238,16 @@ class ClosureBindingMetadataSource final : public MetadataSource {
75238
/// be followed to the heap instance's data, then its metadata pointer.
76239
class ReferenceCaptureMetadataSource final : public MetadataSource {
77240
unsigned Index;
241+
78242
public:
79-
ReferenceCaptureMetadataSource(unsigned Index):
80-
MetadataSource(MetadataSourceKind::ReferenceCapture) {}
243+
ReferenceCaptureMetadataSource(unsigned Index)
244+
: MetadataSource(MetadataSourceKind::ReferenceCapture), Index(Index) {}
245+
246+
template <typename Allocator>
247+
static const ReferenceCaptureMetadataSource *
248+
create(Allocator &A, unsigned Index) {
249+
return A.template make_source<ReferenceCaptureMetadataSource>(Index);
250+
}
81251

82252
unsigned getIndex() const {
83253
return Index;
@@ -88,6 +258,29 @@ class ReferenceCaptureMetadataSource final : public MetadataSource {
88258
}
89259
};
90260

261+
/// Represents a capture of a metadata pointer as an argument to a polymorphic function. These are direct sources of metadata.
262+
class MetadataCaptureMetadataSource final : public MetadataSource {
263+
unsigned Index;
264+
265+
public:
266+
MetadataCaptureMetadataSource(unsigned Index)
267+
: MetadataSource(MetadataSourceKind::MetadataCapture), Index(Index) {}
268+
269+
template <typename Allocator>
270+
static const MetadataCaptureMetadataSource *
271+
create(Allocator &A, unsigned Index) {
272+
return A.template make_source<MetadataCaptureMetadataSource>(Index);
273+
}
274+
275+
unsigned getIndex() const {
276+
return Index;
277+
}
278+
279+
static bool classof(const MetadataSource *MS) {
280+
return MS->getKind() == MetadataSourceKind::MetadataCapture;
281+
}
282+
};
283+
91284
/// Represents the nth generic argument in some other source of instantiated
92285
/// metadata.
93286
///
@@ -106,6 +299,12 @@ class GenericArgumentMetadataSource final : public MetadataSource {
106299
Index(Index),
107300
Source(Source) {}
108301

302+
template <typename Allocator>
303+
static const GenericArgumentMetadataSource *
304+
create(Allocator &A, unsigned Index, const MetadataSource *Source) {
305+
return A.template make_source<GenericArgumentMetadataSource>(Index, Source);
306+
}
307+
109308
unsigned getIndex() const {
110309
return Index;
111310
}
@@ -119,6 +318,64 @@ class GenericArgumentMetadataSource final : public MetadataSource {
119318
}
120319
};
121320

321+
/// Metadata gotten through the parent of a nominal type's metadata.
322+
class ParentMetadataSource final : public MetadataSource {
323+
const MetadataSource *Child;
324+
public:
325+
ParentMetadataSource(const MetadataSource *Child)
326+
: MetadataSource(MetadataSourceKind::Parent),
327+
Child(Child) {}
328+
329+
template <typename Allocator>
330+
static const ParentMetadataSource*
331+
create(Allocator &A, const MetadataSource *Child) {
332+
return A.template make_source<ParentMetadataSource>(Child);
333+
}
334+
335+
const MetadataSource *getChild() const {
336+
return Child;
337+
}
338+
339+
static bool classof(const MetadataSource *MS) {
340+
return MS->getKind() == MetadataSourceKind::Parent;
341+
}
342+
};
343+
344+
/// A source of metadata from the Self metadata parameter passed via
345+
/// a witness_method convention function.
346+
class SelfMetadataSource final : public MetadataSource {
347+
public:
348+
SelfMetadataSource() : MetadataSource(MetadataSourceKind::Self) {}
349+
350+
template <typename Allocator>
351+
static const SelfMetadataSource*
352+
create(Allocator &A) {
353+
return A.template make_source<SelfMetadataSource>();
354+
}
355+
356+
static bool classof(const MetadataSource *MS) {
357+
return MS->getKind() == MetadataSourceKind::Self;
358+
}
359+
};
360+
361+
/// A source of metadata from the Self witness table parameter passed via
362+
/// a witness_method convention function.
363+
class SelfWitnessTableMetadataSource final : public MetadataSource {
364+
public:
365+
SelfWitnessTableMetadataSource()
366+
: MetadataSource(MetadataSourceKind::SelfWitnessTable) {}
367+
368+
template <typename Allocator>
369+
static const SelfWitnessTableMetadataSource*
370+
create(Allocator &A) {
371+
return A.template make_source<SelfWitnessTableMetadataSource>();
372+
}
373+
374+
static bool classof(const MetadataSource *MS) {
375+
return MS->getKind() == MetadataSourceKind::SelfWitnessTable;
376+
}
377+
};
378+
122379
template <typename ImplClass, typename RetTy = void, typename... Args>
123380
class MetadataSourceVisitor {
124381
public:

0 commit comments

Comments
 (0)