Skip to content

Commit 878a2fa

Browse files
authored
Merge pull request #20166 from DougGregor/demangle-fixes-5.0
[5.0] Incorporate recent fixes for demangling to metadata
2 parents 136c821 + 1f6cd9e commit 878a2fa

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1396
-829
lines changed

docs/ABI/Mangling.rst

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,15 @@ Mangling
99
--------
1010
::
1111

12-
mangled-name ::= '$s' global
12+
mangled-name ::= '$s' global // Swift stable mangling
13+
mangled-name ::= '_T0' global // Swift 4.0
14+
mangled-name ::= '$S' global // Swift 4.2
1315

14-
All Swift-mangled names begin with this prefix.
16+
All Swift-mangled names begin with a common prefix. Since Swift 4.0, the
17+
compiler has used variations of the mangling described in this document, though
18+
pre-stable versions may not exactly conform to this description. By using
19+
distinct prefixes, tools can attempt to accommodate bugs and version variations
20+
in pre-stable versions of Swift.
1521

1622
The basic mangling scheme is a list of 'operators' where the operators are
1723
structured in a post-fix order. For example the mangling may start with an
@@ -20,8 +26,6 @@ identifier has to be interpreted::
2026

2127
4Test3FooC // The trailing 'C' says that 'Foo' is a class in module 'Test'
2228

23-
24-
2529
Operators are either identifiers or a sequence of one or more characters,
2630
like ``C`` for class.
2731
All operators share the same name-space. Important operators are a single
@@ -42,6 +46,48 @@ mangled name will start with the module name (after the ``_S``).
4246
In the following, productions which are only _part_ of an operator, are
4347
named with uppercase letters.
4448

49+
Symbolic references
50+
~~~~~~~~~~~~~~~~~~~
51+
52+
The Swift compiler emits mangled names into binary images to encode
53+
references to types for runtime instantiation and reflection. In a binary,
54+
these mangled names may embed pointers to runtime data
55+
structures in order to more efficiently represent locally-defined types.
56+
We call these pointers **symbolic references**.
57+
These references will be introduced by a control character in the range
58+
`\x01` ... `\x1F`, which indicates the kind of symbolic reference, followed by
59+
some number of arbitrary bytes *which may include null bytes*. Code that
60+
processes mangled names out of Swift binaries needs to be aware of symbolic
61+
references in order to properly terminate strings; a null terminator may be
62+
part of a symbolic reference.
63+
64+
::
65+
66+
symbolic-reference ::= [\x01-\x17] .{4} // Relative symbolic reference
67+
#if sizeof(void*) == 8
68+
symbolic-reference ::= [\x18-\x1F] .{8} // Absolute symbolic reference
69+
#elif sizeof(void*) == 4
70+
symbolic-reference ::= [\x18-\x1F] .{4} // Absolute symbolic reference
71+
#endif
72+
73+
Symbolic references are only valid in compiler-emitted metadata structures
74+
and must only appear in read-only parts of a binary image. APIs and tools
75+
that interpret Swift mangled names from potentially uncontrolled inputs must
76+
refuse to interpret symbolic references.
77+
78+
The following symbolic reference kinds are currently implemented:
79+
80+
::
81+
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+
// The grammatical role of the symbolic reference is determined by the
85+
// kind of context descriptor referenced
86+
87+
protocol-conformance-ref ::= '\x03' .{4} // Reference points directly to protocol conformance descriptor (NOT IMPLEMENTED)
88+
protocol-conformance-ref ::= '\x04' .{4} // Reference points indirectly to protocol conformance descriptor (NOT IMPLEMENTED)
89+
90+
4591
Globals
4692
~~~~~~~
4793

@@ -84,7 +130,7 @@ Globals
84130
global ::= protocol-conformance 'WP' // protocol witness table
85131
global ::= protocol-conformance 'Wa' // protocol witness table accessor
86132

87-
global ::= protocol-conformance 'WG' // generic protocol witness table
133+
global ::= protocol-conformance 'WG' // generic protocol witness table (HISTORICAL)
88134
global ::= protocol-conformance 'Wp' // protocol witness table pattern
89135
global ::= protocol-conformance 'Wr' // resilient witness table (HISTORICAL)
90136
global ::= protocol-conformance 'WI' // generic protocol witness table instantiation function
@@ -549,18 +595,36 @@ Generics
549595

