Skip to content

Commit c2da971

Browse files
committed
[GSB] Store the root potential archetype in RequirementSource.
Use TrailingObjects to help us efficiently store the root potential archetype within requirement sources, so we can reconstruct the complete path from the point where a requirement was created to the potential archetype it affects. The test changes are because we are now dumping the root potential archetype as part of -debug-generic-signatures.
1 parent 2d430d8 commit c2da971

File tree

6 files changed

+148
-86
lines changed

6 files changed

+148
-86
lines changed

include/swift/AST/GenericSignatureBuilder.h

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "llvm/ADT/STLExtras.h"
3232
#include "llvm/ADT/MapVector.h"
3333
#include "llvm/ADT/TinyPtrVector.h"
34+
#include "llvm/Support/TrailingObjects.h"
3435
#include <functional>
3536
#include <memory>
3637

@@ -402,7 +403,10 @@ class GenericSignatureBuilder {
402403
/// other implications (e.g., introduced by a particular protocol).
403404
///
404405
/// Requirement sources are uniqued within a generic signature builder.
405-
class GenericSignatureBuilder::RequirementSource : public llvm::FoldingSetNode {
406+
class GenericSignatureBuilder::RequirementSource final
407+
: public llvm::FoldingSetNode,
408+
private llvm::TrailingObjects<RequirementSource, PotentialArchetype *> {
409+
406410
public:
407411
enum Kind : uint8_t {
408412
/// A requirement stated explicitly, e.g., in a where clause or type
@@ -468,7 +472,7 @@ class GenericSignatureBuilder::RequirementSource : public llvm::FoldingSetNode {
468472
private:
469473
/// The kind of storage we have.
470474
enum class StorageKind : uint8_t {
471-
None,
475+
RootArchetype,
472476
TypeRepr,
473477
RequirementRepr,
474478
ProtocolDecl,
@@ -481,6 +485,9 @@ class GenericSignatureBuilder::RequirementSource : public llvm::FoldingSetNode {
481485

482486
/// The actual storage, described by \c storageKind.
483487
union {
488+
/// The root archetype.
489+
PotentialArchetype *rootArchetype;
490+
484491
/// The type representation describing where the requirement came from.
485492
const TypeRepr *typeRepr;
486493

@@ -497,13 +504,38 @@ class GenericSignatureBuilder::RequirementSource : public llvm::FoldingSetNode {
497504
AssociatedTypeDecl *assocType;
498505
} storage;
499506

507+
friend TrailingObjects;
508+
509+
/// The trailing potential archetype, for
510+
size_t numTrailingObjects(OverloadToken<PotentialArchetype *>) const {
511+
switch (kind) {
512+
case RequirementSignatureSelf:
513+
return 1;
514+
515+
case Explicit:
516+
case Inferred:
517+
return storageKind == StorageKind::RootArchetype ? 0 : 1;
518+
519+
case NestedTypeNameMatch:
520+
case ProtocolRequirement:
521+
case Superclass:
522+
case Parent:
523+
case Concrete:
524+
return 0;
525+
}
526+
}
527+
500528
/// Determines whether we have been provided with an acceptable storage kind
501529
/// for the given requirement source kind.
502530
static bool isAcceptableStorageKind(Kind kind, StorageKind storageKind);
503531

504532
/// Retrieve the opaque storage as a single pointer, for use in uniquing.
505533
const void *getOpaqueStorage() const;
506534

535+
/// Retrieve the extra opaque storage as a single pointer, for use in
536+
/// uniquing.
537+
const void *getExtraOpaqueStorage() const;
538+
507539
/// Whether this kind of requirement source is a root.
508540
static bool isRootKind(Kind kind) {
509541
switch (kind) {
@@ -528,15 +560,15 @@ class GenericSignatureBuilder::RequirementSource : public llvm::FoldingSetNode {
528560
/// requirement source with one of the "root" kinds.
529561
const RequirementSource * const parent;
530562

531-
RequirementSource(Kind kind, const RequirementSource *parent)
532-
: kind(kind), storageKind(StorageKind::None), parent(parent) {
563+
RequirementSource(Kind kind, const RequirementSource *parent,
564+
PotentialArchetype *rootArchetype)
565+
: kind(kind), storageKind(StorageKind::RootArchetype), parent(parent) {
533566
assert((static_cast<bool>(parent) != isRootKind(kind)) &&
534567
"Root RequirementSource should not have parent (or vice versa)");
535568
assert(isAcceptableStorageKind(kind, storageKind) &&
536569
"RequirementSource kind/storageKind mismatch");
537570

538-
// Prevent uninitialized memory.
539-
storage.typeRepr = nullptr;
571+
storage.rootArchetype = rootArchetype;
540572
}
541573

542574
RequirementSource(Kind kind, const RequirementSource *parent,
@@ -651,6 +683,9 @@ class GenericSignatureBuilder::RequirementSource : public llvm::FoldingSetNode {
651683
const RequirementSource *viaParent(GenericSignatureBuilder &builder,
652684
AssociatedTypeDecl *assocType) const;
653685

686+
/// Retrieve the potential archetype at the root.
687+
PotentialArchetype *getRootPotentialArchetype() const;
688+
654689
/// Whether the requirement can be derived from something in its path.
655690
///
656691
/// Derived requirements will not be recorded in a minimized generic
@@ -704,15 +739,17 @@ class GenericSignatureBuilder::RequirementSource : public llvm::FoldingSetNode {
704739

705740
/// Profiling support for \c FoldingSet.
706741
void Profile(llvm::FoldingSetNodeID &ID) {
707-
Profile(ID, kind, parent, getOpaqueStorage());
742+
Profile(ID, kind, parent, getOpaqueStorage(), getExtraOpaqueStorage());
708743
}
709744

710745
/// Profiling support for \c FoldingSet.
711746
static void Profile(llvm::FoldingSetNodeID &ID, Kind kind,
712-
const RequirementSource *parent, const void *storage) {
747+
const RequirementSource *parent, const void *storage,
748+
const void *extraStorage) {
713749
ID.AddInteger(kind);
714750
ID.AddPointer(parent);
715751
ID.AddPointer(storage);
752+
ID.AddPointer(extraStorage);
716753
}
717754

718755
LLVM_ATTRIBUTE_DEPRECATED(

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 69 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ bool RequirementSource::isAcceptableStorageKind(Kind kind,
8282
switch (kind) {
8383
case Explicit:
8484
switch (storageKind) {
85-
case StorageKind::None:
85+
case StorageKind::RootArchetype:
8686
case StorageKind::TypeRepr:
8787
case StorageKind::RequirementRepr:
8888
return true;
@@ -95,7 +95,7 @@ bool RequirementSource::isAcceptableStorageKind(Kind kind,
9595

9696
case Inferred:
9797
switch (storageKind) {
98-
case StorageKind::None:
98+
case StorageKind::RootArchetype:
9999
case StorageKind::TypeRepr:
100100
return true;
101101

@@ -108,7 +108,7 @@ bool RequirementSource::isAcceptableStorageKind(Kind kind,
108108

109109
case NestedTypeNameMatch:
110110
switch (storageKind) {
111-
case StorageKind::None:
111+
case StorageKind::RootArchetype:
112112
return true;
113113

114114
case StorageKind::TypeRepr:
@@ -124,7 +124,7 @@ bool RequirementSource::isAcceptableStorageKind(Kind kind,
124124
case StorageKind::AssociatedTypeDecl:
125125
return true;
126126

127-
case StorageKind::None:
127+
case StorageKind::RootArchetype:
128128
case StorageKind::TypeRepr:
129129
case StorageKind::ProtocolDecl:
130130
case StorageKind::ProtocolConformance:
@@ -138,7 +138,7 @@ bool RequirementSource::isAcceptableStorageKind(Kind kind,
138138
case StorageKind::ProtocolDecl:
139139
return true;
140140

141-
case StorageKind::None:
141+
case StorageKind::RootArchetype:
142142
case StorageKind::TypeRepr:
143143
case StorageKind::ProtocolConformance:
144144
case StorageKind::RequirementRepr:
@@ -152,7 +152,7 @@ bool RequirementSource::isAcceptableStorageKind(Kind kind,
152152
case StorageKind::ProtocolConformance:
153153
return true;
154154

155-
case StorageKind::None:
155+
case StorageKind::RootArchetype:
156156
case StorageKind::ProtocolDecl:
157157
case StorageKind::TypeRepr:
158158
case StorageKind::RequirementRepr:
@@ -164,9 +164,8 @@ bool RequirementSource::isAcceptableStorageKind(Kind kind,
164164

165165
const void *RequirementSource::getOpaqueStorage() const {
166166
switch (storageKind) {
167-
case StorageKind::None:
168-
// Note: always null.
169-
return storage.typeRepr;
167+
case StorageKind::RootArchetype:
168+
return storage.rootArchetype;
170169

171170
case StorageKind::TypeRepr:
172171
return storage.typeRepr;
@@ -185,6 +184,13 @@ const void *RequirementSource::getOpaqueStorage() const {
185184
}
186185
}
187186

187+
const void *RequirementSource::getExtraOpaqueStorage() const {
188+
if (numTrailingObjects(OverloadToken<PotentialArchetype *>()) == 1)
189+
return getTrailingObjects<PotentialArchetype *>()[0];
190+
191+
return nullptr;
192+
}
193+
188194
bool RequirementSource::isDerivedRequirement() const {
189195
switch (kind) {
190196
case Explicit:
@@ -228,110 +234,126 @@ bool RequirementSource::isDerivedViaConcreteConformance() const {
228234
return false;
229235
}
230236

231-
#define REQUIREMENT_SOURCE_FACTORY_BODY(SourceKind, Parent, Storage) \
232-
llvm::FoldingSetNodeID nodeID; \
233-
Profile(nodeID, Kind::SourceKind, Parent, Storage); \
234-
\
235-
void *insertPos = nullptr; \
236-
if (auto known = \
237-
builder.Impl->RequirementSources.FindNodeOrInsertPos(nodeID, \
238-
insertPos)) \
239-
return known; \
240-
\
241-
auto result = new RequirementSource(Kind::SourceKind, Parent, Storage); \
242-
builder.Impl->RequirementSources.InsertNode(result, insertPos); \
243-
return result
244-
245-
#define REQUIREMENT_SOURCE_FACTORY_BODY_NOSTORAGE(SourceKind, Parent) \
237+
#define REQUIREMENT_SOURCE_FACTORY_BODY( \
238+
SourceKind, Parent, Storage, ExtraStorage, \
239+
NumPotentialArchetypes) \
246240
llvm::FoldingSetNodeID nodeID; \
247-
Profile(nodeID, Kind::SourceKind, Parent, nullptr); \
241+
Profile(nodeID, Kind::SourceKind, Parent, Storage, ExtraStorage); \
248242
\
249243
void *insertPos = nullptr; \
250244
if (auto known = \
251245
builder.Impl->RequirementSources.FindNodeOrInsertPos(nodeID, \
252246
insertPos)) \
253247
return known; \
254248
\
255-
auto result = new RequirementSource(Kind::SourceKind, Parent); \
249+
unsigned size = \
250+
totalSizeToAlloc<PotentialArchetype *>(NumPotentialArchetypes); \
251+
void *mem = malloc(size); \
252+
auto result = new (mem) RequirementSource(Kind::SourceKind, Parent, \
253+
Storage); \
254+
if (NumPotentialArchetypes > 0) \
255+
result->getTrailingObjects<PotentialArchetype *>()[0] = ExtraStorage; \
256256
builder.Impl->RequirementSources.InsertNode(result, insertPos); \
257257
return result
258258

259259
const RequirementSource *RequirementSource::forAbstract(
260260
PotentialArchetype *root) {
261261
auto &builder = *root->getBuilder();
262-
// FIXME: Store the root
263-
REQUIREMENT_SOURCE_FACTORY_BODY_NOSTORAGE(Explicit, nullptr);
262+
REQUIREMENT_SOURCE_FACTORY_BODY(Explicit, nullptr, root, nullptr, 0);
264263
}
265264

266265
const RequirementSource *RequirementSource::forExplicit(
267266
PotentialArchetype *root,
268267
const TypeRepr *typeRepr) {
268+
// If the type representation is NULL, we have an abstract requirement
269+
// source.
270+
if (!typeRepr)
271+
return forAbstract(root);
272+
269273
auto &builder = *root->getBuilder();
270274
// FIXME: Store the root
271-
REQUIREMENT_SOURCE_FACTORY_BODY(Explicit, nullptr, typeRepr);
275+
REQUIREMENT_SOURCE_FACTORY_BODY(Explicit, nullptr, typeRepr, root, 1);
272276
}
273277

274278
const RequirementSource *RequirementSource::forExplicit(
275279
PotentialArchetype *root,
276280
const RequirementRepr *requirementRepr) {
281+
// If the requirement representation is NULL, we have an abstract requirement
282+
// source.
283+
if (!requirementRepr)
284+
return forAbstract(root);
285+
277286
auto &builder = *root->getBuilder();
278-
// FIXME: Store the root
279-
REQUIREMENT_SOURCE_FACTORY_BODY(Explicit, nullptr, requirementRepr);
287+
REQUIREMENT_SOURCE_FACTORY_BODY(Explicit, nullptr, requirementRepr, root, 1);
280288
}
281289

282290
const RequirementSource *RequirementSource::forInferred(
283291
PotentialArchetype *root,
284292
const TypeRepr *typeRepr) {
285293
auto &builder = *root->getBuilder();
286-
// FIXME: Store the root
287-
REQUIREMENT_SOURCE_FACTORY_BODY(Inferred, nullptr, typeRepr);
294+
REQUIREMENT_SOURCE_FACTORY_BODY(Inferred, nullptr, typeRepr, root, 1);
288295
}
289296

290297
const RequirementSource *RequirementSource::forRequirementSignature(
291298
PotentialArchetype *root,
292299
ProtocolDecl *protocol) {
293300
auto &builder = *root->getBuilder();
294-
// FIXME: Store the root
295-
REQUIREMENT_SOURCE_FACTORY_BODY(RequirementSignatureSelf, nullptr, protocol);
301+
REQUIREMENT_SOURCE_FACTORY_BODY(RequirementSignatureSelf, nullptr, protocol,
302+
root, 1);
296303
}
297304

298305
const RequirementSource *RequirementSource::forNestedTypeNameMatch(
299306
PotentialArchetype *root) {
300307
auto &builder = *root->getBuilder();
301-
// FIXME: Store the root
302-
REQUIREMENT_SOURCE_FACTORY_BODY_NOSTORAGE(NestedTypeNameMatch, nullptr);
308+
REQUIREMENT_SOURCE_FACTORY_BODY(NestedTypeNameMatch, nullptr, root, nullptr,
309+
0);
303310
}
304311

305312
const RequirementSource *RequirementSource::viaAbstractProtocolRequirement(
306313
GenericSignatureBuilder &builder,
307314
ProtocolDecl *protocol) const {
308-
REQUIREMENT_SOURCE_FACTORY_BODY(ProtocolRequirement, this, protocol);
315+
REQUIREMENT_SOURCE_FACTORY_BODY(ProtocolRequirement, this, protocol,
316+
nullptr, 0);
309317
}
310318

311319
const RequirementSource *RequirementSource::viaSuperclass(
312320
GenericSignatureBuilder &builder,
313321
ProtocolConformance *conformance) const {
314-
REQUIREMENT_SOURCE_FACTORY_BODY(Superclass, this, conformance);
322+
REQUIREMENT_SOURCE_FACTORY_BODY(Superclass, this, conformance, nullptr, 0);
315323
}
316324

317325
const RequirementSource *RequirementSource::viaConcrete(
318326
GenericSignatureBuilder &builder,
319327
ProtocolConformance *conformance) const {
320-
REQUIREMENT_SOURCE_FACTORY_BODY(Concrete, this, conformance);
328+
REQUIREMENT_SOURCE_FACTORY_BODY(Concrete, this, conformance, nullptr, 0);
321329
}
322330

323331
const RequirementSource *RequirementSource::viaParent(
324332
GenericSignatureBuilder &builder,
325333
AssociatedTypeDecl *assocType) const {
326-
REQUIREMENT_SOURCE_FACTORY_BODY(Parent, this, assocType);
334+
REQUIREMENT_SOURCE_FACTORY_BODY(Parent, this, assocType, nullptr, 0);
327335
}
328336

329-
#undef REQUIREMENT_SOURCE_FACTORY_BODY_NOSTORAGE
330337
#undef REQUIREMENT_SOURCE_FACTORY_BODY
331338

339+
PotentialArchetype *RequirementSource::getRootPotentialArchetype() const {
340+
/// Find the root.
341+
auto root = this;
342+
while (auto parent = root->parent)
343+
root = parent;
344+
345+
// If the root archetype is in extra storage, grab it from there.
346+
if (root->numTrailingObjects(OverloadToken<PotentialArchetype *>()) == 1)
347+
return root->getTrailingObjects<PotentialArchetype *>()[0];
348+
349+
// Otherwise, it's in inline storage.
350+
assert(storageKind == StorageKind::RootArchetype);
351+
return storage.rootArchetype;
352+
}
353+
332354
ProtocolDecl *RequirementSource::getProtocolDecl() const {
333355
switch (storageKind) {
334-
case StorageKind::None:
356+
case StorageKind::RootArchetype:
335357
case StorageKind::TypeRepr:
336358
case StorageKind::RequirementRepr:
337359
return nullptr;
@@ -405,6 +427,9 @@ void RequirementSource::print(llvm::raw_ostream &out,
405427
if (parent) {
406428
parent->print(out, srcMgr);
407429
out << " -> ";
430+
} else {
431+
auto pa = getRootPotentialArchetype();
432+
out << pa->getDebugName() << ": ";
408433
}
409434

410435
switch (kind) {
@@ -453,7 +478,7 @@ void RequirementSource::print(llvm::raw_ostream &out,
453478
};
454479

455480
switch (storageKind) {
456-
case StorageKind::None:
481+
case StorageKind::RootArchetype:
457482
break;
458483

459484
case StorageKind::TypeRepr:

0 commit comments

Comments
 (0)