Skip to content

Commit 24616ae

Browse files
committed
Mangling support for extended existential type shapes
1 parent 124fe99 commit 24616ae

File tree

9 files changed

+276
-0
lines changed

9 files changed

+276
-0
lines changed

docs/ABI/Mangling.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,8 @@ Globals
189189
global ::= global 'MN' // noncanonical specialized generic type metadata for global
190190
global ::= global 'Mz' // canonical specialized generic type metadata caching token
191191

192+
global ::= global 'Mq' // global with a uniquing prefix
193+
192194
#if SWIFT_RUNTIME_VERSION >= 5.4
193195
global ::= context (decl-name '_')+ 'WZ' // global variable one-time initialization function
194196
global ::= context (decl-name '_')+ 'Wz' // global variable one-time initialization token
@@ -914,6 +916,23 @@ than the module of the conforming type or the conformed-to protocol), it is
914916
mangled with its offset into the set of conformance requirements, the
915917
root protocol conformance, and the suffix 'g'.
916918

919+
::
920+
921+
// No generalization signature, no type expression.
922+
extended-existential-shape ::= generic-signature 'Xg' extended-existential-value-storage
923+
924+
// Generalization signature (the second one), no type expression.
925+
extended-existential-shape ::= generic-signature generic-signature 'XG' extended-existential-value-storage
926+
927+
// No generalization signature, type expression.
928+
extended-existential-shape ::= generic-signature type 'Xh' extended-existential-value-storage
929+
930+
// Generalization signature (the second one), type expression.
931+
extended-existential-shape ::= generic-signature generic-signature type 'Xh' extended-existential-value-storage
932+
933+
extended-existential-value-storage ::= 'o' // opaque
934+
extended-existential-value-storage ::= 'c' // class
935+
extended-existential-value-storage ::= 'm' // metatype
917936

918937
Identifiers
919938
~~~~~~~~~~~

include/swift/Demangling/DemangleNodes.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,9 @@ NODE(CompileTimeConst)
335335
NODE(OpaqueReturnTypeIndexed)
336336
NODE(BackDeploymentThunk)
337337
NODE(BackDeploymentFallback)
338+
NODE(ExtendedExistentialTypeShape)
339+
NODE(ExtendedExistentialValueStorage)
340+
NODE(Uniquable)
338341

339342
#undef CONTEXT_NODE
340343
#undef NODE

