Skip to content

Commit a00896a

Browse files
committed
IRGen: Use conformance access paths to find inherited conformances from opened existentials
Thanks to Joe for the refactoring that made this possible.
1 parent b9eb17c commit a00896a

File tree

3 files changed

+0
-199
lines changed

3 files changed

+0
-199
lines changed

lib/IRGen/GenArchetype.cpp

-25
Original file line numberDiff line numberDiff line change
@@ -172,31 +172,6 @@ llvm::Value *irgen::emitArchetypeWitnessTableRef(IRGenFunction &IGF,
172172
auto wtable = IGF.tryGetLocalTypeData(archetype, localDataKind);
173173
if (wtable) return wtable;
174174

175-
// If we have an opened type, this must be an implied witness table
176-
// reference.
177-
// FIXME: eliminate this path when opened types have generic environments.
178-
if (auto opened = dyn_cast<OpenedArchetypeType>(archetype)) {
179-
SmallVector<ProtocolEntry, 4> entries;
180-
for (auto p : archetype->getConformsTo()) {
181-
const ProtocolInfo &impl =
182-
IGF.IGM.getProtocolInfo(p, ProtocolInfoKind::RequirementSignature);
183-
entries.push_back(ProtocolEntry(p, impl));
184-
}
185-
186-
return emitImpliedWitnessTableRef(IGF, entries, protocol,
187-
[&](unsigned index) -> llvm::Value* {
188-
auto localDataKind =
189-
LocalTypeDataKind::forAbstractProtocolWitnessTable(
190-
entries[index].getProtocol());
191-
auto wtable = IGF.tryGetLocalTypeData(archetype, localDataKind);
192-
assert(wtable &&
193-
"opened type without local type data for direct conformance?");
194-
return wtable;
195-
});
196-
}
197-
198-
assert(isa<PrimaryArchetypeType>(archetype->getRoot())
199-
&& "might not work yet for opened/opaque archetypes!");
200175
auto environment = archetype->getGenericEnvironment();
201176

202177
// Otherwise, ask the generic signature for the environment for the best

lib/IRGen/GenProto.cpp

-154
Original file line numberDiff line numberDiff line change
@@ -800,150 +800,6 @@ namespace {
800800

801801
ArrayRef<WitnessTableEntry> getEntries() const { return Entries; }
802802
};
803-
804-
/// A path through a protocol hierarchy.
805-
class ProtocolPath {
806-
IRGenModule &IGM;
807-
808-
/// The destination protocol.
809-
ProtocolDecl *Dest;
810-
811-
/// The path from the selected origin down to the destination
812-
/// protocol.
813-
SmallVector<WitnessIndex, 8> ReversePath;
814-
815-
/// The origin index to use.
816-
unsigned OriginIndex;
817-
818-
/// The best path length we found.
819-
unsigned BestPathLength;
820-
821-
public:
822-
/// Find a path from the given set of origins to the destination
823-
/// protocol.
824-
///
825-
/// T needs to provide a couple of member functions:
826-
/// ProtocolDecl *getProtocol() const;
827-
/// const ProtocolInfo &getInfo() const;
828-
template <class T>
829-
ProtocolPath(IRGenModule &IGM, ArrayRef<T> origins, ProtocolDecl *dest)
830-
: IGM(IGM), Dest(dest), BestPathLength(~0U) {
831-
832-
// Consider each of the origins in turn, breaking out if any of
833-
// them yields a zero-length path.
834-
for (unsigned i = 0, e = origins.size(); i != e; ++i) {
835-
auto &origin = origins[i];
836-
if (considerOrigin(origin.getProtocol(), origin.getInfo(), i))
837-
break;
838-
}
839-
840-
// Sanity check that we actually found a path at all.
841-
assert(BestPathLength != ~0U);
842-
assert(BestPathLength == ReversePath.size());
843-
}
844-
845-
/// Returns the index of the origin protocol we chose.
846-
unsigned getOriginIndex() const { return OriginIndex; }
847-
848-
/// Apply the path to the given witness table.
849-
llvm::Value *apply(IRGenFunction &IGF, llvm::Value *wtable) const {
850-
for (unsigned i = ReversePath.size(); i != 0; --i) {
851-
wtable = emitInvariantLoadOfOpaqueWitness(IGF, wtable,
852-
ReversePath[i-1].forProtocolWitnessTable());
853-
wtable = IGF.Builder.CreateBitCast(wtable, IGF.IGM.WitnessTablePtrTy);
854-
}
855-
return wtable;
856-
}
857-
858-
private:
859-
/// Consider paths starting from a new origin protocol.
860-
/// Returns true if there's no point in considering other origins.
861-
bool considerOrigin(ProtocolDecl *origin, const ProtocolInfo &originInfo,
862-
unsigned originIndex) {
863-
assert(BestPathLength != 0);
864-
865-
// If the origin *is* the destination, we can stop here.
866-
if (origin == Dest) {
867-
OriginIndex = originIndex;
868-
BestPathLength = 0;
869-
ReversePath.clear();
870-
return true;
871-
}
872-
873-
// Otherwise, if the origin gives rise to a better path, that's
874-
// also cool.
875-
if (findBetterPath(origin, originInfo, 0)) {
876-
OriginIndex = originIndex;
877-
return BestPathLength == 0;
878-
}
879-
880-
return false;
881-
}
882-
883-
/// Consider paths starting at the given protocol.
884-
bool findBetterPath(ProtocolDecl *proto, const ProtocolInfo &protoInfo,
885-
unsigned lengthSoFar) {
886-
assert(lengthSoFar < BestPathLength);
887-
assert(proto != Dest);
888-
889-
// Keep track of whether we found a better path than the
890-
// previous best.
891-
bool foundBetter = false;
892-
for (auto base : proto->getInheritedProtocols()) {
893-
// ObjC protocols do not have witnesses.
894-
if (!Lowering::TypeConverter::protocolRequiresWitnessTable(base))
895-
continue;
896-
897-
auto baseIndex = protoInfo.getBaseIndex(base);
898-
899-
// Compute the length down to this base.
900-
unsigned lengthToBase = lengthSoFar;
901-
if (!baseIndex.isPrefix()) {
902-
lengthToBase++;
903-
904-
// Don't consider this path if we reach a length that can't
905-
// possibly be better than the best so far.
906-
if (lengthToBase == BestPathLength) continue;
907-
}
908-
assert(lengthToBase < BestPathLength);
909-
910-
// If this base *is* the destination, go ahead and start
911-
// building the path into ReversePath.
912-
if (base == Dest) {
913-
// Reset the collected best-path information.
914-
BestPathLength = lengthToBase;
915-
ReversePath.clear();
916-
917-
// Otherwise, if there isn't a better path through this base,
918-
// don't accumulate anything in the path.
919-
} else {
920-
const ProtocolInfo &baseInfo =
921-
IGM.getProtocolInfo(base, ProtocolInfoKind::RequirementSignature);
922-
if (!findBetterPath(base, baseInfo, lengthToBase))
923-
continue;
924-
}
925-
926-
// Okay, we've found a better path, and ReversePath contains a
927-
// path leading from base to Dest.
928-
assert(BestPathLength >= lengthToBase);
929-
foundBetter = true;
930-
931-
// Add the link from proto to base if necessary.
932-
if (!baseIndex.isPrefix()) {
933-
ReversePath.push_back(baseIndex);
934-
935-
// If it isn't necessary, then we might be able to
936-
// short-circuit considering the bases of this protocol.
937-
} else {
938-
if (lengthSoFar == BestPathLength)
939-
return true;
940-
}
941-
}
942-
943-
return foundBetter;
944-
}
945-
};
946-
947803
} // end anonymous namespace
948804

