mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Rework archetype mangling to follow parent hierarchy.
Use the ordinal archetype manglings only for the primary archetypes of a generic context, and define a mangling for associated types relative to their parent archetype. This will make the archetype mangling resilient in the face of our planned improvements to associated type and protocol conformance ABI. It also correctly mangles self and associated types of protocols, which my previous attempt utterly failed to accomplish. Swift SVN r8174
This commit is contained in:
10
docs/ABI.rst
10
docs/ABI.rst
@@ -254,8 +254,7 @@ types where the metadata itself has unknown layout.)
|
|||||||
type ::= 'G' type <type>+ '_' // generic type application
|
type ::= 'G' type <type>+ '_' // generic type application
|
||||||
type ::= 'M' type // metatype
|
type ::= 'M' type // metatype
|
||||||
type ::= 'P' protocol-list '_' // protocol type
|
type ::= 'P' protocol-list '_' // protocol type
|
||||||
type ::= 'Q' index // archetype with depth=0
|
type ::= archetype
|
||||||
type ::= 'Qd' index index // archetype with depth=M+1
|
|
||||||
type ::= 'R' type // byref
|
type ::= 'R' type // byref
|
||||||
type ::= 'T' tuple-element* '_' // tuple
|
type ::= 'T' tuple-element* '_' // tuple
|
||||||
type ::= 't' tuple-element* '_' // variadic tuple
|
type ::= 't' tuple-element* '_' // variadic tuple
|
||||||
@@ -268,9 +267,12 @@ types where the metadata itself has unknown layout.)
|
|||||||
nominal-type-kind ::= 'C' // class
|
nominal-type-kind ::= 'C' // class
|
||||||
nominal-type-kind ::= 'O' // union
|
nominal-type-kind ::= 'O' // union
|
||||||
nominal-type-kind ::= 'V' // struct
|
nominal-type-kind ::= 'V' // struct
|
||||||
|
archetype ::= 'Q' index // archetype with depth=0
|
||||||
|
archetype ::= 'Qd' index index // archetype with depth=M+1
|
||||||
|
archetype ::= associated-type
|
||||||
associated-type ::= substitution
|
associated-type ::= substitution
|
||||||
associated-type ::= 'QP' protocol identifier // protocol associated type
|
associated-type ::= 'Q' protocol-context // self type of protocol
|
||||||
associated-type ::= 'QQ' protocol // protocol Self type
|
associated-type ::= 'Q' archetype identifier // associated type
|
||||||
protocol-context ::= 'P' protocol
|
protocol-context ::= 'P' protocol
|
||||||
tuple-element ::= identifier? type
|
tuple-element ::= identifier? type
|
||||||
|
|
||||||
|
|||||||
@@ -1098,6 +1098,59 @@ private:
|
|||||||
return Node::makeNodePointer(Node::Kind::ArchetypeRef,
|
return Node::makeNodePointer(Node::Kind::ArchetypeRef,
|
||||||
archetypeName(index));
|
archetypeName(index));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NodePointer demangleArchetypeType() {
|
||||||
|
auto makeSelfType = [&](NodePointer proto) -> NodePointer {
|
||||||
|
NodePointer selfType
|
||||||
|
= Node::makeNodePointer(Node::Kind::SelfTypeRef);
|
||||||
|
selfType->push_back_child(proto);
|
||||||
|
Substitutions.push_back({ selfType, IsProtocol::no });
|
||||||
|
return selfType;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto makeAssociatedType = [&](NodePointer root) -> NodePointer {
|
||||||
|
NodePointer name = demangleIdentifier();
|
||||||
|
if (!name) return nullptr;
|
||||||
|
NodePointer assocType
|
||||||
|
= Node::makeNodePointer(Node::Kind::AssociatedTypeRef);
|
||||||
|
assocType->push_back_child(root);
|
||||||
|
assocType->push_back_child(name);
|
||||||
|
Substitutions.push_back({ assocType, IsProtocol::no });
|
||||||
|
return assocType;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (Mangled.nextIf('P')) {
|
||||||
|
NodePointer proto = demangleProtocolName();
|
||||||
|
if (!proto) return nullptr;
|
||||||
|
return makeSelfType(proto);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Mangled.nextIf('Q')) {
|
||||||
|
NodePointer root = demangleArchetypeType();
|
||||||
|
if (!root) return nullptr;
|
||||||
|
return makeAssociatedType(root);
|
||||||
|
}
|
||||||
|
if (Mangled.nextIf('S')) {
|
||||||
|
Substitution sub = demangleSubstitutionIndexWithProtocol();
|
||||||
|
if (!sub.first) return nullptr;
|
||||||
|
if (sub.second == IsProtocol::yes)
|
||||||
|
return makeSelfType(sub.first);
|
||||||
|
else
|
||||||
|
return makeAssociatedType(sub.first);
|
||||||
|
}
|
||||||
|
if (Mangled.nextIf('d')) {
|
||||||
|
size_t depth, index;
|
||||||
|
if (!demangleIndex(depth))
|
||||||
|
return nullptr;
|
||||||
|
if (!demangleIndex(index))
|
||||||
|
return nullptr;
|
||||||
|
return demangleArchetypeRef(depth + 1, index);
|
||||||
|
}
|
||||||
|
size_t index;
|
||||||
|
if (!demangleIndex(index))
|
||||||
|
return nullptr;
|
||||||
|
return demangleArchetypeRef(0, index);
|
||||||
|
}
|
||||||
|
|
||||||
NodePointer demangleTuple(IsVariadic isV) {
|
NodePointer demangleTuple(IsVariadic isV) {
|
||||||
NodePointer tuple = Node::makeNodePointer(
|
NodePointer tuple = Node::makeNodePointer(
|
||||||
@@ -1308,38 +1361,7 @@ private:
|
|||||||
return demangleProtocolList();
|
return demangleProtocolList();
|
||||||
}
|
}
|
||||||
if (c == 'Q') {
|
if (c == 'Q') {
|
||||||
if (Mangled.nextIf('P')) {
|
return demangleArchetypeType();
|
||||||
NodePointer proto = demangleProtocolName();
|
|
||||||
if (!proto) return nullptr;
|
|
||||||
NodePointer name = demangleIdentifier();
|
|
||||||
if (!name) return nullptr;
|
|
||||||
NodePointer assocType
|
|
||||||
= Node::makeNodePointer(Node::Kind::AssociatedTypeRef);
|
|
||||||
assocType->push_back_child(proto);
|
|
||||||
assocType->push_back_child(name);
|
|
||||||
Substitutions.push_back({ assocType, IsProtocol::no });
|
|
||||||
return assocType;
|
|
||||||
}
|
|
||||||
if (Mangled.nextIf('Q')) {
|
|
||||||
NodePointer proto = demangleProtocolName();
|
|
||||||
if (!proto) return nullptr;
|
|
||||||
NodePointer selfType = Node::makeNodePointer(Node::Kind::SelfTypeRef);
|
|
||||||
selfType->push_back_child(proto);
|
|
||||||
Substitutions.push_back({ selfType, IsProtocol::no });
|
|
||||||
return selfType;
|
|
||||||
}
|
|
||||||
if (Mangled.nextIf('d')) {
|
|
||||||
size_t depth, index;
|
|
||||||
if (!demangleIndex(depth))
|
|
||||||
return nullptr;
|
|
||||||
if (!demangleIndex(index))
|
|
||||||
return nullptr;
|
|
||||||
return demangleArchetypeRef(depth + 1, index);
|
|
||||||
}
|
|
||||||
size_t index;
|
|
||||||
if (!demangleIndex(index))
|
|
||||||
return nullptr;
|
|
||||||
return demangleArchetypeRef(0, index);
|
|
||||||
}
|
}
|
||||||
if (c == 'R') {
|
if (c == 'R') {
|
||||||
NodePointer byref = Node::makeNodePointer(Node::Kind::ByRef);
|
NodePointer byref = Node::makeNodePointer(Node::Kind::ByRef);
|
||||||
|
|||||||
@@ -290,7 +290,7 @@ void Mangler::bindGenericParameters(const GenericParamList *genericParams,
|
|||||||
// the outer context.
|
// the outer context.
|
||||||
ArchetypesDepth = genericParams->getDepth() + 1;
|
ArchetypesDepth = genericParams->getDepth() + 1;
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
for (auto archetype : genericParams->getAllArchetypes()) {
|
for (auto archetype : genericParams->getPrimaryArchetypes()) {
|
||||||
// Remember the current depth and level.
|
// Remember the current depth and level.
|
||||||
ArchetypeInfo info;
|
ArchetypeInfo info;
|
||||||
info.Depth = ArchetypesDepth;
|
info.Depth = ArchetypesDepth;
|
||||||
@@ -429,6 +429,7 @@ void Mangler::mangleDeclType(ValueDecl *decl, ExplosionKind explosion,
|
|||||||
/// <type> ::= P <protocol-list> _ # protocol composition
|
/// <type> ::= P <protocol-list> _ # protocol composition
|
||||||
/// <type> ::= Q <index> # archetype with depth=0, index=N
|
/// <type> ::= Q <index> # archetype with depth=0, index=N
|
||||||
/// <type> ::= Qd <index> <index> # archetype with depth=M+1, index=N
|
/// <type> ::= Qd <index> <index> # archetype with depth=M+1, index=N
|
||||||
|
/// <
|
||||||
/// <type> ::= R <type> # lvalue
|
/// <type> ::= R <type> # lvalue
|
||||||
/// <type> ::= T <tuple-element>* _ # tuple
|
/// <type> ::= T <tuple-element>* _ # tuple
|
||||||
/// <type> ::= U <generic-parameter>+ _ <type>
|
/// <type> ::= U <generic-parameter>+ _ <type>
|
||||||
@@ -576,35 +577,42 @@ void Mangler::mangleType(CanType type, ExplosionKind explosion,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// type ::= archetype
|
||||||
case TypeKind::Archetype: {
|
case TypeKind::Archetype: {
|
||||||
auto archetype = cast<ArchetypeType>(type);
|
auto archetype = cast<ArchetypeType>(type);
|
||||||
|
|
||||||
// type ::= associated-type
|
// archetype ::= associated-type
|
||||||
if (!archetype->getParent())
|
|
||||||
if (auto assocType = archetype->getAssocType()) {
|
|
||||||
// associated-type ::= substitution
|
|
||||||
if (tryMangleSubstitution(archetype.getPointer()))
|
|
||||||
return;
|
|
||||||
|
|
||||||
addSubstitution(archetype.getPointer());
|
|
||||||
|
|
||||||
// associated-type ::= QQ <protocol>
|
|
||||||
if (assocType->isSelf()) {
|
|
||||||
Buffer << "QQ";
|
|
||||||
mangleProtocolName(assocType->getProtocol());
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// associated-type ::= QP <protocol> <identifier>
|
|
||||||
Buffer << "QP";
|
|
||||||
mangleProtocolName(assocType->getProtocol());
|
|
||||||
mangleIdentifier(archetype->getName());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// <type> ::= Q <index> # archetype with depth=0, index=N
|
// associated-type ::= substitution
|
||||||
// <type> ::= Qd <index> <index> # archetype with depth=M+1, index=N
|
if (tryMangleSubstitution(archetype.getPointer()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Buffer << 'Q';
|
||||||
|
|
||||||
|
// associated-type ::= 'Q' archetype identifier
|
||||||
|
// Mangle the associated type of a parent archetype.
|
||||||
|
if (auto parent = archetype->getParent()) {
|
||||||
|
assert(archetype->getAssocType()
|
||||||
|
&& "child archetype has no associated type?!");
|
||||||
|
|
||||||
|
mangleType(CanType(parent), explosion, 0);
|
||||||
|
mangleIdentifier(archetype->getName());
|
||||||
|
addSubstitution(archetype.getPointer());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// associated-type ::= 'Q' protocol-context
|
||||||
|
// Mangle the Self archetype of a protocol.
|
||||||
|
if (archetype->getAssocType() && archetype->getAssocType()->isSelf()) {
|
||||||
|
Buffer << 'P';
|
||||||
|
mangleProtocolName(archetype->getAssocType()->getProtocol());
|
||||||
|
addSubstitution(archetype.getPointer());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// archetype ::= 'Q' <index> # archetype with depth=0, index=N
|
||||||
|
// archetype ::= 'Qd' <index> <index> # archetype with depth=M+1, index=N
|
||||||
|
// Mangle generic parameter archetypes.
|
||||||
|
|
||||||
// Find the archetype information. It may be possible for this to
|
// Find the archetype information. It may be possible for this to
|
||||||
// fail for local declarations --- that might be okay; it means we
|
// fail for local declarations --- that might be okay; it means we
|
||||||
@@ -615,7 +623,6 @@ void Mangler::mangleType(CanType type, ExplosionKind explosion,
|
|||||||
auto &info = it->second;
|
auto &info = it->second;
|
||||||
assert(ArchetypesDepth >= info.Depth);
|
assert(ArchetypesDepth >= info.Depth);
|
||||||
|
|
||||||
Buffer << 'Q';
|
|
||||||
unsigned relativeDepth = ArchetypesDepth - info.Depth;
|
unsigned relativeDepth = ArchetypesDepth - info.Depth;
|
||||||
if (relativeDepth != 0) {
|
if (relativeDepth != 0) {
|
||||||
Buffer << 'd' << Index(relativeDepth - 1);
|
Buffer << 'd' << Index(relativeDepth - 1);
|
||||||
|
|||||||
Reference in New Issue
Block a user