Skip to content

[WIP] Protocol conformance decoder #39246

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions docs/ABI/Mangling.rst
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,13 @@ The following symbolic reference kinds are currently implemented:
// The grammatical role of the symbolic reference is determined by the
// kind of context descriptor referenced

protocol-conformance-ref ::= '\x03' .{4} // Reference points directly to protocol conformance descriptor (NOT IMPLEMENTED)
protocol-conformance-ref ::= '\x04' .{4} // Reference points indirectly to protocol conformance descriptor (NOT IMPLEMENTED)
#if SWIFT_RUNTIME_VERSION >= 5.5
protocol-conformance-ref ::= '\x03' .{4} // Reference points directly to protocol conformance descriptor
protocol-conformance-ref ::= '\x04' .{4} // Reference points indirectly to protocol conformance descriptor

dependent-associated-conformance ::= '\x05' .{4} // Reference points directly to associated conformance descriptor (NOT IMPLEMENTED)
dependent-associated-conformance ::= '\x06' .{4} // Reference points indirectly to associated conformance descriptor (NOT IMPLEMENTED)
dependent-associated-conformance ::= '\x05' .{4} // Reference points directly to associated conformance descriptor
dependent-associated-conformance ::= '\x06' .{4} // Reference points indirectly to associated conformance descriptor
#endif

associated-conformance-access-function ::= '\x07' .{4} // Reference points directly to associated conformance access function relative to the protocol
associated-conformance-access-function ::= '\x08' .{4} // Reference points directly to associated conformance access function relative to the conforming type
Expand Down Expand Up @@ -833,6 +835,20 @@ fixed position. An index of 1 ("0\_") is used to indicate "unknown"; all other
values are adjusted by 2. That these indexes are not 0-based is a bug that's
now codified into the ABI; the index 0 is therefore reserved.

For example, if we have a conformance ``C: Collection``, and we're mangling
the path required to extract ``C.Iterator: IteratorProtocol``, the path would
be::

C: Collection -> C: Sequence -> C.Iterator: IteratorProtocol

So we mangle::

<C> <Collection> 'HD' <index>
<Sequence> 'HI' <index>
<C.Iterator> <IteratorProtocol> 'HA' <index>

(where items in angle brackets are themselves to be mangled).

::