550596
::
551597

552-
protocol-conformance ::= type protocol module generic-signature?
598+
protocol-conformance-context ::= protocol module generic-signature?
599+
600+
protocol-conformance ::= type protocol-conformance-context
553601

554602
``<protocol-conformance>`` refers to a type's conformance to a protocol. The
555603
named module is the one containing the extension or type declaration that
556604
declared the conformance.
557605

558606
::
559607

608+
protocol-conformance ::= type protocol
609+
610+
If ``type`` is a generic parameter or associated type of one, then no module
611+
is mangled, because the conformance must be resolved from the generic
612+
environment.
613+
560614
protocol-conformance ::= context identifier protocol identifier generic-signature? // Property behavior conformance
561615

562616
Property behaviors are implemented using private protocol conformances.
563617

618+
::
619+
620+
concrete-protocol-conformance ::= type protocol-conformance-ref
621+
protocol-conformance-ref ::= protocol module?
622+
623+
A compact representation used to represent mangled protocol conformance witness
624+
arguments at runtime. The ``module`` is only specified for conformances that
625+
are "retroactive", meaning that the context in which the conformance is defined
626+
is in neither the protocol or type module.
627+
564628
::
565629

566630
generic-signature ::= requirement* 'l' // one generic parameter

include/swift/ABI/Metadata.h

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1989,7 +1989,7 @@ struct TargetResilientWitnessTable final
19891989
using ResilientWitnessTable = TargetResilientWitnessTable<InProcess>;
19901990

19911991
/// \brief The control structure of a generic or resilient protocol
1992-
/// conformance.
1992+
/// conformance, which is embedded in the protocol conformance descriptor.
19931993
///
19941994
/// Witness tables need to be instantiated at runtime in these cases:
19951995
/// - For a generic conforming type, associated type requirements might be
@@ -2245,14 +2245,16 @@ struct TargetProtocolConformanceDescriptor final
22452245
RelativeContextPointer<Runtime>,
22462246
TargetGenericRequirementDescriptor<Runtime>,
22472247
TargetResilientWitnessesHeader<Runtime>,
2248-
TargetResilientWitness<Runtime>> {
2248+
TargetResilientWitness<Runtime>,
2249+
TargetGenericWitnessTable<Runtime>> {
22492250

22502251
using TrailingObjects = swift::ABI::TrailingObjects<
22512252
TargetProtocolConformanceDescriptor<Runtime>,
22522253
RelativeContextPointer<Runtime>,
22532254
TargetGenericRequirementDescriptor<Runtime>,
22542255
TargetResilientWitnessesHeader<Runtime>,
2255-
TargetResilientWitness<Runtime>>;
2256+
TargetResilientWitness<Runtime>,
2257+
TargetGenericWitnessTable<Runtime>>;
22562258
friend TrailingObjects;
22572259

22582260
template<typename T>
@@ -2268,6 +2270,7 @@ struct TargetProtocolConformanceDescriptor final
22682270

22692271
using ResilientWitnessesHeader = TargetResilientWitnessesHeader<Runtime>;
22702272
using ResilientWitness = TargetResilientWitness<Runtime>;
2273+
using GenericWitnessTable = TargetGenericWitnessTable<Runtime>;
22712274

22722275
private:
22732276
/// The protocol being conformed to.
@@ -2375,6 +2378,14 @@ struct TargetProtocolConformanceDescriptor final
23752378
numTrailingObjects(OverloadToken<ResilientWitness>()));
23762379
}
23772380

2381+
ConstTargetPointer<Runtime, GenericWitnessTable>
2382+
getGenericWitnessTable() const {
2383+
if (!Flags.hasGenericWitnessTable())
2384+
return nullptr;
2385+
2386+
return this->template getTrailingObjects<GenericWitnessTable>();
2387+
}
2388+
23782389
#if !defined(NDEBUG) && SWIFT_OBJC_INTEROP
23792390
void dump() const;
23802391
#endif
@@ -2409,6 +2420,10 @@ struct TargetProtocolConformanceDescriptor final
24092420
->NumWitnesses
24102421
: 0;
24112422
}
2423+
2424+
size_t numTrailingObjects(OverloadToken<GenericWitnessTable>) const {
2425+
return Flags.hasGenericWitnessTable() ? 1 : 0;
2426+
}
24122427
};
24132428
using ProtocolConformanceDescriptor
24142429
= TargetProtocolConformanceDescriptor<InProcess>;

