Skip to content

Commit 95c43f4

Browse files
committed
Decode opaque types in the runtime demangler.
1 parent a3c17bd commit 95c43f4

File tree

17 files changed

+396
-170
lines changed

17 files changed

+396
-170
lines changed

docs/ABI/Mangling.rst

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,13 @@ The following symbolic reference kinds are currently implemented:
7878

7979
::
8080

81-
{any-generic-type, protocol} ::= '\x01' .{4} // Reference points directly to context descriptor
82-
{any-generic-type, protocol} ::= '\x02' .{4} // Reference points indirectly to context descriptor
81+
#if SWIFT_RUNTIME_VERSION < 5.1
82+
{any-generic-type, protocol} ::= '\x01' .{4} // Reference points directly to context descriptor
83+
{any-generic-type, protocol} ::= '\x02' .{4} // Reference points indirectly to context descriptor
84+
#else
85+
{any-generic-type, protocol, opaque-type-decl-name} ::= '\x01' .{4} // Reference points directly to context descriptor
86+
{any-generic-type, protocol, opaque-type-decl-name} ::= '\x02' .{4} // Reference points indirectly to context descriptor
87+
#endif
8388
// The grammatical role of the symbolic reference is determined by the
8489
// kind of context descriptor referenced
8590

@@ -93,15 +98,13 @@ The following symbolic reference kinds are currently implemented:
9398
associated-conformance-access-function ::= '\x08' .{4} // Reference points directly to associated conformance access function relative to the conforming type
9499

95100
// keypaths only in Swift 5.0, generalized in Swift 5.1
96-
metadata-access-function ::= '\x09' .{4} // Reference points directly to metadata access function that can be invoked to produce referenced object
97-
98-
// begin added in Swift 5.1
99-
any-generic-type ::= '\x0B' .{4} // Reference points directly to an opaque type descriptor
100-
any-generic-type ::= '\x0C' .{4} // Reference points indirectly to an opaque type descriptor
101-
// end added in Swift 5.1
101+
#if SWIFT_RUNTIME_VERSION >= 5.1
102+
metadata-access-function ::= '\x09' .{4} // Reference points directly to metadata access function that can be invoked to produce referenced object
103+
#endif
102104

103-
A mangled name may also include ``\xFF`` bytes, which are only used for alignment
104-
padding. They can be skipped over and ignored.
105+
A mangled name may also include ``\xFF`` bytes, which are only used for
106+
alignment padding. They do not affect what the mangled name references and can
107+
be skipped over and ignored.
105108

106109
Globals
107110
~~~~~~~
@@ -120,7 +123,9 @@ Globals
120123
global ::= nominal-type 'Ml' // in-place type initialization cache
121124
global ::= nominal-type 'Mm' // class metaclass
122125
global ::= nominal-type 'Mn' // nominal type descriptor
123-
global ::= opaque-type-decl-name 'MQ' // opaque type descriptor -- added in Swift 5.1
126+
#if SWIFT_RUNTIME_VERSION >= 5.1
127+
global ::= opaque-type-decl-name 'MQ' // opaque type descriptor -- added in Swift 5.1
128+
#endif
124129
global ::= nominal-type 'Mu' // class method lookup function
125130
global ::= nominal-type 'MU' // ObjC metadata update callback function
126131
global ::= nominal-type 'Ms' // ObjC resilient class stub
@@ -613,14 +618,12 @@ implementation details of a function type.
613618

614619
::
615620

616-
// begin added in Swift 5.1
617-
618-
type ::= 'Qr' // opaque result type (of current decl)
619-
type ::= opaque-type-decl-name bound-generic-args 'Qo' // opaque type
620-
621-
opaque-type-decl-name ::= entity 'QO' // opaque result type of specified decl
621+
#if SWIFT_VERSION >= 5.1
622+
type ::= 'Qr' // opaque result type (of current decl)
623+
type ::= opaque-type-decl-name bound-generic-args 'Qo' INDEX // opaque type
622624

623-
// end added in Swift 5.1
625+
opaque-type-decl-name ::= entity 'QO' // opaque result type of specified decl
626+
#endif
624627

625628
Opaque return types have a special short representation in the mangling of
626629
their defining entity. In structural position, opaque types are fully qualified

include/swift/ABI/Metadata.h

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3027,6 +3027,11 @@ struct TargetOpaqueTypeDescriptor final
30273027
using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
30283028

30293029
public:
3030+
using TrailingGenericContextObjects::getGenericContext;
3031+
using TrailingGenericContextObjects::getGenericContextHeader;
3032+
using TrailingGenericContextObjects::getFullGenericContextHeader;
3033+
using TrailingGenericContextObjects::getGenericParams;
3034+
30303035
// The kind-specific flags area is used to store the count of the generic
30313036
// arguments for underlying type(s) encoded in the descriptor.
30323037
unsigned getNumUnderlyingTypeArguments() const {
@@ -3038,9 +3043,12 @@ struct TargetOpaqueTypeDescriptor final
30383043
return getNumUnderlyingTypeArguments();
30393044
}
30403045

