Skip to content

[IRGen] Bind wtables at open_pack_element. #63502

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/IRGen/GenArchetype.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ llvm::Value *irgen::emitArchetypeWitnessTableRef(IRGenFunction &IGF,
/*request*/ MetadataState::Complete,
nullptr).getMetadata();

IGF.setScopedLocalTypeData(archetype, localDataKind, wtable);
return wtable;
}

Expand Down
342 changes: 310 additions & 32 deletions lib/IRGen/GenPack.cpp

Large diffs are not rendered by default.

22 changes: 17 additions & 5 deletions lib/IRGen/GenPack.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "swift/AST/Types.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallVector.h"

namespace llvm {

Expand Down Expand Up @@ -50,15 +51,26 @@ emitTypeMetadataPackRef(IRGenFunction &IGF,
CanPackType packType,
DynamicMetadataRequest request);

llvm::Value *emitTypeMetadataPackElementRef(IRGenFunction &IGF,
CanPackType packType,
llvm::Value *index,
DynamicMetadataRequest request);
llvm::Value *
emitTypeMetadataPackElementRef(IRGenFunction &IGF, CanPackType packType,
ArrayRef<ProtocolDecl *> protocols,
llvm::Value *index,
DynamicMetadataRequest request,
llvm::SmallVectorImpl<llvm::Value *> &wtables);

void cleanupTypeMetadataPack(IRGenFunction &IGF,
StackAddress pack,
Optional<unsigned> elementCount);

StackAddress emitWitnessTablePack(IRGenFunction &IGF, CanPackType packType,
PackConformance *conformance);

llvm::Value *emitWitnessTablePackRef(IRGenFunction &IGF, CanPackType packType,
PackConformance *conformance);

void cleanupWitnessTablePack(IRGenFunction &IGF, StackAddress pack,
Optional<unsigned> elementCount);

/// Emit the dynamic index of a particular structural component
/// of the given pack type. If the component is a pack expansion, this
/// is the index of the first element of the pack (or where it would be
Expand All @@ -70,4 +82,4 @@ llvm::Value *emitIndexOfStructuralPackComponent(IRGenFunction &IGF,
} // end namespace irgen
} // end namespace swift

#endif
#endif
4 changes: 4 additions & 0 deletions lib/IRGen/GenProto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
#include "GenHeap.h"
#include "GenMeta.h"
#include "GenOpaque.h"
#include "GenPack.h"
#include "GenPointerAuth.h"
#include "GenPoly.h"
#include "GenType.h"
Expand Down Expand Up @@ -3250,6 +3251,9 @@ llvm::Value *irgen::emitWitnessTableRef(IRGenFunction &IGF,
// conformance info for them. However, that conformance info might be
// more concrete than we're expecting.
// TODO: make a best effort to devirtualize, maybe?
} else if (conformance.isPack()) {
auto pack = cast<PackType>(srcType);
return emitWitnessTablePackRef(IGF, pack, conformance.getPack());
} else {
concreteConformance = conformance.getConcrete();
}
Expand Down
9 changes: 6 additions & 3 deletions lib/IRGen/IRGenSIL.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6876,10 +6876,13 @@ void IRGenSILFunction::visitOpenPackElementInst(swift::OpenPackElementInst *i) {

i->getOpenedGenericEnvironment()->forEachPackElementBinding(
[&](auto *archetype, auto *pack) {
auto protocols = archetype->getConformsTo();
llvm::SmallVector<llvm::Value *, 2> wtables;
auto *metadata = emitTypeMetadataPackElementRef(
*this, CanPackType(pack), index, MetadataState::Complete);
this->bindArchetype(CanElementArchetypeType(archetype), metadata,
MetadataState::Complete, {});
*this, CanPackType(pack), protocols, index, MetadataState::Complete,
wtables);
bindArchetype(CanElementArchetypeType(archetype), metadata,
MetadataState::Complete, wtables);
});

// The result is just used for type dependencies.
Expand Down
9 changes: 9 additions & 0 deletions lib/IRGen/LocalTypeData.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include "IRGenModule.h"
#include "MetadataRequest.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/PackConformance.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/SIL/SILModule.h"

Expand Down Expand Up @@ -705,12 +706,20 @@ void LocalTypeDataKind::print(llvm::raw_ostream &out) const {
out << "AbstractConformance("
<< getAbstractProtocolConformance()->getName()
<< ")";
} else if (isPackProtocolConformance()) {
out << "PackConformance("
<< getPackProtocolConformance()->getType()
<< ":"
<< getPackProtocolConformance()->getProtocol()->getName()
<< ")";
} else if (Value == FormalTypeMetadata) {
out << "FormalTypeMetadata";
} else if (Value == RepresentationTypeMetadata) {
out << "RepresentationTypeMetadata";
} else if (Value == ValueWitnessTable) {
out << "ValueWitnessTable";
} else if (Value == Shape) {
out << "Shape";
} else {
assert(isSingletonKind());
if (Value >= ValueWitnessDiscriminatorBase) {
Expand Down
27 changes: 24 additions & 3 deletions lib/IRGen/LocalTypeDataKind.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,10 @@ class LocalTypeDataKind {
ValueWitnessDiscriminatorBase = ValueWitnessBase + MaxNumValueWitnesses,

FirstPayloadValue = 2048,
Kind_Decl = 0,
Kind_Conformance = 1,
KindMask = 0x1,
Kind_Decl = 0b0,
Kind_Conformance = 0b1,
Kind_PackConformance = 0b10,
KindMask = 0b11,
};

public:
Expand Down Expand Up @@ -119,10 +120,17 @@ class LocalTypeDataKind {
return LocalTypeDataKind(uintptr_t(conformance) | Kind_Conformance);
}

static LocalTypeDataKind forProtocolWitnessTablePack(PackConformance *pack) {
assert(pack && "pack conformance reference may not be null");
return LocalTypeDataKind(uintptr_t(pack) | Kind_PackConformance);
}

static LocalTypeDataKind
forProtocolWitnessTable(ProtocolConformanceRef conformance) {
if (conformance.isConcrete()) {
return forConcreteProtocolWitnessTable(conformance.getConcrete());
} else if (conformance.isPack()) {
return forProtocolWitnessTablePack(conformance.getPack());
} else {
return forAbstractProtocolWitnessTable(conformance.getAbstract());
}
Expand Down Expand Up @@ -159,11 +167,24 @@ class LocalTypeDataKind {
return reinterpret_cast<ProtocolDecl*>(Value - Kind_Decl);
}

bool isPackProtocolConformance() const {
return (!isSingletonKind() &&
((Value & KindMask) == Kind_PackConformance));
}

PackConformance *getPackProtocolConformance() const {
assert(isPackProtocolConformance());
return reinterpret_cast<PackConformance*>(Value - Kind_PackConformance);
}

ProtocolConformanceRef getProtocolConformance() const {
assert(!isSingletonKind());
if ((Value & KindMask) == Kind_Decl) {
return ProtocolConformanceRef(getAbstractProtocolConformance());
} else if ((Value & KindMask) == Kind_PackConformance) {
return ProtocolConformanceRef(getPackProtocolConformance());
} else {
assert((Value & KindMask) == Kind_Conformance);
return ProtocolConformanceRef(getConcreteProtocolConformance());
}
}
Expand Down
Loading