Skip to content

Commit 757ebe2

Browse files
committed
Future-proof the mangling of invertible protocols
Invertible protocols are currently always mangled with `Ri`, followed by a single letter for each invertible protocol (e.g., `c` and `e` for `Copyable` and `Escapable`, respectively), followed by the generic parameter index. However, this requires that we extend the mangling for any future invertible protocols, which mean they won't be backward compatible. Replace this mangling with one that mangles the bit # for the invertible protocol, e.g., `Ri_` (followed by the generic parameter index) is bit 0, which is `Copyable`. `Ri0_` (then generic parameter index) is bit 1, which is `Escapable`. This allows us to round-trip through mangled names for any invertible protocol, without any knowledge of what the invertible protocol is, providing forward compatibility. The same forward compatibility is present in all metadata and the runtime, allowing us to add more invertible protocols in the future without updating any of them, and also allowing backward compatibility. Only the demangling to human-readable strings maps the bit numbers back to their names, and there's a fallback printing with just the bit number when appropriate. Also generalize the mangling a bit to allow for mangling of invertible requirements on associated types, e.g., `S.Sequence: ~Copyable`. This is currently unsupported by the compiler or runtime, but that may change, and it was easy enough to finish off the mangling work for it.
1 parent 220392b commit 757ebe2

27 files changed

+251
-233
lines changed

docs/ABI/Mangling.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,9 +1011,6 @@ now codified into the ABI; the index 0 is therefore reserved.
10111011

10121012
generic-param-pack-marker ::= 'Rv' GENERIC_PARAM-INDEX // generic parameter pack marker
10131013

1014-
INVERTIBLE-KIND ::= 'c' // Copyable
1015-
INVERTIBLE-KIND ::= 'e' // Escapable
1016-
10171014
GENERIC-PARAM-COUNT ::= 'z' // zero parameters
10181015
GENERIC-PARAM-COUNT ::= INDEX // N+1 parameters
10191016

@@ -1022,7 +1019,10 @@ now codified into the ABI; the index 0 is therefore reserved.
10221019
requirement ::= protocol assoc-type-list 'RP' GENERIC-PARAM-INDEX // protocol requirement on associated type at depth
10231020
requirement ::= protocol substitution 'RQ' // protocol requirement with substitution
10241021
#if SWIFT_RUNTIME_VERSION >= 6.0
1025-
requirement ::= 'Ri' INVERTIBLE-KIND GENERIC-PARAM-INDEX // inverse requirement
1022+
requirement ::= 'Ri' INDEX GENERIC-PARAM-INDEX // inverse requirement on generic parameter where INDEX is the bit number
1023+
requirement ::= substitution 'RI' INDEX // inverse requirement with substitution
1024+
requirement ::= assoc-type-name 'Rj' INDEX GENERIC-PARAM-INDEX // inverse requirement on associated type
1025+
requirement ::= assoc-type-list 'RJ' INDEX GENERIC-PARAM-INDEX // inverse requirement on associated type at depth
10261026
#endif
10271027
requirement ::= type 'Rb' GENERIC-PARAM-INDEX // base class requirement
10281028
requirement ::= type assoc-type-name 'Rc' GENERIC-PARAM-INDEX // base class requirement on associated type

include/swift/ABI/SuppressibleProtocols.def

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,13 @@
1919
// Name: The name of the protocol, e.g., Copyable
2020
// Bit: The bit in the set bitset of suppressible protocols that is used
2121
// to indicate this.
22-
// MangleChar: The character used for the name mangling to refer to this
23-
// protocol.
2422
//===----------------------------------------------------------------------===//
2523

2624
#ifndef SUPPRESSIBLE_PROTOCOL
2725
# error Must define SUPPRESSIBLE_PROTOCOL macro before including this file
2826
#endif
2927

30-
SUPPRESSIBLE_PROTOCOL(Copyable, 0, 'c')
31-
SUPPRESSIBLE_PROTOCOL(Escapable, 1, 'e')
28+
SUPPRESSIBLE_PROTOCOL(Copyable, 0)
29+
SUPPRESSIBLE_PROTOCOL(Escapable, 1)
3230

3331
#undef SUPPRESSIBLE_PROTOCOL

