Skip to content

Commit 36f2eb1

Browse files
authored
Merge pull request #62515 from slavapestov/irgen-generic-requirement
IRGen: Refactor GenericRequirement
2 parents 1ca373a + 0c3a9d8 commit 36f2eb1

24 files changed

+275
-149
lines changed

include/swift/AST/GenericRequirement.h

Lines changed: 0 additions & 51 deletions
This file was deleted.
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
//===--- GenericRequirement.h - Generic requirement -------------*- 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+
#ifndef SWIFT_AST_GENERIC_REQUIREMENT_H
14+
#define SWIFT_AST_GENERIC_REQUIREMENT_H
15+
16+
#include "swift/AST/Decl.h"
17+
#include "swift/AST/Type.h"
18+
#include "llvm/Support/raw_ostream.h"
19+
20+
namespace swift {
21+
22+
class ProtocolDecl;
23+
24+
/// The three kinds of entities passed in the runtime calling convention for
25+
/// generic code: pack shapes, type metadata, and witness tables.
26+
///
27+
/// A pack shape describes an equivalence class of type parameter packs; the
28+
/// runtime value is a single integer, which is the length of the pack.
29+
///
30+
/// Type metadata is emitted for each reduced generic parameter (that is,
31+
/// not same-type constrained to another generic parameter or concrete type).
32+
///
33+
/// A witness table is emitted for each conformance requirement in the
34+
/// generic signature.
35+
class GenericRequirement {
36+
public:
37+
enum class Kind: uint8_t {
38+
Shape,
39+
Metadata,
40+
WitnessTable
41+
};
42+
43+
private:
44+
Kind kind;
45+
CanType type;
46+
ProtocolDecl *proto;
47+
48+
GenericRequirement(Kind kind, CanType type, ProtocolDecl *proto)
49+
: kind(kind), type(type), proto(proto) {}
50+
51+
public:
52+
Kind getKind() const {
53+
return kind;
54+
}
55+
56+
CanType getTypeParameter() const {
57+
return type;
58+
}
59+
60+
ProtocolDecl *getProtocol() const {
61+
return proto;
62+
}
63+
64+
bool isShape() const {
65+
return kind == Kind::Shape;
66+
}
67+
68+
static GenericRequirement forShape(CanType type) {
69+
assert(type->isParameterPack());
70+
return GenericRequirement(Kind::Shape, type, nullptr);
71+
}
72+
73+
bool isMetadata() const {
74+
return kind == Kind::Metadata;
75+
}
76+
77+
static GenericRequirement forMetadata(CanType type) {
78+
return GenericRequirement(Kind::Metadata, type, nullptr);
79+
}
80+
81+
bool isWitnessTable() const {
82+
return kind == Kind::WitnessTable;
83+
}
84+
85+
static GenericRequirement forWitnessTable(CanType type, ProtocolDecl *proto) {
86+
assert(proto != nullptr);
87+
return GenericRequirement(Kind::WitnessTable, type, proto);
88+
}
89+
90+
void dump(llvm::raw_ostream &out) const {
91+
switch (kind) {
92+
case Kind::Shape:
93+
out << "shape: " << type;
94+
break;
95+
case Kind::Metadata:
96+
out << "metadata: " << type;
97+
break;
98+
case Kind::WitnessTable:
99+
out << "witness_table: " << type << " : " << proto->getName();
100+
break;
101+
}
102+
}
103+
};
104+
105+
} // end namespace swift
106+
107+
namespace llvm {
108+
template <> struct DenseMapInfo<swift::GenericRequirement> {
109+
using GenericRequirement = swift::GenericRequirement;
110+
using CanTypeInfo = llvm::DenseMapInfo<swift::CanType>;
111+
static GenericRequirement getEmptyKey() {
112+
return GenericRequirement::forMetadata(CanTypeInfo::getEmptyKey());
113+
}
114+
static GenericRequirement getTombstoneKey() {
115+
return GenericRequirement::forMetadata(CanTypeInfo::getTombstoneKey());
116+
}
117+
static llvm::hash_code getHashValue(GenericRequirement req) {
118+
return hash_combine(CanTypeInfo::getHashValue(req.getTypeParameter()),
119+
hash_value(req.getProtocol()));
120+
}
121+
static bool isEqual(GenericRequirement lhs, GenericRequirement rhs) {
122+
return (lhs.getKind() == rhs.getKind() &&
123+
lhs.getTypeParameter() == rhs.getTypeParameter() &&
124+
lhs.getProtocol() == rhs.getProtocol());
125+
}
126+
};
127+
} // end namespace llvm
128+
129+
#endif // SWIFT_AST_GENERIC_REQUIREMENT_H