include/swift/Demangling/Demangler.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,7 @@ class Demangler : public NodeFactory {
529529
NodePointer demangleArchetype();
530530
NodePointer demangleAssociatedTypeSimple(NodePointer GenericParamIdx);
531531
NodePointer demangleAssociatedTypeCompound(NodePointer GenericParamIdx);
532+
NodePointer demangleExtendedExistentialShape(char kind);
532533

533534
NodePointer popAssocTypeName();
534535
NodePointer popAssocTypePath();

lib/Demangling/Demangler.cpp

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2117,6 +2117,8 @@ NodePointer Demangler::demangleMetatype() {
21172117
return createWithChild(Node::Kind::ProtocolDescriptor, popProtocol());
21182118
case 'P':
21192119
return createWithPoppedType(Node::Kind::GenericTypeMetadataPattern);
2120+
case 'q':
2121+
return createWithChild(Node::Kind::Uniquable, popNode());
21202122
case 'Q':
21212123
return createWithChild(Node::Kind::OpaqueTypeDescriptor, popNode());
21222124
case 'r':
@@ -3227,6 +3229,11 @@ NodePointer Demangler::demangleSpecialType() {
32273229
return popFunctionType(Node::Kind::ObjCBlock);
32283230
case 'C':
32293231
return popFunctionType(Node::Kind::CFunctionPointer);
3232+
case 'g':
3233+
case 'G':
3234+
case 'h':
3235+
case 'H':
3236+
return demangleExtendedExistentialShape(specialChar);
32303237
case 'z':
32313238
switch (auto cchar = nextChar()) {
32323239
case 'B':
@@ -3374,6 +3381,51 @@ NodePointer Demangler::demangleSpecialType() {
33743381
}
33753382
}
33763383

3384+
NodePointer Demangler::demangleExtendedExistentialShape(char nodeKind) {
3385+
assert(nodeKind == 'g' || nodeKind == 'G' ||
3386+
nodeKind == 'h' || nodeKind == 'H');
3387+
3388+
NodePointer type = nullptr;
3389+
if (nodeKind == 'h' || nodeKind == 'H')
3390+
type = popNode(Node::Kind::Type);
3391+
3392+
NodePointer genSig = nullptr;
3393+
if (nodeKind == 'G' || nodeKind == 'H')
3394+
genSig = popNode(Node::Kind::DependentGenericSignature);
3395+
3396+
NodePointer reqSig = popNode(Node::Kind::DependentGenericSignature);
3397+
3398+
NodePointer valueStorage = [&]() -> NodePointer {
3399+
switch (nextChar()) {
3400+
case 'o':
3401+
return createNode(Node::Kind::ExtendedExistentialValueStorage,
3402+
"opaque");
3403+
case 'c':
3404+
return createNode(Node::Kind::ExtendedExistentialValueStorage,
3405+
"class");
3406+
case 'm':
3407+
return createNode(Node::Kind::ExtendedExistentialValueStorage,
3408+
"metatype");
3409+
default:
3410+
return nullptr;
3411+
}
3412+
}();
3413+
if (!valueStorage) return nullptr;
3414+
3415+
// Make a default type expression if one wasn't given.
3416+
if (!type) {
3417+
type = createType(getDependentGenericParamType(genSig ? 1 : 0, 0));
3418+
}
3419+
3420+
if (genSig) {
3421+
return createWithChildren(Node::Kind::ExtendedExistentialTypeShape,
3422+
reqSig, genSig, type, valueStorage);
3423+
} else {
3424+
return createWithChildren(Node::Kind::ExtendedExistentialTypeShape,
3425+
reqSig, type, valueStorage);
3426+
}
3427+
}
3428+
33773429
NodePointer Demangler::demangleMetatypeRepresentation() {
33783430
switch (nextChar()) {
33793431
case 't':

lib/Demangling/NodePrinter.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,9 @@ class NodePrinter {
594594
case Node::Kind::AccessibleFunctionRecord:
595595
case Node::Kind::BackDeploymentThunk:
596596
case Node::Kind::BackDeploymentFallback:
597+
case Node::Kind::ExtendedExistentialTypeShape:
598+
case Node::Kind::ExtendedExistentialValueStorage:
599+
case Node::Kind::Uniquable:
597600
return false;
598601
}
599602
printer_unreachable("bad node kind");
@@ -2962,6 +2965,41 @@ NodePointer NodePrinter::print(NodePointer Node, unsigned depth,
29622965
Printer << " suspend resume partial function for ";
29632966
}
29642967
return nullptr;
2968+
case Node::Kind::Uniquable:
2969+
Printer << "uniquable ";
2970+
print(Node->getChild(0), depth + 1);
2971+
return nullptr;
2972+
case Node::Kind::ExtendedExistentialTypeShape: {
2973+
// Printing the requirement signature is pretty useless if we
2974+
// don't print `where` clauses.
2975+
auto savedDisplayWhereClauses = Options.DisplayWhereClauses;
2976+
Options.DisplayWhereClauses = true;
2977+
2978+
NodePointer reqSig = Node->getChild(0);
2979+
NodePointer genSig = nullptr, type = nullptr;
2980+
if (Node->getNumChildren() == 4) {
2981+
genSig = Node->getChild(1);
2982+
type = Node->getChild(2);
2983+
} else {
2984+
type = Node->getChild(1);
2985+
}
2986+
2987+
Printer << "existential shape for ";
2988+
if (genSig) {
2989+
print(genSig, depth + 1);
2990+
Printer << " ";
2991+
}
2992+
Printer << "any";
2993+
print(reqSig, depth + 1);
2994+
Printer << " ";
2995+
print(type, depth + 1);
2996+
2997+
Options.DisplayWhereClauses = savedDisplayWhereClauses;
2998+
return nullptr;
2999+
}
3000+
case Node::Kind::ExtendedExistentialValueStorage:
3001+
Printer << Node->getText();
3002+
return nullptr;
29653003
}
29663004

29673005
printer_unreachable("bad node kind!");

lib/Demangling/OldRemangler.cpp

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2718,6 +2718,17 @@ ManglingError Remangler::mangleParameterizedProtocol(Node *node,
27182718
unsigned int depth) {
27192719
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
27202720
}
2721+
ManglingError Remangler::mangleUniquable(Node *node, unsigned int depth) {
2722+
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
2723+
}
2724+
ManglingError Remangler::mangleExtendedExistentialTypeShape(Node *node,
2725+
unsigned int depth) {
2726+
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
2727+
}
2728+
ManglingError Remangler::mangleExtendedExistentialValueStorage(Node *node,
2729+
unsigned int depth) {
2730+
return MANGLING_ERROR(ManglingError::UnsupportedNodeKind, node);
2731+
}
27212732
ManglingError
27222733
Remangler::mangleCanonicalSpecializedGenericMetaclass(Node *node,
27232734
unsigned depth) {

lib/Demangling/Remangler.cpp

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3437,6 +3437,76 @@ ManglingError Remangler::mangleBackDeploymentFallback(Node *node,
34373437
return ManglingError::Success;
34383438
}
34393439

3440+
ManglingError Remangler::mangleUniquable(Node *node, unsigned depth) {
3441+
RETURN_IF_ERROR(mangle(node->getChild(0), depth + 1));
3442+
Buffer << "Mq";
3443+
return ManglingError::Success;
3444+
}
3445+
3446+
ManglingError Remangler::mangleExtendedExistentialTypeShape(Node *node,
3447+
unsigned depth) {
3448+
NodePointer reqSig, genSig, type, storage;
3449+
reqSig = node->getChild(0);
3450+
if (node->getNumChildren() == 3) {
3451+
genSig = nullptr;
3452+
type = node->getChild(1);
3453+
storage = node->getChild(2);
3454+
} else {
3455+
genSig = node->getChild(1);
3456+
type = node->getChild(2);
3457+
storage = node->getChild(3);
3458+
}
3459+
3460+
RETURN_IF_ERROR(mangle(reqSig, depth + 1));
3461+
if (genSig) {
3462+
RETURN_IF_ERROR(mangle(genSig, depth + 1));
3463+
}
3464+
3465+
// Recognize the special case of a type expression that's just the
3466+
// unique requirement type parameter.
3467+
{
3468+
if (type->getKind() != Node::Kind::Type)
3469+
return MANGLING_ERROR(ManglingError::WrongNodeType, type);
3470+
auto typeNode = type->getChild(0);
3471+
3472+
if (typeNode->getKind() == Node::Kind::DependentGenericParamType) {
3473+
auto paramDepth = typeNode->getChild(0)->getIndex();
3474+
auto index = typeNode->getChild(1)->getIndex();
3475+
if (paramDepth == (genSig ? 1 : 0) && index == 0)
3476+
type = nullptr;
3477+
}
3478+
}
3479+
if (type)
3480+
RETURN_IF_ERROR(mangle(type, depth + 1));
3481+
3482+
if (genSig && type)
3483+
Buffer << "XH";
3484+
else if (type)
3485+
Buffer << "Xh";
3486+
else if (genSig)
3487+
Buffer << "XG";
3488+
else
3489+
Buffer << "Xg";
3490+
3491+
RETURN_IF_ERROR(mangle(storage, depth + 1));
3492+
3493+
return ManglingError::Success;
3494+
}
3495+
3496+
ManglingError Remangler::mangleExtendedExistentialValueStorage(Node *node,
3497+
unsigned depth) {
3498+
if (node->getText() == "opaque")
3499+
Buffer << "o";
3500+
else if (node->getText() == "class")
3501+
Buffer << "c";
3502+
else if (node->getText() == "metatype")
3503+
Buffer << "m";
3504+
else
3505+
return MANGLING_ERROR(ManglingError::UnknownEncoding, node);
3506+
3507+
return ManglingError::Success;
3508+
}
3509+
34403510
} // anonymous namespace
34413511

34423512
/// The top-level interface to the remangler.

lib/IRGen/IRGenMangler.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,3 +397,69 @@ std::string IRGenMangler::mangleSymbolNameForGenericEnvironment(
397397
appendGenericSignature(genericSig);
398398
return finalize();
399399
}
400+
401+
std::string
402+
IRGenMangler::mangleExtendedExistentialTypeShape(bool isUnique,
403+
CanGenericSignature genSig,
404+
CanExistentialType type,
405+
unsigned metatypeDepth) {
406+
beginMangling();
407+
408+
appendExtendedExistentialTypeShape(genSig, type, metatypeDepth);
409+
410+
// If this is non-unique, add a suffix to avoid accidental misuse
411+
// (and to make it easier to analyze in an image).
412+
if (!isUnique)
413+
appendOperator("Mq");
414+
415+
return finalize();
416+
}
417+
418+
std::string
419+
IRGenMangler::mangleExtendedExistentialTypeShapeForUniquing(
420+
CanGenericSignature genSig,
421+
CanExistentialType type,
422+
unsigned metatypeDepth) {
423+
beginManglingWithoutPrefix();
424+
appendExtendedExistentialTypeShape(genSig, type, metatypeDepth);
425+
return finalize();
426+
}
427+
void
428+
IRGenMangler::appendExtendedExistentialTypeShape(CanGenericSignature genSig,
429+
CanExistentialType type,
430+
unsigned metatypeDepth) {
431+
// Append the requirement signature of the existential.
432+
auto &ctx = type->getASTContext();
433+
auto reqSig = ctx.getOpenedArchetypeSignature(type, genSig);
434+
appendGenericSignature(reqSig, genSig);
435+
436+
// Append the generalization signature.
437+
if (genSig) appendGenericSignature(genSig);
438+
439+
// Append the type expression, if we have metatypes.
440+
// Metatypes are called out because they're currently the only
441+
// type expression we support.
442+
if (metatypeDepth) {
443+
assert(reqSig.getGenericParams().size() == 1);
444+
Type type = reqSig.getGenericParams()[0];
445+
for (unsigned i = 0; i != metatypeDepth; ++i)
446+
type = MetatypeType::get(type);
447+
appendType(type, reqSig);
448+
}
449+
450+
// Append the shape operator.
451+
if (!genSig) {
452+
appendOperator(metatypeDepth ? "Xh" : "Xg");
453+
} else {
454+
appendOperator(metatypeDepth ? "XH" : "XG");
455+
}
456+
457+
// Append the value storage.
458+
if (metatypeDepth)
459+
appendOperator("m");
460+
else if (type->requiresClass())
461+
appendOperator("c");
462+
else
463+
appendOperator("o");
464+
}
465+

lib/IRGen/IRGenMangler.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,22 @@ class IRGenMangler : public Mangle::ASTMangler {
468468
}
469469
}
470470

471+
void appendExtendedExistentialTypeShape(CanGenericSignature genSig,
472+
CanExistentialType type,
473+
unsigned metatypeDepth);
474+
475+
/// Mangle the symbol name for an extended existential type shape.
476+
std::string mangleExtendedExistentialTypeShape(bool isUnique,
477+
CanGenericSignature genSig,
478+
CanExistentialType type,
479+
unsigned metatypeDepth);
480+
481+
/// Mangle an extended existential type shape for the uniquing hash.
482+
std::string mangleExtendedExistentialTypeShapeForUniquing(
483+
CanGenericSignature genSig,
484+
CanExistentialType type,
485+
unsigned metatypeDepth);
486+
471487
std::string mangleCoroutineContinuationPrototype(CanSILFunctionType type) {
472488
return mangleTypeSymbol(type, "TC");
473489
}

0 commit comments

Comments
 (0)