Skip to content

Commit 60c85b0

Browse files
committed
SILGen: Handle nested opened archetypes and add tests
1 parent 57e8064 commit 60c85b0

File tree

16 files changed

+889
-182
lines changed

16 files changed

+889
-182
lines changed

include/swift/AST/Types.h

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -637,9 +637,9 @@ class alignas(1 << TypeAlignInBits) TypeBase
637637
/// Determine whether the type is an opened existential type with Error inside
638638
bool isOpenedExistentialWithError();
639639

640-
/// Retrieve the set of opened existential archetypes that occur
641-
/// within this type.
642-
void getOpenedExistentials(SmallVectorImpl<OpenedArchetypeType *> &opened);
640+
/// Retrieve the set of root opened archetypes that occur within this type.
641+
void getRootOpenedExistentials(
642+
SmallVectorImpl<OpenedArchetypeType *> &rootOpenedArchetypes) const;
643643

644644
/// Replace opened archetypes with the given root with their most
645645
/// specific non-dependent upper bounds throughout this type.
@@ -5536,7 +5536,8 @@ class ArchetypeType : public SubstitutableType,
55365536
/// primary archetype.
55375537
ArchetypeType *getParent() const;
55385538

5539-
/// Return the root archetype parent of this archetype.
5539+
/// Return the archetype that represents the root generic parameter of its
5540+
/// interface type.
55405541
ArchetypeType *getRoot() const;
55415542

55425543
/// Determine whether this is a root archetype within the environment.
@@ -5773,6 +5774,12 @@ class OpenedArchetypeType final : public ArchetypeType,
57735774
/// Retrieve the opened existential type
57745775
Type getOpenedExistentialType() const;
57755776

5777+
/// Return the archetype that represents the root generic parameter of its
5778+
/// interface type.
5779+
OpenedArchetypeType *getRoot() const {
5780+
return cast<OpenedArchetypeType>(ArchetypeType::getRoot());
5781+
}
5782+
57765783
static bool classof(const TypeBase *T) {
57775784
return T->getKind() == TypeKind::OpenedArchetype;
57785785
}

include/swift/SIL/SILInstruction.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1018,9 +1018,9 @@ class SingleValueInstruction : public SILInstruction, public ValueBase {
10181018
node->getKind() <= SILNodeKind::Last_SingleValueInstruction;
10191019
}
10201020

1021-
/// If this is an instruction which "defines" an opened archetype, it is
1021+
/// If this is an instruction which "defines" a root opened archetype, it is
10221022
/// returned.
1023-
CanArchetypeType getOpenedArchetype() const;
1023+
CanOpenedArchetypeType getDefinedOpenedArchetype() const;
10241024