949805
/// Return true if the witness table requires runtime instantiation to
@@ -2889,16 +2745,6 @@ void NecessaryBindings::addProtocolConformance(CanType type,
28892745
Requirements.insert({type, conf.getAbstract()});
28902746
}
28912747

2892-
llvm::Value *irgen::emitImpliedWitnessTableRef(IRGenFunction &IGF,
2893-
ArrayRef<ProtocolEntry> entries,
2894-
ProtocolDecl *target,
2895-
const GetWitnessTableFn &getWitnessTable) {
2896-
ProtocolPath path(IGF.IGM, entries, target);
2897-
auto wtable = getWitnessTable(path.getOriginIndex());
2898-
wtable = path.apply(IGF, wtable);
2899-
return wtable;
2900-
}
2901-
29022748
llvm::Value *irgen::emitWitnessTableRef(IRGenFunction &IGF,
29032749
CanType srcType,
29042750
ProtocolConformanceRef conformance) {

lib/IRGen/GenProto.h

-20
Original file line numberDiff line numberDiff line change
@@ -177,26 +177,6 @@ namespace irgen {
177177
CanType srcType,
178178
ProtocolConformanceRef conformance);
179179

180-
/// An entry in a list of known protocols.
181-
class ProtocolEntry {
182-
ProtocolDecl *Protocol;
183-
const ProtocolInfo &Impl;
184-
185-
public:
186-
explicit ProtocolEntry(ProtocolDecl *proto, const ProtocolInfo &impl)
187-
: Protocol(proto), Impl(impl) {}
188-
189-
ProtocolDecl *getProtocol() const { return Protocol; }
190-
const ProtocolInfo &getInfo() const { return Impl; }
191-
};
192-
193-
using GetWitnessTableFn =
194-
llvm::function_ref<llvm::Value*(unsigned originIndex)>;
195-
llvm::Value *emitImpliedWitnessTableRef(IRGenFunction &IGF,
196-
ArrayRef<ProtocolEntry> protos,
197-
ProtocolDecl *target,
198-
const GetWitnessTableFn &getWitnessTable);
199-
200180
class MetadataSource {
201181
public:
202182
enum class Kind {

0 commit comments

Comments
 (0)