include/swift/ABI/SuppressibleProtocols.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace swift {
2626
/// Describes a "suppressible" protocol, such as Copyable, which is assumed to
2727
/// hold for all types unless explicitly suppressed.
2828
enum class SuppressibleProtocolKind : uint8_t {
29-
#define SUPPRESSIBLE_PROTOCOL(Name, Bit, MangleChar) Name = Bit,
29+
#define SUPPRESSIBLE_PROTOCOL(Name, Bit) Name = Bit,
3030
#include "swift/ABI/SuppressibleProtocols.def"
3131
};
3232

@@ -72,7 +72,7 @@ class SuppressibleProtocolSet {
7272
/// Clear out all of the protocols from the set.
7373
void clear() { bits = 0; }
7474

75-
#define SUPPRESSIBLE_PROTOCOL(Name, Bit, MangleChar) \
75+
#define SUPPRESSIBLE_PROTOCOL(Name, Bit) \
7676
bool contains##Name() const { \
7777
return contains(SuppressibleProtocolKind::Name); \
7878
}
@@ -82,7 +82,7 @@ class SuppressibleProtocolSet {
8282
/// protocols.
8383
static SuppressibleProtocolSet allKnown() {
8484
SuppressibleProtocolSet result;
85-
#define SUPPRESSIBLE_PROTOCOL(Name, Bit, MangleChar) \
85+
#define SUPPRESSIBLE_PROTOCOL(Name, Bit) \
8686
result.insert(SuppressibleProtocolKind::Name);
8787
#include "swift/ABI/SuppressibleProtocols.def"
8888
return result;
@@ -213,7 +213,7 @@ class SuppressibleProtocolSet {
213213
static inline const char *
214214
getSuppressibleProtocolKindName(SuppressibleProtocolKind kind) {
215215
switch (kind) {
216-
#define SUPPRESSIBLE_PROTOCOL(Name, Bit, MangleChar) \
216+
#define SUPPRESSIBLE_PROTOCOL(Name, Bit) \
217217
case SuppressibleProtocolKind::Name: return #Name;
218218
#include "swift/ABI/SuppressibleProtocols.def"
219219
}

include/swift/AST/ASTMangler.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,24 @@ class ASTMangler : public Mangler {
596596
GenericSignature contextSig,
597597
BaseEntitySignature &base);
598598

599+
/// Describes how the subject of a requirement was mangled.
600+
struct RequirementSubject {
601+
enum Kind {
602+
GenericParameter,
603+
AssociatedType,
604+
AssociatedTypeAtDepth,
605+
Substitution
606+
} kind;
607+
608+
/// Generic parameter at the base, if there is one. Valid for everything
609+
/// except Substitution subjects.
610+
GenericTypeParamType *gpBase = nullptr;
611+
};
612+
613+
/// Append the subject of a generic requirement and state what kind it is.
614+
RequirementSubject appendRequirementSubject(
615+
CanType subjectType, GenericSignature sig);
616+
599617
/// Append a requirement to the mangling.
600618
///
601619
/// \param reqt The requirement to mangle

include/swift/AST/InvertibleProtocolKind.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,11 @@
1919
#define SWIFT_AST_INVERTIBLEPROTOCOLKIND_H
2020

2121
#include <stdint.h>
22+
#include <swift/ABI/SuppressibleProtocols.h>
2223

2324
namespace swift {
2425

25-
enum class InvertibleProtocolKind : uint8_t {
26-
#define INVERTIBLE_PROTOCOL_WITH_NAME(Id, Name) Id,
27-
#include "swift/AST/KnownProtocols.def"
28-
};
29-
26+
typedef SuppressibleProtocolKind InvertibleProtocolKind;
3027

3128
} // end namespace swift
3229

include/swift/AST/KnownProtocols.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ PROTOCOL(AsyncIteratorProtocol)
136136

137137
PROTOCOL(FloatingPoint)
138138

139-
#define SUPPRESSIBLE_PROTOCOL(Name, Bit, MangleChar) \
139+
#define SUPPRESSIBLE_PROTOCOL(Name, Bit) \
140140
INVERTIBLE_PROTOCOL_WITH_NAME(Name, #Name)
141141
#include "swift/ABI/SuppressibleProtocols.def"
142142

include/swift/AST/KnownProtocols.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,6 @@ KnownProtocolKind getKnownProtocolKind(InvertibleProtocolKind ip);
7373
void simple_display(llvm::raw_ostream &out,
7474
const InvertibleProtocolKind &value);
7575

76-
SuppressibleProtocolKind asSuppressible(InvertibleProtocolKind kind);
77-
InvertibleProtocolKind asInvertible(SuppressibleProtocolKind kind);
78-
7976
} // end namespace swift
8077

8178
#endif

include/swift/Demangling/TypeDecoder.h

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -456,38 +456,15 @@ void decodeRequirement(
456456
} else if (child->getKind() ==
457457
Demangle::Node::Kind::DependentGenericInverseConformanceRequirement) {
458458
// Type child
459-
auto constraintNode = child->getChild(1);
459+
auto constraintNode = child->getChild(0);
460460
if (constraintNode->getKind() != Demangle::Node::Kind::Type ||
461461
constraintNode->getNumChildren() != 1)
462462
return;
463463

464-
// Protocol child
465-
auto protocolNode = constraintNode->getChild(0);
466-
if (protocolNode->getKind() != Demangle::Node::Kind::Protocol ||
467-
protocolNode->getNumChildren() != 2)
468-
return;
469-
470-
auto moduleNode = protocolNode->getChild(0);
471-
if (moduleNode->getKind() != Demangle::Node::Kind::Module ||
472-
moduleNode->getText() != "Swift")
473-
return;
474-
475-
auto protocolNameNode = protocolNode->getChild(1);
476-
if (protocolNameNode->getKind() != Demangle::Node::Kind::Identifier)
477-
return;
478-
479-
auto protocolName = protocolNameNode->getText();
480-
using OptInvertibleKind = std::optional<InvertibleProtocolKind>;
481-
auto protocolKind = llvm::StringSwitch<OptInvertibleKind>(protocolName)
482-
#define INVERTIBLE_PROTOCOL_WITH_NAME(Id, Name) \
483-
.Case(Name, InvertibleProtocolKind::Id)
484-
#include "swift/AST/KnownProtocols.def"
485-
.Default(std::nullopt);
486-
if (!protocolKind)
487-
return;
488-
464+
auto protocolKind =
465+
static_cast<SuppressibleProtocolKind>(child->getChild(1)->getIndex());
489466
inverseRequirements.push_back(
490-
Builder.createInverseRequirement(subjectType, *protocolKind));
467+
Builder.createInverseRequirement(subjectType, protocolKind));
491468
continue;
492469
}
493470

lib/AST/ASTContext.cpp

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -132,26 +132,10 @@ void swift::simple_display(llvm::raw_ostream &out,
132132

133133
// Metadata stores a 16-bit field for suppressible protocols. Trigger a build
134134
// error when we assign the 15th bit so we can think about what to do.
135-
#define SUPPRESSIBLE_PROTOCOL(Name, Bit, MangleChar) \
135+
#define SUPPRESSIBLE_PROTOCOL(Name, Bit) \
136136
static_assert(Bit < 15);
137137
#include "swift/ABI/SuppressibleProtocols.def"
138138

139-
SuppressibleProtocolKind swift::asSuppressible(InvertibleProtocolKind kind) {
140-
switch (kind) {
141-
#define SUPPRESSIBLE_PROTOCOL(Name, Bit, MangleChar) \
142-
case InvertibleProtocolKind::Name: return SuppressibleProtocolKind::Name;
143-
#include "swift/ABI/SuppressibleProtocols.def"
144-
}
145-
}
146-
147-
InvertibleProtocolKind swift::asInvertible(SuppressibleProtocolKind kind) {
148-
switch (kind) {
149-
#define SUPPRESSIBLE_PROTOCOL(Name, Bit, MangleChar) \
150-
case SuppressibleProtocolKind::Name: return InvertibleProtocolKind::Name;
151-
#include "swift/ABI/SuppressibleProtocols.def"
152-
}
153-
}
154-
155139
namespace {
156140
enum class SearchPathKind : uint8_t {
157141
Import = 1 << 0,

0 commit comments

Comments
 (0)