3041-
const char * getUnderlyingTypeArgument(unsigned i) const {
3046+
StringRef getUnderlyingTypeArgument(unsigned i) const {
30423047
assert(i < getNumUnderlyingTypeArguments());
3043-
return (this->template getTrailingObjects<RelativeDirectPointer<const char>>())[i];
3048+
const char *ptr =
3049+
(this->template getTrailingObjects<RelativeDirectPointer<const char>>())[i];
3050+
3051+
return Demangle::makeSymbolicMangledNameStringRef(ptr);
30443052
}
30453053

30463054
static bool classof(const TargetContextDescriptor<Runtime> *cd) {
@@ -4257,6 +4265,9 @@ TargetContextDescriptor<Runtime>::getGenericContext() const {
42574265
case ContextDescriptorKind::Struct:
42584266
return llvm::cast<TargetStructDescriptor<Runtime>>(this)
42594267
->getGenericContext();
4268+
case ContextDescriptorKind::OpaqueType:
4269+
return llvm::cast<TargetOpaqueTypeDescriptor<Runtime>>(this)
4270+
->getGenericContext();
42604271
default:
42614272
// We don't know about this kind of descriptor.
42624273
return nullptr;
@@ -4308,6 +4319,8 @@ TargetTypeContextDescriptor<Runtime>::getGenericParams() const {
43084319
return llvm::cast<TargetEnumDescriptor<Runtime>>(this)->getGenericParams();
43094320
case ContextDescriptorKind::Struct:
43104321
return llvm::cast<TargetStructDescriptor<Runtime>>(this)->getGenericParams();
4322+
case ContextDescriptorKind::OpaqueType:
4323+
return llvm::cast<TargetOpaqueTypeDescriptor<Runtime>>(this)->getGenericParams();
43114324
default:
43124325
swift_runtime_unreachable("Not a type context descriptor.");
43134326
}

include/swift/AST/ASTDemangler.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,10 @@ class ASTBuilder {
8282
Type createTypeAliasType(GenericTypeDecl *decl, Type parent);
8383

8484
Type createBoundGenericType(GenericTypeDecl *decl, ArrayRef<Type> args);
85+
86+
Type resolveOpaqueType(NodePointer opaqueDescriptor,
87+
ArrayRef<Type> args,
88+
unsigned ordinal);
8589

8690
Type createBoundGenericType(GenericTypeDecl *decl, ArrayRef<Type> args,
8791
Type parent);

include/swift/AST/ASTMangler.h

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,18 @@ class ASTMangler : public Mangler {
5959

6060
public:
6161
using SymbolicReferent = llvm::PointerUnion<const NominalTypeDecl *,
62-
const ProtocolConformance *>;
62+
const OpaqueTypeDecl *>;
6363
protected:
6464

6565
/// If set, the mangler calls this function to determine whether to symbolic
66-
/// reference a given entity. Defaults to always returning true.
66+
/// reference a given entity. If null, the mangler acts as if it's set to
67+
/// always return true.
6768
std::function<bool (SymbolicReferent)> CanSymbolicReference;
69+
70+
bool canSymbolicReference(SymbolicReferent referent) {
71+
return AllowSymbolicReferences
72+
&& (!CanSymbolicReference || CanSymbolicReference(referent));
73+
}
6874

6975
std::vector<std::pair<SymbolicReferent, unsigned>> SymbolicReferences;
7076

@@ -237,7 +243,8 @@ class ASTMangler : public Mangler {
237243

238244
/// Append any retroactive conformances.
239245
void appendRetroactiveConformances(Type type);
240-
246+
void appendRetroactiveConformances(SubstitutionMap subMap,
247+
ModuleDecl *fromModule);
241248
void appendImplFunctionType(SILFunctionType *fn);
242249

243250
void appendContextOf(const ValueDecl *decl);

include/swift/Demangling/DemangleNodes.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -262,11 +262,12 @@ NODE(SugaredDictionary)
262262
NODE(SugaredParen)
263263

264264
// Added in Swift 5.1
265+
NODE(AccessorFunctionReference)
265266
NODE(OpaqueType)
267+
NODE(OpaqueTypeDescriptorSymbolicReference)
266268
NODE(OpaqueTypeDescriptor)
267269
NODE(OpaqueReturnType)
268270
NODE(OpaqueReturnTypeOf)
269-
NODE(AccessorFunctionReference)
270271

271272
#undef CONTEXT_NODE
272273
#undef NODE

include/swift/Demangling/Demangler.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,9 @@ class Demangler : public NodeFactory {
562562
NodePointer demangleSymbolicReference(unsigned char rawKind,
563563
const void *at);
564564

565+
bool demangleBoundGenerics(Vector<NodePointer> &TypeListList,
566+
NodePointer &RetroactiveConformances);
567+
565568
void dump();
566569

567570
public:

include/swift/Demangling/TypeDecoder.h

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,8 @@ class TypeDecoder {
318318
SmallVector<BuiltType, 8> args;
319319

320320
const auto &genericArgs = Node->getChild(1);
321-
assert(genericArgs->getKind() == NodeKind::TypeList);
321+
if (genericArgs->getKind() != NodeKind::TypeList)
322+
return BuiltType();
322323

323324
for (auto genericArg : *genericArgs) {
324325
auto paramType = decodeMangledType(genericArg);
@@ -777,6 +778,35 @@ class TypeDecoder {
777778

778779
return Builder.createParenType(base);
779780
}
781+
case NodeKind::OpaqueType: {
782+
if (Node->getNumChildren() < 3)
783+
return BuiltType();
784+
auto descriptor = Node->getChild(0);
785+
auto ordinalNode = Node->getChild(1);
786+
787+
if (ordinalNode->getKind() != NodeKind::Index
788+
|| !ordinalNode->hasIndex())
789+
return BuiltType();
790+
auto ordinal = ordinalNode->getIndex();
791+
792+
std::vector<BuiltType> genericArgs;
793+
auto boundGenerics = Node->getChild(2);
794+
for (unsigned i = 0; i < boundGenerics->getNumChildren(); ++i) {
795+
auto genericsNode = boundGenerics->getChild(i);
796+
if (genericsNode->getKind() != NodeKind::TypeList)
797+
break;
798+
for (auto argNode : *genericsNode) {
799+
auto arg = decodeMangledType(argNode);
800+
if (!arg)
801+
return BuiltType();
802+
genericArgs.push_back(arg);
803+
}
804+
}
805+
806+
return Builder.resolveOpaqueType(descriptor, genericArgs, ordinal);
807+
}
808+
// TODO: Handle OpaqueReturnType, when we're in the middle of reconstructing
809+
// the defining decl
780810
default:
781811
return BuiltType();
782812
}

include/swift/Reflection/TypeRefBuilder.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,14 @@ class TypeRefBuilder {
278278
const TypeRef *parent) {
279279
return BoundGenericTypeRef::create(*this, *mangledName, args, parent);
280280
}
281+
282+
const TypeRef *
283+
resolveOpaqueType(NodePointer opaqueDescriptor,
284+
const std::vector<const TypeRef *> &genericArgs,
285+
unsigned ordinal) {
286+
// TODO
287+
return nullptr;
288+
}
281289

282290
const TupleTypeRef *
283291
createTupleType(ArrayRef<const TypeRef *> elements,

lib/AST/ASTDemangler.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,13 @@ Type ASTBuilder::createBoundGenericType(GenericTypeDecl *decl,
247247
return substType;
248248
}
249249

250+
Type ASTBuilder::resolveOpaqueType(NodePointer opaqueDescriptor,
251+
ArrayRef<Type> args,
252+
unsigned ordinal) {
253+
// TODO
254+
return Type();
255+
}
256+
250257
Type ASTBuilder::createBoundGenericType(GenericTypeDecl *decl,
251258
ArrayRef<Type> args,
252259
Type parent) {

lib/AST/ASTMangler.cpp

Lines changed: 46 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -732,7 +732,9 @@ static bool shouldMangleAsGeneric(Type type) {
732732
}
733733

734734
void ASTMangler::appendOpaqueDeclName(const OpaqueTypeDecl *opaqueDecl) {
735-
if (auto namingDecl = opaqueDecl->getNamingDecl()) {
735+
if (canSymbolicReference(opaqueDecl)) {
736+
appendSymbolicReference(opaqueDecl);
737+
} else if (auto namingDecl = opaqueDecl->getNamingDecl()) {
736738
appendEntity(namingDecl);
737739
appendOperator("QO");
738740
} else {
@@ -976,13 +978,24 @@ void ASTMangler::appendType(Type type, const ValueDecl *forDecl) {
976978
}
977979
}
978980

979-
// Otherwise, use the fully qualified mangling.
981+
// Otherwise, try to substitute it.
982+
if (tryMangleTypeSubstitution(type))
983+
return;
984+
985+
// Use the fully elaborated explicit mangling.
980986
appendOpaqueDeclName(opaqueDecl);
981987
bool isFirstArgList = true;
982988
appendBoundGenericArgs(opaqueDecl->getInnermostDeclContext(),
983989
opaqueType->getSubstitutions(),
984990
isFirstArgList);
985-
appendOperator("Qo");
991+
appendRetroactiveConformances(opaqueType->getSubstitutions(),
992+
opaqueDecl->getParentModule());
993+
994+
// TODO: If we support multiple opaque types in a return, put the
995+
// ordinal for this archetype here.
996+
appendOperator("Qo", Index(0));
997+
998+
addTypeSubstitution(type);
986999
return;
9871000
}
9881001

@@ -1297,24 +1310,8 @@ static bool containsRetroactiveConformance(
12971310
return false;
12981311
}
12991312

1300-
void ASTMangler::appendRetroactiveConformances(Type type) {
1301-
// Dig out the substitution map to use.
1302-
SubstitutionMap subMap;
1303-
ModuleDecl *module;
1304-
if (auto typeAlias = dyn_cast<TypeAliasType>(type.getPointer())) {
1305-
module = Mod ? Mod : typeAlias->getDecl()->getModuleContext();
1306-
subMap = typeAlias->getSubstitutionMap();
1307-
} else {
1308-
if (type->hasUnboundGenericType())
1309-
return;
1310-
1311-
auto nominal = type->getAnyNominal();
1312-
if (!nominal) return;
1313-
1314-
module = Mod ? Mod : nominal->getModuleContext();
1315-
subMap = type->getContextSubstitutionMap(module, nominal);
1316-
}
1317-
1313+
void ASTMangler::appendRetroactiveConformances(SubstitutionMap subMap,
1314+
ModuleDecl *fromModule) {
13181315
if (subMap.empty()) return;
13191316

13201317
unsigned numProtocolRequirements = 0;
@@ -1328,14 +1325,35 @@ void ASTMangler::appendRetroactiveConformances(Type type) {
13281325
continue;
13291326

13301327
// Skip non-retroactive conformances.
1331-
if (!containsRetroactiveConformance(conformance.getConcrete(), module))
1328+
if (!containsRetroactiveConformance(conformance.getConcrete(), fromModule))
13321329
continue;
13331330

13341331
appendConcreteProtocolConformance(conformance.getConcrete());
13351332
appendOperator("g", Index(numProtocolRequirements));
13361333
}
13371334
}
13381335

1336+
void ASTMangler::appendRetroactiveConformances(Type type) {
1337+
// Dig out the substitution map to use.
1338+
SubstitutionMap subMap;
1339+
ModuleDecl *module;
1340+
if (auto typeAlias = dyn_cast<TypeAliasType>(type.getPointer())) {
1341+
module = Mod ? Mod : typeAlias->getDecl()->getModuleContext();
1342+
subMap = typeAlias->getSubstitutionMap();
1343+
} else {
1344+
if (type->hasUnboundGenericType())
1345+
return;
1346+
1347+
auto nominal = type->getAnyNominal();
1348+
if (!nominal) return;
1349+
1350+
module = Mod ? Mod : nominal->getModuleContext();
1351+
subMap = type->getContextSubstitutionMap(module, nominal);
1352+
}
1353+
1354+
appendRetroactiveConformances(subMap, module);
1355+
}
1356+
13391357
static char getParamConvention(ParameterConvention conv) {
13401358
// @in and @out are mangled the same because they're put in
13411359
// different places.
@@ -1700,8 +1718,7 @@ void ASTMangler::appendProtocolName(const ProtocolDecl *protocol,
17001718
return;
17011719

17021720
// We can use a symbolic reference if they're allowed in this context.
1703-
if (AllowSymbolicReferences
1704-
&& (!CanSymbolicReference || CanSymbolicReference(protocol))) {
1721+
if (canSymbolicReference(protocol)) {
17051722
// Try to use a symbolic reference substitution.
17061723
if (tryMangleSubstitution(protocol))
17071724
return;
@@ -1761,16 +1778,13 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
17611778
if (tryMangleSubstitution(cast<TypeAliasDecl>(decl)))
17621779
return;
17631780
}
1764-
17651781

17661782
// Try to mangle a symbolic reference for a nominal type.
1767-
if (AllowSymbolicReferences) {
1768-
if (nominal && (!CanSymbolicReference || CanSymbolicReference(nominal))) {
1769-
appendSymbolicReference(nominal);
1770-
// Substitutions can refer back to the symbolic reference.
1771-
addTypeSubstitution(nominal->getDeclaredType());
1772-
return;
1773-
}
1783+
if (nominal && canSymbolicReference(nominal)) {
1784+
appendSymbolicReference(nominal);
1785+
// Substitutions can refer back to the symbolic reference.
1786+
addTypeSubstitution(nominal->getDeclaredType());
1787+
return;
17741788
}
17751789

17761790
appendContextOf(decl);

0 commit comments

Comments
 (0)