Skip to content

Commit 5b4c2cf

Browse files
committed
Minor improvements to MetadataPath for base conformances.
1 parent dbf2be4 commit 5b4c2cf

File tree

5 files changed

+119
-63
lines changed

5 files changed

+119
-63
lines changed

lib/IRGen/Fulfillment.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "swift/AST/SubstitutionMap.h"
2323
#include "swift/SIL/TypeLowering.h"
2424
#include "GenericRequirement.h"
25+
#include "ProtocolInfo.h"
2526

2627
using namespace swift;
2728
using namespace irgen;
@@ -179,22 +180,20 @@ bool FulfillmentMap::searchWitnessTable(IRGenModule &IGM,
179180

180181
bool hadFulfillment = false;
181182

182-
auto nextInheritedIndex = 0;
183-
for (auto inherited : protocol->getInheritedProtocols()) {
184-
auto index = nextInheritedIndex++;
183+
auto &pi = IGM.getProtocolInfo(protocol);
185184

186-
// Ignore protocols that don't have witness tables.
187-
if (!Lowering::TypeConverter::protocolRequiresWitnessTable(inherited))
188-
continue;
185+
for (auto &entry : pi.getWitnessEntries()) {
186+
if (!entry.isBase()) continue;
189187

188+
ProtocolDecl *inherited = entry.getBase();
190189
MetadataPath inheritedPath = path;
191-
inheritedPath.addInheritedProtocolComponent(index);
190+
inheritedPath.addInheritedProtocolComponent(pi.getBaseWitnessIndex(&entry));
192191
hadFulfillment |= searchWitnessTable(IGM, type, inherited,
193192
source, std::move(inheritedPath),
194193
keys, interestingConformances);
195194
}
196195

197-
// If we're not limited the set of interesting conformances, or if
196+
// If we're not limiting the set of interesting conformances, or if
198197
// this is an interesting conformance, record it.
199198
if (!interestingConformances || interestingConformances->count(protocol)) {
200199
hadFulfillment |= addFulfillment({type, protocol}, source, std::move(path));

lib/IRGen/GenProto.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2066,11 +2066,14 @@ llvm::Value *MetadataPath::followComponent(IRGenFunction &IGF,
20662066
return source;
20672067
}
20682068

2069-
case Component::Kind::InheritedProtocol: {
2069+
case Component::Kind::OutOfLineBaseProtocol: {
20702070
auto conformance = sourceKey.Kind.getProtocolConformance();
20712071
auto protocol = conformance.getRequirement();
2072-
auto inheritedProtocol =
2073-
protocol->getInheritedProtocols()[component.getPrimaryIndex()];
2072+
auto &pi = IGF.IGM.getProtocolInfo(protocol);
2073+
2074+
auto &entry = pi.getWitnessEntries()[component.getPrimaryIndex()];
2075+
assert(entry.isOutOfLineBase());
2076+
auto inheritedProtocol = entry.getBase();
20742077

20752078
sourceKey.Kind =
20762079
LocalTypeDataKind::forAbstractProtocolWitnessTable(inheritedProtocol);
@@ -2084,14 +2087,11 @@ llvm::Value *MetadataPath::followComponent(IRGenFunction &IGF,
20842087
}
20852088

20862089
if (source) {
2087-
auto &pi = IGF.IGM.getProtocolInfo(protocol);
2088-
auto index = pi.getBaseIndex(inheritedProtocol);
2089-
if (!index.isPrefix()) {
2090-
source = emitInvariantLoadOfOpaqueWitness(IGF, source, index);
2091-
source = IGF.Builder.CreateBitCast(source, IGF.IGM.WitnessTablePtrTy);
2092-
setProtocolWitnessTableName(IGF.IGM, source, sourceKey.Type,
2093-
inheritedProtocol);
2094-
}
2090+
WitnessIndex index(component.getPrimaryIndex(), /*prefix*/ false);
2091+
source = emitInvariantLoadOfOpaqueWitness(IGF, source, index);
2092+
source = IGF.Builder.CreateBitCast(source, IGF.IGM.WitnessTablePtrTy);
2093+
setProtocolWitnessTableName(IGF.IGM, source, sourceKey.Type,
2094+
inheritedProtocol);
20952095
}
20962096
return source;
20972097
}
@@ -2113,8 +2113,8 @@ void MetadataPath::print(llvm::raw_ostream &out) const {
21132113
if (i != Path.begin()) out << ".";
21142114
auto component = *i;
21152115
switch (component.getKind()) {
2116-
case Component::Kind::InheritedProtocol:
2117-
out << "inherited_protocol[" << component.getPrimaryIndex() << "]";
2116+
case Component::Kind::OutOfLineBaseProtocol:
2117+
out << "out_of_line_base_protocol[" << component.getPrimaryIndex() << "]";
21182118
break;
21192119
case Component::Kind::NominalTypeArgument:
21202120
out << "nominal_type_argument[" << component.getPrimaryIndex() << "]";

lib/IRGen/MetadataPath.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include "swift/Basic/EncodedSequence.h"
2222
#include "swift/Reflection/MetadataSource.h"
23+
#include "WitnessIndex.h"
2324
#include "IRGen.h"
2425

2526
namespace llvm {
@@ -45,8 +46,8 @@ class MetadataPath {
4546
// Some components carry indices.
4647
// P means the primary index.
4748

48-
/// Base protocol P of a protocol.
49-
InheritedProtocol,
49+
/// Base protocol of a protocol. P is the WitnessIndex.
50+
OutOfLineBaseProtocol,
5051

5152
/// Witness table at requirement index P of a generic nominal type.
5253
NominalTypeArgumentConformance,
@@ -95,7 +96,7 @@ class MetadataPath {
9596
/// Return an abstract measurement of the cost of this component.
9697
OperationCost cost() const {
9798
switch (getKind()) {
98-
case Kind::InheritedProtocol:
99+
case Kind::OutOfLineBaseProtocol:
99100
case Kind::NominalTypeArgumentConformance:
100101
case Kind::NominalTypeArgument:
101102
case Kind::NominalParent:
@@ -155,12 +156,12 @@ class MetadataPath {
155156
index));
156157
}
157158

158-
/// Add a step to this path which gets the kth inherited protocol from a
159-
/// witness table.
160-
///
161-
/// k is computed including protocols which do not have witness tables.
162-
void addInheritedProtocolComponent(unsigned index) {
163-
Path.push_back(Component(Component::Kind::InheritedProtocol, index));
159+
/// Add a step to this path which gets the inherited protocol at
160+
/// a particular witness index.
161+
void addInheritedProtocolComponent(WitnessIndex index) {
162+
assert(!index.isPrefix());
163+
Path.push_back(Component(Component::Kind::OutOfLineBaseProtocol,
164+
index.getValue()));
164165
}
165166

166167
/// Return an abstract measurement of the cost of this path.

lib/IRGen/ProtocolInfo.h

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/AST/Decl.h"
2222

2323
#include "ValueWitness.h"
24+
#include "WitnessIndex.h"
2425
#include "llvm/ADT/DenseMap.h"
2526
#include "llvm/ADT/ArrayRef.h"
2627
#include "llvm/Support/TrailingObjects.h"
@@ -36,21 +37,6 @@ namespace irgen {
3637
class IRGenModule;
3738
class TypeInfo;
3839

39-
/// A class which encapsulates an index into a witness table.
40-
class WitnessIndex {
41-
unsigned Value : 31;
42-
unsigned IsPrefix : 1;
43-
public:
44-
WitnessIndex() = default;
45-
WitnessIndex(ValueWitness index) : Value(unsigned(index)) {}
46-
explicit WitnessIndex(unsigned index, bool isPrefix)
47-
: Value(index), IsPrefix(isPrefix) {}
48-
49-
unsigned getValue() const { return Value; }
50-
51-
bool isPrefix() const { return IsPrefix; }
52-
};
53-
5440
/// A witness to a specific element of a protocol. Every
5541
/// ProtocolTypeInfo stores one of these for each requirement
5642
/// introduced by the protocol.
@@ -195,48 +181,74 @@ class ProtocolInfo final :
195181
return NumTableEntries;
196182
}
197183

184+
/// Return all of the entries in this protocol witness table.
185+
///
186+
/// The addresses of the entries in this array can be passed to
187+
/// getBaseWitnessIndex/getNonBaseWitnessIndex, below.
198188
ArrayRef<WitnessTableEntry> getWitnessEntries() const {
199189
return {getTrailingObjects<WitnessTableEntry>(), NumTableEntries};
200190
}
201191

202-
WitnessIndex getBaseIndex(ProtocolDecl *protocol) const {
192+
/// Given the address of a witness entry from this PI for a base protocol
193+
/// conformance, return its witness index.
194+
WitnessIndex getBaseWitnessIndex(const WitnessTableEntry *witness) const {
195+
assert(witness && witness->isBase());
196+
auto entries = getWitnessEntries();
197+
assert(entries.begin() <= witness && witness < entries.end() &&
198+
"argument witness entry does not belong to this ProtocolInfo");
199+
if (witness->isOutOfLineBase()) {
200+
return WitnessIndex(witness - entries.begin(), false);
201+
} else {
202+
return WitnessIndex(0, true);
203+
}
204+
}
205+
206+
/// Given the address of a witness entry from this PI for a non-base
207+
/// witness, return its witness index.
208+
WitnessIndex getNonBaseWitnessIndex(const WitnessTableEntry *witness) const {
209+
assert(witness && !witness->isBase());
203210
auto entries = getWitnessEntries();
204-
for (auto &witness : entries) {
205-
if (witness.matchesBase(protocol)) {
206-
if (witness.isOutOfLineBase()) {
207-
return WitnessIndex(&witness - entries.begin(), false);
208-
} else {
209-
return WitnessIndex(0, true);
210-
}
211-
}
211+
assert(entries.begin() <= witness && witness < entries.end());
212+
return WitnessIndex(witness - entries.begin(), false);
213+
}
214+
215+
/// Return the witness index for the protocol conformance pointer
216+
/// for the given base protocol requirement.
217+
WitnessIndex getBaseIndex(ProtocolDecl *protocol) const {
218+
for (auto &witness : getWitnessEntries()) {
219+
if (witness.matchesBase(protocol))
220+
return getBaseWitnessIndex(&witness);
212221
}
213222
llvm_unreachable("didn't find entry for base");
214223
}
215224

225+
/// Return the witness index for the witness function for the given
226+
/// function requirement.
216227
WitnessIndex getFunctionIndex(AbstractFunctionDecl *function) const {
217-
auto entries = getWitnessEntries();
218-
for (auto &witness : entries) {
228+
for (auto &witness : getWitnessEntries()) {
219229
if (witness.matchesFunction(function))
220-
return WitnessIndex(&witness - entries.begin(), false);
230+
return getNonBaseWitnessIndex(&witness);
221231
}
222232
llvm_unreachable("didn't find entry for function");
223233
}
224234

235+
/// Return the witness index for the type metadata access function
236+
/// for the given associated type.
225237
WitnessIndex getAssociatedTypeIndex(AssociatedTypeDecl *assocType) const {
226-
auto entries = getWitnessEntries();
227-
for (auto &witness : entries) {
238+
for (auto &witness : getWitnessEntries()) {
228239
if (witness.matchesAssociatedType(assocType))
229-
return WitnessIndex(&witness - entries.begin(), false);
240+
return getNonBaseWitnessIndex(&witness);
230241
}
231242
llvm_unreachable("didn't find entry for associated type");
232243
}
233244

245+
/// Return the witness index for the protocol witness table access
246+
/// function for the given associated protocol conformance.
234247
WitnessIndex getAssociatedConformanceIndex(CanType path,
235248
ProtocolDecl *requirement) const {
236-
auto entries = getWitnessEntries();
237-
for (auto &witness : entries) {
249+
for (auto &witness : getWitnessEntries()) {
238250
if (witness.matchesAssociatedConformance(path, requirement))
239-
return WitnessIndex(&witness - entries.begin(), false);
251+
return getNonBaseWitnessIndex(&witness);
240252
}
241253
llvm_unreachable("didn't find entry for associated conformance");
242254
}

lib/IRGen/WitnessIndex.h

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//===--- WitnessIndex.h - Index into a witness table ------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines the WitnessIndex type, used for drilling into a
14+
// protocol witness table or value witness table.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
18+
#ifndef SWIFT_IRGEN_WITNESSINDEX_H
19+
#define SWIFT_IRGEN_WITNESSINDEX_H
20+
21+
#include "ValueWitness.h"
22+
23+
namespace swift {
24+
namespace irgen {
25+
26+
/// A class which encapsulates an index into a witness table.
27+
class WitnessIndex {
28+
unsigned Value : 31;
29+
unsigned IsPrefix : 1;
30+
public:
31+
WitnessIndex() = default;
32+
WitnessIndex(ValueWitness index) : Value(unsigned(index)) {}
33+
explicit WitnessIndex(unsigned index, bool isPrefix)
34+
: Value(index), IsPrefix(isPrefix) {}
35+
36+
unsigned getValue() const { return Value; }
37+
38+
bool isPrefix() const { return IsPrefix; }
39+
};
40+
41+
} // end namespace irgen
42+
} // end namespace swift
43+
44+
#endif

0 commit comments

Comments
 (0)