10251025
SILInstruction *getPreviousInstruction() {
10261026
return SILInstruction::getPreviousInstruction();

include/swift/SIL/SILModule.h

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -323,20 +323,21 @@ class SILModule {
323323
/// projections, shared between all functions in the module.
324324
std::unique_ptr<IndexTrieNode> indexTrieRoot;
325325

326-
/// A mapping from opened archetypes to the instructions which define them.
326+
/// A mapping from root opened archetypes to the instructions which define
327+
/// them.
327328
///
328329
/// The value is either a SingleValueInstrution or a PlaceholderValue, in case
329-
/// an opened-archetype definition is lookedup during parsing or deserializing
330-
/// SIL, where opened archetypes can be forward referenced.
330+
/// an opened archetype definition is looked up during parsing or
331+
/// deserializing SIL, where opened archetypes can be forward referenced.
331332
///
332333
/// In theory we wouldn't need to have the SILFunction in the key, because
333-
/// opened archetypes _should_ be unique across the module. But currently
334+
/// opened archetypes \em should be unique across the module. But currently
334335
/// in some rare cases SILGen re-uses the same opened archetype for multiple
335336
/// functions.
336-
using OpenedArchetypeKey = std::pair<ArchetypeType*, SILFunction*>;
337-
llvm::DenseMap<OpenedArchetypeKey, SILValue> openedArchetypeDefs;
337+
using OpenedArchetypeKey = std::pair<OpenedArchetypeType *, SILFunction *>;
338+
llvm::DenseMap<OpenedArchetypeKey, SILValue> RootOpenedArchetypeDefs;
338339

339-
/// The number of PlaceholderValues in openedArchetypeDefs.
340+
/// The number of PlaceholderValues in RootOpenedArchetypeDefs.
340341
int numUnresolvedOpenedArchetypes = 0;
341342

342343
/// The options passed into this SILModule.
@@ -408,24 +409,25 @@ class SILModule {
408409
regDeserializationNotificationHandlerForAllFuncOME = true;
409410
}
410411

411-
/// Returns the instruction which defines an opened archetype, e.g. an
412-
/// open_existential_addr.
412+
/// Returns the instruction which defines the given root opened archetype,
413+
/// e.g. an open_existential_addr.
413414
///
414415
/// In case the opened archetype is not defined yet (e.g. during parsing or
415416
/// deserilization), a PlaceholderValue is returned. This should not be the
416417
/// case outside of parsing or deserialization.
417-
SILValue getOpenedArchetypeDef(CanArchetypeType archetype,
418-
SILFunction *inFunction);
418+
SILValue getRootOpenedArchetypeDef(CanOpenedArchetypeType archetype,
419+
SILFunction *inFunction);
419420

420-
/// Returns the instruction which defines an opened archetype, e.g. an
421-
/// open_existential_addr.
421+
/// Returns the instruction which defines the given root opened archetype,
422+
/// e.g. an open_existential_addr.
422423
///
423424
/// In contrast to getOpenedArchetypeDef, it is required that all opened
424425
/// archetypes are resolved.
425-
SingleValueInstruction *getOpenedArchetypeInst(CanArchetypeType archetype,
426-
SILFunction *inFunction) {
427-
return cast<SingleValueInstruction>(getOpenedArchetypeDef(archetype,
428-
inFunction));
426+
SingleValueInstruction *
427+
getRootOpenedArchetypeDefInst(CanOpenedArchetypeType archetype,
428+
SILFunction *inFunction) {
429+
return cast<SingleValueInstruction>(
430+
getRootOpenedArchetypeDef(archetype, inFunction));
429431
}
430432

431433
/// Returns true if there are unresolved opened archetypes in the module.

include/swift/SIL/SILType.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ namespace swift {
4646
/// It checks only the type itself, but does not try to
4747
/// recursively check any children of this type, because
4848
/// this is the task of the type visitor invoking it.
49-
/// \returns The found archetype or empty type otherwise.
50-
CanArchetypeType getOpenedArchetypeOf(CanType Ty);
49+
/// \returns The found opened archetype or empty type otherwise.
50+
CanOpenedArchetypeType getOpenedArchetypeOf(CanType Ty);
5151

5252
/// How an existential type container is represented.
5353
enum class ExistentialRepresentation {

lib/AST/Type.cpp

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -455,19 +455,20 @@ bool TypeBase::hasOpenedExistentialWithRoot(
455455
});
456456
}
457457

458-
void TypeBase::getOpenedExistentials(
459-
SmallVectorImpl<OpenedArchetypeType *> &opened) {
458+
void TypeBase::getRootOpenedExistentials(
459+
SmallVectorImpl<OpenedArchetypeType *> &rootOpenedArchetypes) const {
460460
if (!hasOpenedExistential())
461461
return;
462462

463-
SmallPtrSet<ArchetypeType *, 4> known;
463+
SmallPtrSet<OpenedArchetypeType *, 4> known;
464464
getCanonicalType().findIf([&](Type type) -> bool {
465-
auto archetype = dyn_cast<OpenedArchetypeType>(type.getPointer());
465+
auto *archetype = dyn_cast<OpenedArchetypeType>(type.getPointer());
466466
if (!archetype)
467467
return false;
468468

469-
if (known.insert(archetype).second)
470-
opened.push_back(archetype);
469+
auto *root = archetype->getRoot();
470+
if (known.insert(root).second)
471+
rootOpenedArchetypes.push_back(root);
471472

472473
return false;
473474
});
@@ -3329,6 +3330,10 @@ ArchetypeType *ArchetypeType::getParent() const {
33293330
}
33303331

33313332
ArchetypeType *ArchetypeType::getRoot() const {
3333+
if (isRoot()) {
3334+
return const_cast<ArchetypeType *>(this);
3335+
}
3336+
33323337
auto gp = InterfaceType->getRootGenericParam();
33333338
assert(gp && "Missing root generic parameter?");
33343339
return getGenericEnvironment()->mapTypeIntoContext(
@@ -4447,16 +4452,16 @@ static Type substType(Type derivedType,
44474452
if (isa<GenericTypeParamType>(substOrig))
44484453
return ErrorType::get(type);
44494454

4450-
// Opened existentials cannot be substituted in this manner,
4451-
// but if they appear in the original type this is not an
4452-
// error.
44534455
auto origArchetype = cast<ArchetypeType>(substOrig);
4454-
if (isa<OpenedArchetypeType>(origArchetype->getRoot()))
4455-
return Type(type);
4456-
4457-
// Root archetypes must already have been substituted above.
4458-
if (origArchetype->isRoot())
4459-
return ErrorType::get(type);
4456+
if (origArchetype->isRoot()) {
4457+
// Root opened archetypes are not required to be substituted. Other root
4458+
// archetypes must already have been substituted above.
4459+
if (isa<OpenedArchetypeType>(origArchetype)) {
4460+
return Type(type);
4461+
} else {
4462+
return ErrorType::get(type);
4463+
}
4464+
}
44604465

44614466
// For nested archetypes, we can substitute the parent.
44624467
auto parent = origArchetype->getParent();

lib/SIL/IR/SILInstruction.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1571,21 +1571,21 @@ const ValueBase *SILInstructionResultArray::back() const {
15711571
// SingleValueInstruction
15721572
//===----------------------------------------------------------------------===//
15731573

1574-
CanArchetypeType SingleValueInstruction::getOpenedArchetype() const {
1574+
CanOpenedArchetypeType
1575+
SingleValueInstruction::getDefinedOpenedArchetype() const {
15751576
switch (getKind()) {
15761577
case SILInstructionKind::OpenExistentialAddrInst:
15771578
case SILInstructionKind::OpenExistentialRefInst:
15781579
case SILInstructionKind::OpenExistentialBoxInst:
15791580
case SILInstructionKind::OpenExistentialBoxValueInst:
15801581
case SILInstructionKind::OpenExistentialMetatypeInst:
15811582
case SILInstructionKind::OpenExistentialValueInst: {
1582-
auto Ty = getOpenedArchetypeOf(getType().getASTType());
1583-
assert(Ty && Ty->isOpenedExistential() &&
1584-
"Type should be an opened archetype");
1583+
const auto Ty = getOpenedArchetypeOf(getType().getASTType());
1584+
assert(Ty && Ty->isRoot() && "Type should be a root opened archetype");
15851585
return Ty;
15861586
}
15871587
default:
1588-
return CanArchetypeType();
1588+
return CanOpenedArchetypeType();
15891589
}
15901590
}
15911591

lib/SIL/IR/SILInstructions.cpp

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -41,70 +41,69 @@ static void *allocateTrailingInst(SILFunction &F, CountTypes... counts) {
4141
alignof(Inst));
4242
}
4343

44-
// Collect used open archetypes from a given type into the \p openedArchetypes.
45-
// \p openedArchetypes is being used as a set. We don't use a real set type here
46-
// for performance reasons.
47-
static void
48-
collectDependentTypeInfo(CanType Ty,
49-
SmallVectorImpl<CanArchetypeType> &openedArchetypes,
50-
bool &hasDynamicSelf) {
44+
/// Collect root open archetypes from a given type into \p RootOpenedArchetypes.
45+
/// \p RootOpenedArchetypes is being used as a set. We don't use a real set type
46+
/// here for performance reasons.
47+
static void collectDependentTypeInfo(
48+
CanType Ty, SmallVectorImpl<CanOpenedArchetypeType> &RootOpenedArchetypes,
49+
bool &hasDynamicSelf) {
5150
if (!Ty)
5251
return;
5352
if (Ty->hasDynamicSelfType())
5453
hasDynamicSelf = true;
5554
if (!Ty->hasOpenedExistential())
5655
return;
5756
Ty.visit([&](CanType t) {
58-
if (t->isOpenedExistential()) {
59-
// Add this opened archetype if it was not seen yet.
57+
if (const auto opened = dyn_cast<OpenedArchetypeType>(t)) {
58+
const auto root = cast<OpenedArchetypeType>(CanType(opened->getRoot()));
59+
60+
// Add this root opened archetype if it was not seen yet.
6061
// We don't use a set here, because the number of open archetypes
6162
// is usually very small and using a real set may introduce too
6263
// much overhead.
63-
auto archetypeTy = cast<ArchetypeType>(t);
64-
if (std::find(openedArchetypes.begin(), openedArchetypes.end(),
65-
archetypeTy) == openedArchetypes.end())
66-
openedArchetypes.push_back(archetypeTy);
64+
if (std::find(RootOpenedArchetypes.begin(), RootOpenedArchetypes.end(),
65+
root) == RootOpenedArchetypes.end())
66+
RootOpenedArchetypes.push_back(root);
6767
}
6868
});
6969
}
7070

71-
// Takes a set of open archetypes as input and produces a set of
72-
// references to open archetype definitions.
71+
/// Takes a set of root opened archetypes as input and produces a set of
72+
/// references to their definitions.
7373
static void buildTypeDependentOperands(
74-
SmallVectorImpl<CanArchetypeType> &OpenedArchetypes,
75-
bool hasDynamicSelf,
76-
SmallVectorImpl<SILValue> &TypeDependentOperands, SILFunction &F) {
74+
SmallVectorImpl<CanOpenedArchetypeType> &RootOpenedArchetypes,
75+
bool hasDynamicSelf, SmallVectorImpl<SILValue> &TypeDependentOperands,
76+
SILFunction &F) {
7777

78-
for (auto archetype : OpenedArchetypes) {
79-
SILValue def = F.getModule().getOpenedArchetypeDef(archetype, &F);
78+
for (const auto archetype : RootOpenedArchetypes) {
79+
SILValue def = F.getModule().getRootOpenedArchetypeDef(archetype, &F);
8080
assert(def->getFunction() == &F &&
81-
"def of opened archetype is in wrong function");
81+
"def of root opened archetype is in wrong function");
8282
TypeDependentOperands.push_back(def);
8383
}
8484
if (hasDynamicSelf)
8585
TypeDependentOperands.push_back(F.getDynamicSelfMetadata());
8686
}
8787

88-
// Collects all opened archetypes from a type and a substitutions list and form
89-
// a corresponding list of opened archetype operands.
90-
// We need to know the number of opened archetypes to estimate
91-
// the number of opened archetype operands for the instruction
92-
// being formed, because we need to reserve enough memory
93-
// for these operands.
88+
/// Collects all root opened archetypes from a type and a substitution list, and
89+
/// forms a corresponding list of operands.
90+
/// We need to know the number of root opened archetypes to estimate the number
91+
/// of corresponding operands for the instruction being formed, because we need
92+
/// to reserve enough memory for these operands.
9493
static void collectTypeDependentOperands(
9594
SmallVectorImpl<SILValue> &TypeDependentOperands,
9695
SILFunction &F,
9796
CanType Ty,
9897
SubstitutionMap subs = { }) {
99-
SmallVector<CanArchetypeType, 4> openedArchetypes;
98+
SmallVector<CanOpenedArchetypeType, 4> RootOpenedArchetypes;
10099
bool hasDynamicSelf = false;
101-
collectDependentTypeInfo(Ty, openedArchetypes, hasDynamicSelf);
100+
collectDependentTypeInfo(Ty, RootOpenedArchetypes, hasDynamicSelf);
102101
for (Type replacement : subs.getReplacementTypes()) {
103102
// Substitutions in SIL should really be canonical.
104103
auto ReplTy = replacement->getCanonicalType();
105-
collectDependentTypeInfo(ReplTy, openedArchetypes, hasDynamicSelf);
104+
collectDependentTypeInfo(ReplTy, RootOpenedArchetypes, hasDynamicSelf);
106105
}
107-
buildTypeDependentOperands(openedArchetypes, hasDynamicSelf,
106+
buildTypeDependentOperands(RootOpenedArchetypes, hasDynamicSelf,
108107
TypeDependentOperands, F);
109108
}
110109

lib/SIL/IR/SILModule.cpp

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -245,13 +245,14 @@ void *SILModule::allocateInst(unsigned Size, unsigned Align) const {
245245
}
246246

247247
void SILModule::willDeleteInstruction(SILInstruction *I) {
248-
// Update openedArchetypeDefs.
248+
// Update RootOpenedArchetypeDefs.
249249
if (auto *svi = dyn_cast<SingleValueInstruction>(I)) {
250-
if (CanArchetypeType archeTy = svi->getOpenedArchetype()) {
250+
if (const CanOpenedArchetypeType archeTy =
251+
svi->getDefinedOpenedArchetype()) {
251252
OpenedArchetypeKey key = {archeTy, svi->getFunction()};
252-
assert(openedArchetypeDefs.lookup(key) == svi &&
253+
assert(RootOpenedArchetypeDefs.lookup(key) == svi &&
253254
"archetype def was not registered");
254-
openedArchetypeDefs.erase(key);
255+
RootOpenedArchetypeDefs.erase(key);
255256
}
256257
}
257258
}
@@ -761,9 +762,11 @@ void SILModule::registerDeserializationNotificationHandler(
761762
deserializationNotificationHandlers.add(std::move(handler));
762763
}
763764

764-
SILValue SILModule::getOpenedArchetypeDef(CanArchetypeType archetype,
765-
SILFunction *inFunction) {
766-
SILValue &def = openedArchetypeDefs[{archetype, inFunction}];
765+
SILValue SILModule::getRootOpenedArchetypeDef(CanOpenedArchetypeType archetype,
766+
SILFunction *inFunction) {
767+
assert(archetype->isRoot());
768+
769+
SILValue &def = RootOpenedArchetypeDefs[{archetype, inFunction}];
767770
if (!def) {
768771
numUnresolvedOpenedArchetypes++;
769772
def = ::new PlaceholderValue(SILType::getPrimitiveAddressType(archetype));
@@ -778,12 +781,13 @@ bool SILModule::hasUnresolvedOpenedArchetypeDefinitions() {
778781

779782
void SILModule::notifyAddedInstruction(SILInstruction *inst) {
780783
if (auto *svi = dyn_cast<SingleValueInstruction>(inst)) {
781-
if (CanArchetypeType archeTy = svi->getOpenedArchetype()) {
782-
SILValue &val = openedArchetypeDefs[{archeTy, inst->getFunction()}];
784+
if (const CanOpenedArchetypeType archeTy =
785+
svi->getDefinedOpenedArchetype()) {
786+
SILValue &val = RootOpenedArchetypeDefs[{archeTy, inst->getFunction()}];
783787
if (val) {
784788
if (!isa<PlaceholderValue>(val)) {
785789
// Print a useful error message (and not just abort with an assert).
786-
llvm::errs() << "re-definition of opened archetype in function "
790+
llvm::errs() << "re-definition of root opened archetype in function "
787791
<< svi->getFunction()->getName() << ":\n";
788792
svi->print(llvm::errs());
789793
llvm::errs() << "previously defined in function "
@@ -806,12 +810,13 @@ void SILModule::notifyAddedInstruction(SILInstruction *inst) {
806810
void SILModule::notifyMovedInstruction(SILInstruction *inst,
807811
SILFunction *fromFunction) {
808812
if (auto *svi = dyn_cast<SingleValueInstruction>(inst)) {
809-
if (CanArchetypeType archeTy = svi->getOpenedArchetype()) {
813+
if (const CanOpenedArchetypeType archeTy =
814+
svi->getDefinedOpenedArchetype()) {
810815
OpenedArchetypeKey key = {archeTy, fromFunction};
811-
assert(openedArchetypeDefs.lookup(key) == svi &&
816+
assert(RootOpenedArchetypeDefs.lookup(key) == svi &&
812817
"archetype def was not registered");
813-
openedArchetypeDefs.erase(key);
814-
openedArchetypeDefs[{archeTy, svi->getFunction()}] = svi;
818+
RootOpenedArchetypeDefs.erase(key);
819+
RootOpenedArchetypeDefs[{archeTy, svi->getFunction()}] = svi;
815820
}
816821
}
817822
}

0 commit comments

Comments
 (0)