include/swift/IRGen/IRABIDetailsProvider.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@
1414
#define SWIFT_IRGEN_IRABIDETAILSPROVIDER_H
1515

1616
#include "swift/AST/Decl.h"
17-
#include "swift/AST/GenericRequirement.h"
1817
#include "swift/AST/Type.h"
1918
#include "swift/AST/Types.h"
19+
#include "swift/IRGen/GenericRequirement.h"
2020
#include "clang/AST/CharUnits.h"
2121
#include "llvm/ADT/MapVector.h"
2222
#include "llvm/ADT/Optional.h"

lib/IRGen/EntryPointArgumentEmission.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class Value;
1818

1919
namespace swift {
2020

21-
struct GenericRequirement;
21+
class GenericRequirement;
2222
class SILArgument;
2323

2424
namespace irgen {

lib/IRGen/Fulfillment.cpp

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ bool FulfillmentMap::searchTypeMetadata(IRGenModule &IGM, CanType type,
150150
}
151151

152152
// Add the fulfillment.
153-
hadFulfillment |= addFulfillment({type, nullptr},
153+
hadFulfillment |= addFulfillment(GenericRequirement::forMetadata(type),
154154
source, std::move(path), metadataState);
155155
return hadFulfillment;
156156
}
@@ -251,8 +251,9 @@ bool FulfillmentMap::searchWitnessTable(
251251
// If we're not limiting the set of interesting conformances, or if
252252
// this is an interesting conformance, record it.
253253
if (!interestingConformances || interestingConformances->count(protocol)) {
254-
hadFulfillment |= addFulfillment({type, protocol}, source,
255-
std::move(path), MetadataState::Complete);
254+
hadFulfillment |= addFulfillment(
255+
GenericRequirement::forWitnessTable(type, protocol), source,
256+
std::move(path), MetadataState::Complete);
256257
}
257258

258259
return hadFulfillment;
@@ -315,7 +316,7 @@ bool FulfillmentMap::searchNominalTypeMetadata(IRGenModule &IGM,
315316
}
316317

317318
/// Testify that there's a fulfillment at the given path.
318-
bool FulfillmentMap::addFulfillment(FulfillmentKey key,
319+
bool FulfillmentMap::addFulfillment(GenericRequirement key,
319320
unsigned source,
320321
MetadataPath &&path,
321322
MetadataState metadataState) {
@@ -360,10 +361,8 @@ static StringRef getStateName(MetadataState state) {
360361
void FulfillmentMap::dump() const {
361362
auto &out = llvm::errs();
362363
for (auto &entry : Fulfillments) {
363-
out << "(" << entry.first.first;
364-
if (auto proto = entry.first.second) {
365-
out << ", " << proto->getNameStr();
366-
}
364+
out << "(";
365+
entry.first.dump(out);
367366
out << ") => " << getStateName(entry.second.getState())
368367
<< " at sources[" << entry.second.SourceIndex
369368
<< "]." << entry.second.Path << "\n";

lib/IRGen/Fulfillment.h

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "llvm/ADT/DenseMap.h"
2222
#include "swift/AST/Types.h"
2323
#include "swift/AST/GenericSignature.h"
24+
#include "swift/IRGen/GenericRequirement.h"
2425
#include "MetadataPath.h"
2526

2627
namespace swift {
@@ -48,9 +49,7 @@ struct Fulfillment {
4849
};
4950

5051
class FulfillmentMap {
51-
using FulfillmentKey = std::pair<Type, ProtocolDecl*>;
52-
53-
llvm::DenseMap<FulfillmentKey, Fulfillment> Fulfillments;
52+
llvm::DenseMap<GenericRequirement, Fulfillment> Fulfillments;
5453

5554
public:
5655
struct InterestingKeysCallback {
@@ -115,25 +114,28 @@ class FulfillmentMap {
115114
///
116115
/// \return true if the fulfillment was added, which won't happen if there's
117116
/// already a fulfillment that was at least as good
118-
bool addFulfillment(FulfillmentKey key, unsigned source,
117+
bool addFulfillment(GenericRequirement key, unsigned source,
119118
MetadataPath &&path, MetadataState state);
120119

121-
const Fulfillment *getTypeMetadata(CanType type) const {
122-
auto it = Fulfillments.find({type, nullptr});
120+
const Fulfillment *getFulfillment(GenericRequirement key) const {
121+
auto it = Fulfillments.find(key);
123122
if (it != Fulfillments.end()) {
124123
return &it->second;
125124
} else {
126125
return nullptr;
127126
}
128127
}
129128

129+
const Fulfillment *getShape(CanType type) const {
130+
return getFulfillment(GenericRequirement::forShape(type));
131+
}
132+
133+
const Fulfillment *getTypeMetadata(CanType type) const {
134+
return getFulfillment(GenericRequirement::forMetadata(type));
135+
}
136+
130137
const Fulfillment *getWitnessTable(CanType type, ProtocolDecl *proto) const {
131-
auto it = Fulfillments.find({type, proto});
132-
if (it != Fulfillments.end()) {
133-
return &it->second;
134-
} else {
135-
return nullptr;
136-
}
138+
return getFulfillment(GenericRequirement::forWitnessTable(type, proto));
137139
}
138140

139141
void dump() const;

lib/IRGen/GenArchetype.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -435,14 +435,15 @@ withOpaqueTypeGenericArgs(IRGenFunction &IGF,
435435
enumerateGenericSignatureRequirements(
436436
opaqueDecl->getGenericSignature().getCanonicalSignature(),
437437
[&](GenericRequirement reqt) {
438-
auto ty = reqt.TypeParameter.subst(archetype->getSubstitutions())
438+
auto ty = reqt.getTypeParameter().subst(archetype->getSubstitutions())
439439
->getReducedType(opaqueDecl->getGenericSignature());
440-
if (reqt.Protocol) {
440+
if (reqt.isWitnessTable()) {
441441
auto ref =
442-
ProtocolConformanceRef(reqt.Protocol)
443-
.subst(reqt.TypeParameter, archetype->getSubstitutions());
442+
ProtocolConformanceRef(reqt.getProtocol())
443+
.subst(reqt.getTypeParameter(), archetype->getSubstitutions());
444444
args.push_back(emitWitnessTableRef(IGF, ty, ref));
445445
} else {
446+
assert(reqt.isMetadata());
446447
args.push_back(IGF.emitAbstractTypeMetadataRef(ty));
447448
}
448449
types.push_back(args.back()->getType());

lib/IRGen/GenKeyPath.cpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -886,7 +886,7 @@ emitKeyPathComponent(IRGenModule &IGM,
886886
enumerateGenericSignatureRequirements(
887887
componentCanSig, [&](GenericRequirement reqt) {
888888
auto substType =
889-
reqt.TypeParameter.subst(subs)->getCanonicalType();
889+
reqt.getTypeParameter().subst(subs)->getCanonicalType();
890890

891891
// FIXME: This seems wrong. We used to just mangle opened archetypes as
892892
// their interface type. Let's make that explicit now.
@@ -896,14 +896,17 @@ emitKeyPathComponent(IRGenModule &IGM,
896896
return None;
897897
})->getCanonicalType();
898898

899-
if (!reqt.Protocol) {
899+
if (reqt.isMetadata()) {
900900
// Type requirement.
901901
externalSubArgs.push_back(emitMetadataTypeRefForKeyPath(
902902
IGM, substType, componentCanSig));
903903
} else {
904+
assert(reqt.isWitnessTable());
905+
904906
// Protocol requirement.
905907
auto conformance = subs.lookupConformance(
906-
reqt.TypeParameter->getCanonicalType(), reqt.Protocol);
908+
reqt.getTypeParameter()->getCanonicalType(),
909+
reqt.getProtocol());
907910
externalSubArgs.push_back(IGM.emitWitnessTableRefString(
908911
substType, conformance,
909912
genericEnv ? genericEnv->getGenericSignature() : nullptr,

lib/IRGen/GenMeta.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4250,20 +4250,21 @@ namespace {
42504250
}
42514251

42524252
void addGenericArgument(GenericRequirement requirement) {
4253-
auto t = requirement.TypeParameter.subst(genericSubstitutions());
4253+
auto t = requirement.getTypeParameter().subst(genericSubstitutions());
42544254
ConstantReference ref = IGM.getAddrOfTypeMetadata(
42554255
CanType(t), SymbolReferenceKind::Relative_Direct);
42564256
this->B.add(ref.getDirectValue());
42574257
}
42584258

42594259
void addGenericWitnessTable(GenericRequirement requirement) {
42604260
auto conformance = genericSubstitutions().lookupConformance(
4261-
requirement.TypeParameter->getCanonicalType(), requirement.Protocol);
4261+
requirement.getTypeParameter()->getCanonicalType(),
4262+
requirement.getProtocol());
42624263
ProtocolConformance *concreteConformance = conformance.getConcrete();
42634264

42644265
llvm::Constant *addr;
42654266

4266-
Type argument = requirement.TypeParameter.subst(genericSubstitutions());
4267+
Type argument = requirement.getTypeParameter().subst(genericSubstitutions());
42674268
auto argumentNominal = argument->getAnyNominal();
42684269
if (argumentNominal && argumentNominal->isGenericContext()) {
42694270
// TODO: Statically specialize the witness table pattern for t's

0 commit comments

Comments
 (0)