include/swift/ABI/MetadataValues.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,7 @@ class ConformanceFlags {
629629
NumConditionalRequirementsShift = 8,
630630

631631
HasResilientWitnessesMask = 0x01 << 16,
632+
HasGenericWitnessTableMask = 0x01 << 17,
632633
};
633634

634635
int_type Value;
@@ -668,6 +669,14 @@ class ConformanceFlags {
668669
: 0));
669670
}
670671

672+
ConformanceFlags withHasGenericWitnessTable(
673+
bool hasGenericWitnessTable) const {
674+
return ConformanceFlags((Value & ~HasGenericWitnessTableMask)
675+
| (hasGenericWitnessTable
676+
? HasGenericWitnessTableMask
677+
: 0));
678+
}
679+
671680
/// Retrieve the conformance kind.
672681
ConformanceKind getConformanceKind() const {
673682
return ConformanceKind(Value & ConformanceKindMask);
@@ -709,6 +718,12 @@ class ConformanceFlags {
709718
return Value & HasResilientWitnessesMask;
710719
}
711720

721+
/// Whether this conformance has a generic witness table that may need to
722+
/// be instantiated.
723+
bool hasGenericWitnessTable() const {
724+
return Value & HasGenericWitnessTableMask;
725+
}
726+
712727
int_type getIntValue() const { return Value; }
713728
};
714729

