Skip to content

Commit e7998f1

Browse files
committed
[ABI] Record unmangled names in Swift protocol descriptors.
Rather than storing a mangled name in a Swift protocol descriptor, which encodes information that is redundant with the context of the protocol, store an unmangled name as in nominal type descriptors. Update the various places where this name is used to extract the demangle tree from the context descriptors.
1 parent a54a6d8 commit e7998f1

File tree

8 files changed

+116
-83
lines changed

8 files changed

+116
-83
lines changed

docs/ABI/TypeMetadata.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -427,8 +427,7 @@ as follows:
427427
* **Bit 1** indicates that the protocol is **resilient**.
428428
* **Bits 2-7** indicate specify the **special protocol kind**. Only one
429429
special protocol kind is defined: the `Error` protocol has value 1.
430-
- A pointer to the **name** of the protocol. FIXME: The name is currently
431-
mangles, but will change to the (unmangled) name.
430+
- A pointer to the **name** of the protocol.
432431
- The number of generic requirements within the **requirement signature** of
433432
the protocol. The generic requirements themselves follow the fixed part
434433
of the protocol descriptor.

include/swift/Remote/MetadataReader.h

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -383,28 +383,9 @@ class MetadataReader {
383383
}
384384
#endif
385385

386-
// Read the protocol descriptor.
387-
ContextDescriptorRef descriptor
388-
= readContextDescriptor(ProtocolAddress.getSwiftProtocol());
389-
if (!descriptor)
390-
return BuiltType();
391-
392-
auto protocolBuffer =
393-
reinterpret_cast<const TargetProtocolDescriptor<Runtime> *>
394-
(descriptor.getLocalBuffer());
395-
396-
std::string mangledNameStr;
397-
auto nameAddress = resolveRelativeField(descriptor,
398-
protocolBuffer->Name);
399-
if (!Reader->readString(RemoteAddress(nameAddress),
400-
mangledNameStr))
401-
return BuiltType();
402-
403-
StringRef mangledName =
404-
Demangle::dropSwiftManglingPrefix(mangledNameStr);
405-
406-
Demangle::Context DCtx;
407-
auto Demangled = DCtx.demangleTypeAsNode(mangledName);
386+
Demangle::Demangler Dem;
387+
auto Demangled = readDemanglingForContextDescriptor(
388+
ProtocolAddress.getSwiftProtocol(), Dem);
408389
if (!Demangled)
409390
return BuiltType();
410391