generic-signature ::= requirement* 'l' // one generic parameter
Expand Down
37 changes: 37 additions & 0 deletions include/swift/AST/ASTDemangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ class ASTBuilder {
using BuiltType = swift::Type;
using BuiltTypeDecl = swift::GenericTypeDecl *; // nominal or type alias
using BuiltProtocolDecl = swift::ProtocolDecl *;
using BuiltProtocolConformance = swift::ProtocolConformanceRef;
using BuiltProtocolConformanceDecl = swift::ProtocolConformance *;

explicit ASTBuilder(ASTContext &ctx) : Ctx(ctx) {}

ASTContext &getASTContext() { return Ctx; }
Expand Down Expand Up @@ -163,6 +166,40 @@ class ASTBuilder {
Type createDictionaryType(Type key, Type value);

Type createParenType(Type base);

ProtocolConformanceRef
createConcreteProtocolConformance(Type conformingType,
ProtocolConformance *conformanceDecl,
ArrayRef<ProtocolConformanceRef> args);

ProtocolConformanceRef
createDependentProtocolConformanceRoot(Type conformingType,
ProtocolDecl *requirement,
unsigned index);

ProtocolConformanceRef
createDependentProtocolConformanceAssociated(ProtocolConformanceRef base,
Type conformingType,
ProtocolDecl *requirement,
unsigned index);

ProtocolConformanceRef
createDependentProtocolConformanceInherited(ProtocolConformanceRef base,
BuiltProtocolDecl requirement,
unsigned index);

ProtocolConformance *
createProtocolConformanceDeclInTypeModule(Type conformingType,
ProtocolDecl *protocol);

ProtocolConformance *
createProtocolConformanceDeclInProtocolModule(Type conformingType,
ProtocolDecl *protocol);

ProtocolConformance *
createProtocolConformanceDeclRetroactive(Type conformingType,
ProtocolDecl *protocol,
StringRef moduleName);

LayoutConstraint getLayoutConstraint(LayoutConstraintKind kind);
LayoutConstraint getLayoutConstraintWithSizeAlign(LayoutConstraintKind kind,
Expand Down
3 changes: 2 additions & 1 deletion include/swift/AST/ASTMangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ class ASTMangler : public Mangler {

public:
using SymbolicReferent = llvm::PointerUnion<const NominalTypeDecl *,
const OpaqueTypeDecl *>;
const OpaqueTypeDecl *,
const ProtocolConformance *>;
protected:

/// If set, the mangler calls this function to determine whether to symbolic
Expand Down
10 changes: 4 additions & 6 deletions include/swift/Basic/Unreachable.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,10 @@

#include "swift/Runtime/Config.h"

SWIFT_RUNTIME_ATTRIBUTE_NORETURN
inline static void swift_unreachable(const char *msg) {
assert(false && msg);
(void)msg;
abort();
}
#define swift_unreachable(msg) do { \
assert(false && (msg)); \
abort(); \
} while (0)

#endif

Expand Down
6 changes: 6 additions & 0 deletions include/swift/Demangling/DemangleNodes.def
Original file line number Diff line number Diff line change
Expand Up @@ -320,5 +320,11 @@ NODE(IndexSubset)
NODE(AsyncAwaitResumePartialFunction)
NODE(AsyncSuspendResumePartialFunction)

// Added in Swift 5.6
NODE(AssociatedConformanceProtocolRelativeAccessor)
NODE(AssociatedConformanceTypeRelativeAccessor)
NODE(ProtocolConformanceDescriptorRef)
NODE(AssociatedConformanceDescriptorRef)

#undef CONTEXT_NODE
#undef NODE
23 changes: 23 additions & 0 deletions include/swift/Demangling/Demangler.h
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,13 @@ enum class SymbolicReferenceKind : uint8_t {
/// A symbolic reference to a context descriptor, representing the
/// (unapplied generic) context.
Context,
/// A protocol conformance descriptor.
ProtocolConformanceDescriptor,
/// An associated conformance descriptor.
AssociatedConformanceDescriptor,
/// An associated conformance access function.
AssociatedConformanceProtocolRelativeAccessor,
AssociatedConformanceTypeRelativeAccessor,
/// A symbolic reference to an accessor function, which can be executed in
/// the process to get a pointer to the referenced entity.
AccessorFunctionReference,
Expand Down Expand Up @@ -618,6 +625,21 @@ class Demangler : public NodeFactory {
NodePointer demangleType(StringRef MangledName,
std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver
= nullptr);

/// Demangle the given protocol conformance and return the parse tree.
///
/// \param MangledName The mangled conformance string, which does _not_ start
/// with the mangling prefix $S.
/// \param SymbolicReferenceResolver A function invoked to resolve symbolic references in
/// the string. If null, then symbolic references will cause the demangle to fail.
///
/// \returns A parse tree for the demangled string - or a null pointer
/// on failure.
/// The lifetime of the returned node tree ends with the lifetime of the
/// Demangler or with a call of clear().
NodePointer demangleConformance(StringRef MangledName,
std::function<SymbolicReferenceResolver_t> SymbolicReferenceResolver
= nullptr);
};

/// A demangler which uses stack space for its initial memory.
Expand All @@ -634,6 +656,7 @@ template <size_t Size> class StackAllocatedDemangler : public Demangler {

NodePointer demangleOldSymbolAsNode(StringRef MangledName,
NodeFactory &Factory);

SWIFT_END_INLINE_NAMESPACE
} // end namespace Demangle
} // end namespace swift
Expand Down
Loading