include/swift/AST/ASTMangler.h

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,22 @@ class ASTMangler : public Mangler {
4646
/// If disabled, it is an error to try to mangle such an entity.
4747
bool AllowNamelessEntities = false;
4848

49-
/// If nonnull, provides a callback to encode symbolic references to
50-
/// type contexts.
51-
std::function<bool (const DeclContext *Context)>
52-
CanSymbolicReference;
53-
54-
std::vector<std::pair<const DeclContext *, unsigned>> SymbolicReferences;
49+
/// If enabled, some entities will be emitted as symbolic reference
50+
/// placeholders. The offsets of these references will be stored in the
51+
/// `SymbolicReferences` vector, and it is up to the consumer of the mangling
52+
/// to fill these in.
53+
bool AllowSymbolicReferences = false;
54+
55+
public:
56+
using SymbolicReferent = llvm::PointerUnion<const NominalTypeDecl *,
57+
const ProtocolConformance *>;
58+
protected:
59+
60+
/// If set, the mangler calls this function to determine whether to symbolic
61+
/// reference a given entity. Defaults to always returning true.
62+
std::function<bool (SymbolicReferent)> CanSymbolicReference;
63+
64+
std::vector<std::pair<SymbolicReferent, unsigned>> SymbolicReferences;
5565

5666
public:
5767
enum class SymbolKind {
@@ -292,7 +302,7 @@ class ASTMangler : public Mangler {
292302

293303
void appendOpParamForLayoutConstraint(LayoutConstraint Layout);
294304

295-
void appendSymbolicReference(const DeclContext *context);
305+
void appendSymbolicReference(SymbolicReferent referent);
296306

297307
std::string mangleTypeWithoutPrefix(Type type) {
298308
appendType(type);

include/swift/Demangling/Demangle.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ namespace llvm {
3333
namespace swift {
3434
namespace Demangle {
3535

36+
enum class SymbolicReferenceKind : uint8_t;
37+
3638
struct DemangleOptions {
3739
bool SynthesizeSugarOnTypes = false;
3840
bool DisplayDebuggerGeneratedModule = true;
@@ -473,7 +475,9 @@ void mangleIdentifier(const char *data, size_t length,
473475
/// This should always round-trip perfectly with demangleSymbolAsNode.
474476
std::string mangleNode(const NodePointer &root);
475477

476-
using SymbolicResolver = llvm::function_ref<Demangle::NodePointer (const void *)>;
478+
using SymbolicResolver =
479+
llvm::function_ref<Demangle::NodePointer (SymbolicReferenceKind,
480+
const void *)>;
477481

478482
/// \brief Remangle a demangled parse tree, using a callback to resolve
479483
/// symbolic references.
@@ -537,6 +541,8 @@ class DemanglerPrinter {
537541
return std::move(*this << std::forward<T>(x));
538542
}
539543

544+
DemanglerPrinter &writeHex(unsigned long long n) &;
545+
540546
std::string &&str() && { return std::move(Stream); }
541547

542548
llvm::StringRef getStringRef() const { return Stream; }

include/swift/Demangling/DemangleNodes.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ NODE(PrefixOperator)
143143
NODE(PrivateDeclName)
144144
NODE(PropertyDescriptor)
145145
CONTEXT_NODE(Protocol)
146+
CONTEXT_NODE(ProtocolSymbolicReference)
146147
NODE(ProtocolConformance)
147148
NODE(ProtocolDescriptor)
148149
NODE(ProtocolConformanceDescriptor)
@@ -172,13 +173,13 @@ NODE(SpecializationIsFragile)
172173
CONTEXT_NODE(Static)
173174
CONTEXT_NODE(Structure)
174175
CONTEXT_NODE(Subscript)
175-
CONTEXT_NODE(SymbolicReference)
176176
NODE(Suffix)
177177
NODE(ThinFunctionType)
178178
NODE(Tuple)
179179
NODE(TupleElement)
180180
NODE(TupleElementName)
181181
NODE(Type)
182+
CONTEXT_NODE(TypeSymbolicReference)
182183
CONTEXT_NODE(TypeAlias)
183184
NODE(TypeList)
184185
NODE(TypeMangling)
@@ -192,7 +193,6 @@ NODE(TypeMetadataLazyCache)
192193
NODE(UncurriedFunctionType)
193194
#define REF_STORAGE(Name, ...) NODE(Name)
194195
#include "swift/AST/ReferenceStorage.def"
195-
CONTEXT_NODE(UnresolvedSymbolicReference)
196196
CONTEXT_NODE(UnsafeAddressor)
197197
CONTEXT_NODE(UnsafeMutableAddressor)
198198
NODE(ValueWitness)

include/swift/Demangling/Demangler.h

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,17 @@ class CharVector : public Vector<char> {
280280
}
281281
};
282282

283+
/// Kinds of symbolic reference supported.
284+
enum class SymbolicReferenceKind : uint8_t {
285+
/// A symbolic reference to a context descriptor, representing the
286+
/// (unapplied generic) context.
287+
Context,
288+
};
289+
290+
using SymbolicReferenceResolver_t = NodePointer (SymbolicReferenceKind,
291+
Directness,
292+
int32_t, const void *);
293+
283294
/// The demangler.
284295
///
285296
/// It de-mangles a string and it also owns the returned node-tree. This means
@@ -301,7 +312,7 @@ class Demangler : public NodeFactory {
301312
StringRef Words[MaxNumWords];
302313
int NumWords = 0;
303314

304-
std::function<NodePointer (int32_t, const void *)> SymbolicReferenceResolver;
315+
std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver;
305316

306317
bool nextIf(StringRef str) {
307318
if (!Text.substr(Pos).startswith(str)) return false;
@@ -472,7 +483,8 @@ class Demangler : public NodeFactory {
472483

473484
NodePointer demangleObjCTypeName();
474485
NodePointer demangleTypeMangling();
475-
NodePointer demangleSymbolicReference(const void *at);
486+
NodePointer demangleSymbolicReference(unsigned char rawKind,
487+
const void *at);
476488

477489
void dump();
478490

@@ -483,7 +495,7 @@ class Demangler : public NodeFactory {
483495

484496
/// Install a resolver for symbolic references in a mangled string.
485497
void setSymbolicReferenceResolver(
486-
std::function<NodePointer (int32_t, const void*)> resolver) {
498+
std::function<SymbolicReferenceResolver_t> resolver) {
487499
SymbolicReferenceResolver = resolver;
488500
}
489501

0 commit comments

Comments
 (0)