@@ -1218,7 +1199,17 @@ class MetadataReader {
12181199
nodeKind = Demangle::Node::Kind::Enum;
12191200
isTypeContext = true;
12201201
break;
1202+
case ContextDescriptorKind::Protocol: {
1203+
auto protocolBuffer =
1204+
reinterpret_cast<const TargetProtocolDescriptor<Runtime> *>
1205+
(parent.getLocalBuffer());
1206+
auto nameAddress = resolveRelativeField(parent, protocolBuffer->Name);
1207+
if (!Reader->readString(RemoteAddress(nameAddress), nodeName))
1208+
return nullptr;
12211209

1210+
nodeKind = Demangle::Node::Kind::Protocol;
1211+
break;
1212+
}
12221213
case ContextDescriptorKind::Extension:
12231214
// TODO: Remangle something about the extension context here.
12241215
return nullptr;

lib/IRGen/GenMeta.cpp

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -514,15 +514,7 @@ namespace {
514514
}
515515

516516
void addName() {
517-
// Include the _Tt prefix. The runtime is currently depending on this
518-
// so the naming scheme matches up with @objc protocols.
519-
// FIXME: We want to put the bare name here, because the context
520-
// information is enough for us.
521-
IRGenMangler mangler;
522-
std::string Name =
523-
mangler.mangleForProtocolDescriptor(Proto->getDeclaredType());
524-
525-
auto nameStr = IGM.getAddrOfGlobalString(Name,
517+
auto nameStr = IGM.getAddrOfGlobalString(Proto->getName().str(),
526518
/*willBeRelativelyAddressed*/ true);
527519
B.addRelativeAddress(nameStr);
528520
}

stdlib/public/runtime/Demangle.cpp

Lines changed: 55 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,19 @@ swift::_buildDemanglingForContext(const ContextDescriptor *context,
122122
break;
123123
}
124124

125+
case ContextDescriptorKind::Protocol: {
126+
auto protocol = llvm::cast<ProtocolDescriptor>(component);
127+
auto name = protocol->Name.get();
128+
129+
auto protocolNode = Dem.createNode(Node::Kind::Protocol);
130+
protocolNode->addChild(node, Dem);
131+
auto nameNode = Dem.createNode(Node::Kind::Identifier, name);
132+
protocolNode->addChild(nameNode, Dem);
133+
134+
node = protocolNode;
135+
break;
136+
}
137+
125138
default:
126139
// Form a type context demangling for type contexts.
127140
if (auto type = llvm::dyn_cast<TypeContextDescriptor>(component)) {
@@ -392,37 +405,51 @@ swift::_swift_buildDemanglingForMetadata(const Metadata *type,
392405
// its canonical ordering of protocols.
393406

394407
for (auto protocol : protocols) {
395-
// The protocol name is mangled as a type symbol, with the _Tt prefix.
396-
StringRef ProtoName(protocol.getName());
397-
NodePointer protocolNode = Dem.demangleSymbol(ProtoName);
398-
399-
// ObjC protocol names aren't mangled.
400-
if (!protocolNode) {
401-
auto module = Dem.createNode(Node::Kind::Module,
402-
MANGLING_MODULE_OBJC);
403-
auto node = Dem.createNode(Node::Kind::Protocol);
404-
node->addChild(module, Dem);
405-
node->addChild(Dem.createNode(Node::Kind::Identifier, ProtoName), Dem);
406-
auto typeNode = Dem.createNode(Node::Kind::Type);
407-
typeNode->addChild(node, Dem);
408-
type_list->addChild(typeNode, Dem);
408+
#if SWIFT_OBJC_INTEROP
409+
if (protocol.isObjC()) {
410+
// The protocol name is mangled as a type symbol, with the _Tt prefix.
411+
StringRef ProtoName(protocol.getName());
412+
NodePointer protocolNode = Dem.demangleSymbol(ProtoName);
413+
414+
// ObjC protocol names aren't mangled.
415+
if (!protocolNode) {
416+
auto module = Dem.createNode(Node::Kind::Module,
417+
MANGLING_MODULE_OBJC);
418+
auto node = Dem.createNode(Node::Kind::Protocol);
419+
node->addChild(module, Dem);
420+
node->addChild(Dem.createNode(Node::Kind::Identifier, ProtoName),
421+
Dem);
422+
auto typeNode = Dem.createNode(Node::Kind::Type);
423+
typeNode->addChild(node, Dem);
424+
type_list->addChild(typeNode, Dem);
425+
continue;
426+
}
427+
428+
// Dig out the protocol node.
429+
// Global -> (Protocol|TypeMangling)
430+
protocolNode = protocolNode->getChild(0);
431+
if (protocolNode->getKind() == Node::Kind::TypeMangling) {
432+
protocolNode = protocolNode->getChild(0); // TypeMangling -> Type
433+
protocolNode = protocolNode->getChild(0); // Type -> ProtocolList
434+
protocolNode = protocolNode->getChild(0); // ProtocolList -> TypeList
435+
protocolNode = protocolNode->getChild(0); // TypeList -> Type
436+
437+
assert(protocolNode->getKind() == Node::Kind::Type);
438+
assert(protocolNode->getChild(0)->getKind() == Node::Kind::Protocol);
439+
} else {
440+
assert(protocolNode->getKind() == Node::Kind::Protocol);
441+
}
442+
443+
type_list->addChild(protocolNode, Dem);
409444
continue;
410445
}
446+
#endif
411447

412-
// Dig out the protocol node.
413-
// Global -> (Protocol|TypeMangling)
414-
protocolNode = protocolNode->getChild(0);
415-
if (protocolNode->getKind() == Node::Kind::TypeMangling) {
416-
protocolNode = protocolNode->getChild(0); // TypeMangling -> Type
417-
protocolNode = protocolNode->getChild(0); // Type -> ProtocolList
418-
protocolNode = protocolNode->getChild(0); // ProtocolList -> TypeList
419-
protocolNode = protocolNode->getChild(0); // TypeList -> Type
420-
421-
assert(protocolNode->getKind() == Node::Kind::Type);
422-
assert(protocolNode->getChild(0)->getKind() == Node::Kind::Protocol);
423-
} else {
424-
assert(protocolNode->getKind() == Node::Kind::Protocol);
425-
}
448+
auto protocolNode =
449+
_buildDemanglingForContext(protocol.getSwiftProtocol(), { }, false,
450+
Dem);
451+
if (!protocolNode)
452+
return nullptr;
426453

427454
type_list->addChild(protocolNode, Dem);
428455
}

stdlib/public/runtime/MetadataLookup.cpp

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -233,7 +233,19 @@ swift::_contextDescriptorMatchesMangling(const ContextDescriptor *context,
233233
node = node->getChild(0);
234234
break;
235235
}
236-
236+
237+
case ContextDescriptorKind::Protocol:
238+
// Match a protocol context.
239+
if (node->getKind() == Demangle::Node::Kind::Protocol) {
240+
auto proto = llvm::cast<ProtocolDescriptor>(context);
241+
auto nameNode = node->getChild(1);
242+
if (nameNode->getText() == proto->Name.get()) {
243+
node = node->getChild(0);
244+
break;
245+
}
246+
}
247+
return false;
248+
237249
default:
238250
if (auto type = llvm::dyn_cast<TypeContextDescriptor>(context)) {
239251
switch (node->getKind()) {
@@ -290,7 +302,7 @@ swift::_contextDescriptorMatchesMangling(const ContextDescriptor *context,
290302
return false;
291303

292304
}
293-
305+
294306
// We don't know about this kind of context, or it doesn't have a stable
295307
// name we can match to.
296308
return false;
@@ -445,16 +457,11 @@ void swift::swift_registerProtocols(const ProtocolRecord *begin,
445457

446458
static const ProtocolDescriptor *
447459
_searchProtocolRecords(ProtocolMetadataPrivateState &C,
448-
const llvm::StringRef protocolName){
460+
const Demangle::NodePointer &node) {
449461
for (auto &section : C.SectionsToScan.snapshot()) {
450462
for (const auto &record : section) {
451463
if (auto protocol = record.Protocol.getPointer()) {
452-
// Drop the "S$" prefix from the protocol record. It's not used in
453-
// the type itself.
454-
StringRef foundProtocolName = protocol->Name.get();
455-
assert(foundProtocolName.startswith("$S"));
456-
foundProtocolName = foundProtocolName.drop_front(2);
457-
if (foundProtocolName == protocolName)
464+
if (_contextDescriptorMatchesMangling(protocol, node))
458465
return protocol;
459466
}
460467
}
@@ -464,17 +471,35 @@ _searchProtocolRecords(ProtocolMetadataPrivateState &C,
464471
}
465472

466473
static const ProtocolDescriptor *
467-
_findProtocolDescriptor(llvm::StringRef mangledName) {
474+
_findProtocolDescriptor(const Demangle::NodePointer &node,
475+
Demangle::Demangler &Dem,
476+
std::string &mangledName) {
468477
const ProtocolDescriptor *foundProtocol = nullptr;
469478
auto &T = Protocols.get();
470479

480+
// If we have a symbolic reference to a context, resolve it immediately.
481+
NodePointer symbolicNode = node;
482+
if (symbolicNode->getKind() == Node::Kind::Type)
483+
symbolicNode = symbolicNode->getChild(0);
484+
if (symbolicNode->getKind() == Node::Kind::SymbolicReference)
485+
return cast<ProtocolDescriptor>(
486+
(const ContextDescriptor *)symbolicNode->getIndex());
487+
488+
mangledName =
489+
Demangle::mangleNode(node,
490+
[&](const void *context) -> NodePointer {
491+
return _buildDemanglingForContext(
492+
(const ContextDescriptor *) context,
493+
{}, false, Dem);
494+
});
495+
471496
// Look for an existing entry.
472497
// Find the bucket for the metadata entry.
473498
if (auto Value = T.ProtocolCache.find(mangledName))
474499
return Value->getDescription();
475500

476501
// Check type metadata records
477-
foundProtocol = _searchProtocolRecords(T, mangledName);
502+
foundProtocol = _searchProtocolRecords(T, node);
478503

479504
if (foundProtocol) {
480505
T.ProtocolCache.getOrInsert(mangledName, foundProtocol);
@@ -761,11 +786,10 @@ class DecodedMetadataBuilder {
761786
}
762787
#endif
763788

764-
auto mangledName = Demangle::mangleNode(node);
765-
766-
// Look for a Swift protocol with this mangled name.
767-
if (auto protocol = _findProtocolDescriptor(mangledName))
768-
return ProtocolDescriptorRef::forSwift(protocol);
789+
// Look for a protocol descriptor based on its mangled name.
790+
std::string mangledName;
791+
if (auto protocol = _findProtocolDescriptor(node, demangler, mangledName))
792+
return ProtocolDescriptorRef::forSwift(protocol);;
769793

770794
#if SWIFT_OBJC_INTEROP
771795
// Look for a Swift-defined @objc protocol with the Swift 3 mangling that

test/IRGen/protocol_metadata.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ protocol ABO : A, B, O { func abo() }
2525
// CHECK-SAME: @_PROTOCOL_METHOD_TYPES__TtP17protocol_metadata1O_
2626
// CHECK-SAME: }
2727

28-
// CHECK: [[A_NAME:@.*]] = private constant [25 x i8] c"$S17protocol_metadata1AP\00"
28+
// CHECK: [[A_NAME:@.*]] = private constant [2 x i8] c"A\00"
2929

3030
// CHECK-LABEL: @"$S17protocol_metadata1AMp" = hidden constant
3131
// CHECK-SAME: i32 65603,
@@ -36,7 +36,7 @@ protocol ABO : A, B, O { func abo() }
3636
// CHECK-SAME: i32 0,
3737
// CHECK-SAME: }
3838

39-
// CHECK: [[B_NAME:@.*]] = private constant [25 x i8] c"$S17protocol_metadata1BP\00"
39+
// CHECK: [[B_NAME:@.*]] = private constant [2 x i8] c"B\00"
4040
// CHECK-LABEL: @"$S17protocol_metadata1BMp" = hidden constant
4141
// CHECK-SAME: i32 65603,
4242
// CHECK-SAME: @"$S17protocol_metadataMXM"
@@ -45,7 +45,7 @@ protocol ABO : A, B, O { func abo() }
4545
// CHECK-SAME: i32 1,
4646
// CHECK: }
4747

48-
// CHECK: [[C_NAME:@.*]] = private constant [25 x i8] c"$S17protocol_metadata1CP\00"
48+
// CHECK: [[C_NAME:@.*]] = private constant [2 x i8] c"C\00"
4949
// CHECK-LABEL: @"$S17protocol_metadata1CMp" = hidden constant
5050
// CHECK-SAME: i32 67,
5151
// CHECK-SAME: @"$S17protocol_metadataMXM"
@@ -68,7 +68,7 @@ protocol ABO : A, B, O { func abo() }
6868

6969
// -- inheritance lists for refined protocols
7070

71-
// CHECK: [[AB_NAME:@.*]] = private constant [26 x i8] c"$S17protocol_metadata2ABP\00"
71+
// CHECK: [[AB_NAME:@.*]] = private constant [3 x i8] c"AB\00"
7272
// CHECK: @"$S17protocol_metadata2ABMp" = hidden constant
7373
// CHECK-SAME: i32 65603,
7474
// CHECK-SAME: @"$S17protocol_metadataMXM"

test/IRGen/protocol_resilience.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ import resilient_protocol
3939
// CHECK-SAME: }
4040

4141
// Protocol descriptor for ResilientProtocol
42-
// CHECK: [[RESILIENT_PROTOCOL_NAME:@.*]] = private constant [44 x i8] c"$S19protocol_resilience17ResilientProtocolP\00
42+
// CHECK: [[RESILIENT_PROTOCOL_NAME:@.*]] = private constant [18 x i8] c"ResilientProtocol\00
4343
// CHECK: [[ASSOCIATED_TYPES_T:@.*]] = private constant [2 x i8] c"T\00"
4444
// CHECK: @"$S19protocol_resilience17ResilientProtocolMp" = {{(dllexport )?}}{{(protected )?}}constant
4545
// CHECK-SAME: i32 196675,

test/IRGen/special_protocols.sil

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// RUN: %target-swift-frontend -assume-parsing-unqualified-ownership-sil %s -emit-ir -parse-stdlib -module-name Swift | %FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-%target-ptrsize
22

33
public protocol Error {}
4-
// CHECK: [[ERROR_NAME:@.*]] = private constant [11 x i8] c"$Ss5ErrorP\00"
4+
// CHECK: [[ERROR_NAME:@.*]] = private constant [6 x i8] c"Error\00"
55

66
// CHECK-LABEL: @"$Ss5ErrorMp" = {{(dllexport )?}}{{(protected )?}}constant
77
// -- 0x0000_0047: special protocol 01, non-class, unique, protocol context

0 commit comments

Comments
 (0)