mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Decode opaque types in the runtime demangler.
This commit is contained in:
@@ -78,8 +78,13 @@ The following symbolic reference kinds are currently implemented:
|
||||
|
||||
::
|
||||
|
||||
{any-generic-type, protocol} ::= '\x01' .{4} // Reference points directly to context descriptor
|
||||
{any-generic-type, protocol} ::= '\x02' .{4} // Reference points indirectly to context descriptor
|
||||
#if SWIFT_RUNTIME_VERSION < 5.1
|
||||
{any-generic-type, protocol} ::= '\x01' .{4} // Reference points directly to context descriptor
|
||||
{any-generic-type, protocol} ::= '\x02' .{4} // Reference points indirectly to context descriptor
|
||||
#else
|
||||
{any-generic-type, protocol, opaque-type-decl-name} ::= '\x01' .{4} // Reference points directly to context descriptor
|
||||
{any-generic-type, protocol, opaque-type-decl-name} ::= '\x02' .{4} // Reference points indirectly to context descriptor
|
||||
#endif
|
||||
// The grammatical role of the symbolic reference is determined by the
|
||||
// kind of context descriptor referenced
|
||||
|
||||
@@ -93,15 +98,13 @@ The following symbolic reference kinds are currently implemented:
|
||||
associated-conformance-access-function ::= '\x08' .{4} // Reference points directly to associated conformance access function relative to the conforming type
|
||||
|
||||
// keypaths only in Swift 5.0, generalized in Swift 5.1
|
||||
metadata-access-function ::= '\x09' .{4} // Reference points directly to metadata access function that can be invoked to produce referenced object
|
||||
#if SWIFT_RUNTIME_VERSION >= 5.1
|
||||
metadata-access-function ::= '\x09' .{4} // Reference points directly to metadata access function that can be invoked to produce referenced object
|
||||
#endif
|
||||
|
||||
// begin added in Swift 5.1
|
||||
any-generic-type ::= '\x0B' .{4} // Reference points directly to an opaque type descriptor
|
||||
any-generic-type ::= '\x0C' .{4} // Reference points indirectly to an opaque type descriptor
|
||||
// end added in Swift 5.1
|
||||
|
||||
A mangled name may also include ``\xFF`` bytes, which are only used for alignment
|
||||
padding. They can be skipped over and ignored.
|
||||
A mangled name may also include ``\xFF`` bytes, which are only used for
|
||||
alignment padding. They do not affect what the mangled name references and can
|
||||
be skipped over and ignored.
|
||||
|
||||
Globals
|
||||
~~~~~~~
|
||||
@@ -120,7 +123,9 @@ Globals
|
||||
global ::= nominal-type 'Ml' // in-place type initialization cache
|
||||
global ::= nominal-type 'Mm' // class metaclass
|
||||
global ::= nominal-type 'Mn' // nominal type descriptor
|
||||
global ::= opaque-type-decl-name 'MQ' // opaque type descriptor -- added in Swift 5.1
|
||||
#if SWIFT_RUNTIME_VERSION >= 5.1
|
||||
global ::= opaque-type-decl-name 'MQ' // opaque type descriptor -- added in Swift 5.1
|
||||
#endif
|
||||
global ::= nominal-type 'Mu' // class method lookup function
|
||||
global ::= nominal-type 'MU' // ObjC metadata update callback function
|
||||
global ::= nominal-type 'Ms' // ObjC resilient class stub
|
||||
@@ -613,14 +618,12 @@ implementation details of a function type.
|
||||
|
||||
::
|
||||
|
||||
// begin added in Swift 5.1
|
||||
#if SWIFT_VERSION >= 5.1
|
||||
type ::= 'Qr' // opaque result type (of current decl)
|
||||
type ::= opaque-type-decl-name bound-generic-args 'Qo' INDEX // opaque type
|
||||
|
||||
type ::= 'Qr' // opaque result type (of current decl)
|
||||
type ::= opaque-type-decl-name bound-generic-args 'Qo' // opaque type
|
||||
|
||||
opaque-type-decl-name ::= entity 'QO' // opaque result type of specified decl
|
||||
|
||||
// end added in Swift 5.1
|
||||
opaque-type-decl-name ::= entity 'QO' // opaque result type of specified decl
|
||||
#endif
|
||||
|
||||
Opaque return types have a special short representation in the mangling of
|
||||
their defining entity. In structural position, opaque types are fully qualified
|
||||
|
||||
@@ -3027,6 +3027,11 @@ private:
|
||||
using OverloadToken = typename TrailingObjects::template OverloadToken<T>;
|
||||
|
||||
public:
|
||||
using TrailingGenericContextObjects::getGenericContext;
|
||||
using TrailingGenericContextObjects::getGenericContextHeader;
|
||||
using TrailingGenericContextObjects::getFullGenericContextHeader;
|
||||
using TrailingGenericContextObjects::getGenericParams;
|
||||
|
||||
// The kind-specific flags area is used to store the count of the generic
|
||||
// arguments for underlying type(s) encoded in the descriptor.
|
||||
unsigned getNumUnderlyingTypeArguments() const {
|
||||
@@ -3038,9 +3043,12 @@ public:
|
||||
return getNumUnderlyingTypeArguments();
|
||||
}
|
||||
|
||||
const char * getUnderlyingTypeArgument(unsigned i) const {
|
||||
StringRef getUnderlyingTypeArgument(unsigned i) const {
|
||||
assert(i < getNumUnderlyingTypeArguments());
|
||||
return (this->template getTrailingObjects<RelativeDirectPointer<const char>>())[i];
|
||||
const char *ptr =
|
||||
(this->template getTrailingObjects<RelativeDirectPointer<const char>>())[i];
|
||||
|
||||
return Demangle::makeSymbolicMangledNameStringRef(ptr);
|
||||
}
|
||||
|
||||
static bool classof(const TargetContextDescriptor<Runtime> *cd) {
|
||||
@@ -4257,6 +4265,9 @@ TargetContextDescriptor<Runtime>::getGenericContext() const {
|
||||
case ContextDescriptorKind::Struct:
|
||||
return llvm::cast<TargetStructDescriptor<Runtime>>(this)
|
||||
->getGenericContext();
|
||||
case ContextDescriptorKind::OpaqueType:
|
||||
return llvm::cast<TargetOpaqueTypeDescriptor<Runtime>>(this)
|
||||
->getGenericContext();
|
||||
default:
|
||||
// We don't know about this kind of descriptor.
|
||||
return nullptr;
|
||||
@@ -4308,6 +4319,8 @@ TargetTypeContextDescriptor<Runtime>::getGenericParams() const {
|
||||
return llvm::cast<TargetEnumDescriptor<Runtime>>(this)->getGenericParams();
|
||||
case ContextDescriptorKind::Struct:
|
||||
return llvm::cast<TargetStructDescriptor<Runtime>>(this)->getGenericParams();
|
||||
case ContextDescriptorKind::OpaqueType:
|
||||
return llvm::cast<TargetOpaqueTypeDescriptor<Runtime>>(this)->getGenericParams();
|
||||
default:
|
||||
swift_runtime_unreachable("Not a type context descriptor.");
|
||||
}
|
||||
|
||||
@@ -83,6 +83,10 @@ public:
|
||||
|
||||
Type createBoundGenericType(GenericTypeDecl *decl, ArrayRef<Type> args);
|
||||
|
||||
Type resolveOpaqueType(NodePointer opaqueDescriptor,
|
||||
ArrayRef<Type> args,
|
||||
unsigned ordinal);
|
||||
|
||||
Type createBoundGenericType(GenericTypeDecl *decl, ArrayRef<Type> args,
|
||||
Type parent);
|
||||
|
||||
|
||||
@@ -59,13 +59,19 @@ protected:
|
||||
|
||||
public:
|
||||
using SymbolicReferent = llvm::PointerUnion<const NominalTypeDecl *,
|
||||
const ProtocolConformance *>;
|
||||
const OpaqueTypeDecl *>;
|
||||
protected:
|
||||
|
||||
/// If set, the mangler calls this function to determine whether to symbolic
|
||||
/// reference a given entity. Defaults to always returning true.
|
||||
/// reference a given entity. If null, the mangler acts as if it's set to
|
||||
/// always return true.
|
||||
std::function<bool (SymbolicReferent)> CanSymbolicReference;
|
||||
|
||||
bool canSymbolicReference(SymbolicReferent referent) {
|
||||
return AllowSymbolicReferences
|
||||
&& (!CanSymbolicReference || CanSymbolicReference(referent));
|
||||
}
|
||||
|
||||
std::vector<std::pair<SymbolicReferent, unsigned>> SymbolicReferences;
|
||||
|
||||
public:
|
||||
@@ -237,7 +243,8 @@ protected:
|
||||
|
||||
/// Append any retroactive conformances.
|
||||
void appendRetroactiveConformances(Type type);
|
||||
|
||||
void appendRetroactiveConformances(SubstitutionMap subMap,
|
||||
ModuleDecl *fromModule);
|
||||
void appendImplFunctionType(SILFunctionType *fn);
|
||||
|
||||
void appendContextOf(const ValueDecl *decl);
|
||||
|
||||
@@ -262,11 +262,12 @@ NODE(SugaredDictionary)
|
||||
NODE(SugaredParen)
|
||||
|
||||
// Added in Swift 5.1
|
||||
NODE(AccessorFunctionReference)
|
||||
NODE(OpaqueType)
|
||||
NODE(OpaqueTypeDescriptorSymbolicReference)
|
||||
NODE(OpaqueTypeDescriptor)
|
||||
NODE(OpaqueReturnType)
|
||||
NODE(OpaqueReturnTypeOf)
|
||||
NODE(AccessorFunctionReference)
|
||||
|
||||
#undef CONTEXT_NODE
|
||||
#undef NODE
|
||||
|
||||
@@ -562,6 +562,9 @@ protected:
|
||||
NodePointer demangleSymbolicReference(unsigned char rawKind,
|
||||
const void *at);
|
||||
|
||||
bool demangleBoundGenerics(Vector<NodePointer> &TypeListList,
|
||||
NodePointer &RetroactiveConformances);
|
||||
|
||||
void dump();
|
||||
|
||||
public:
|
||||
|
||||
@@ -318,7 +318,8 @@ class TypeDecoder {
|
||||
SmallVector<BuiltType, 8> args;
|
||||
|
||||
const auto &genericArgs = Node->getChild(1);
|
||||
assert(genericArgs->getKind() == NodeKind::TypeList);
|
||||
if (genericArgs->getKind() != NodeKind::TypeList)
|
||||
return BuiltType();
|
||||
|
||||
for (auto genericArg : *genericArgs) {
|
||||
auto paramType = decodeMangledType(genericArg);
|
||||
@@ -777,6 +778,35 @@ class TypeDecoder {
|
||||
|
||||
return Builder.createParenType(base);
|
||||
}
|
||||
case NodeKind::OpaqueType: {
|
||||
if (Node->getNumChildren() < 3)
|
||||
return BuiltType();
|
||||
auto descriptor = Node->getChild(0);
|
||||
auto ordinalNode = Node->getChild(1);
|
||||
|
||||
if (ordinalNode->getKind() != NodeKind::Index
|
||||
|| !ordinalNode->hasIndex())
|
||||
return BuiltType();
|
||||
auto ordinal = ordinalNode->getIndex();
|
||||
|
||||
std::vector<BuiltType> genericArgs;
|
||||
auto boundGenerics = Node->getChild(2);
|
||||
for (unsigned i = 0; i < boundGenerics->getNumChildren(); ++i) {
|
||||
auto genericsNode = boundGenerics->getChild(i);
|
||||
if (genericsNode->getKind() != NodeKind::TypeList)
|
||||
break;
|
||||
for (auto argNode : *genericsNode) {
|
||||
auto arg = decodeMangledType(argNode);
|
||||
if (!arg)
|
||||
return BuiltType();
|
||||
genericArgs.push_back(arg);
|
||||
}
|
||||
}
|
||||
|
||||
return Builder.resolveOpaqueType(descriptor, genericArgs, ordinal);
|
||||
}
|
||||
// TODO: Handle OpaqueReturnType, when we're in the middle of reconstructing
|
||||
// the defining decl
|
||||
default:
|
||||
return BuiltType();
|
||||
}
|
||||
|
||||
@@ -279,6 +279,14 @@ public:
|
||||
return BoundGenericTypeRef::create(*this, *mangledName, args, parent);
|
||||
}
|
||||
|
||||
const TypeRef *
|
||||
resolveOpaqueType(NodePointer opaqueDescriptor,
|
||||
const std::vector<const TypeRef *> &genericArgs,
|
||||
unsigned ordinal) {
|
||||
// TODO
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const TupleTypeRef *
|
||||
createTupleType(ArrayRef<const TypeRef *> elements,
|
||||
std::string &&labels, bool isVariadic) {
|
||||
|
||||
@@ -247,6 +247,13 @@ Type ASTBuilder::createBoundGenericType(GenericTypeDecl *decl,
|
||||
return substType;
|
||||
}
|
||||
|
||||
Type ASTBuilder::resolveOpaqueType(NodePointer opaqueDescriptor,
|
||||
ArrayRef<Type> args,
|
||||
unsigned ordinal) {
|
||||
// TODO
|
||||
return Type();
|
||||
}
|
||||
|
||||
Type ASTBuilder::createBoundGenericType(GenericTypeDecl *decl,
|
||||
ArrayRef<Type> args,
|
||||
Type parent) {
|
||||
|
||||
@@ -732,7 +732,9 @@ static bool shouldMangleAsGeneric(Type type) {
|
||||
}
|
||||
|
||||
void ASTMangler::appendOpaqueDeclName(const OpaqueTypeDecl *opaqueDecl) {
|
||||
if (auto namingDecl = opaqueDecl->getNamingDecl()) {
|
||||
if (canSymbolicReference(opaqueDecl)) {
|
||||
appendSymbolicReference(opaqueDecl);
|
||||
} else if (auto namingDecl = opaqueDecl->getNamingDecl()) {
|
||||
appendEntity(namingDecl);
|
||||
appendOperator("QO");
|
||||
} else {
|
||||
@@ -976,13 +978,24 @@ void ASTMangler::appendType(Type type, const ValueDecl *forDecl) {
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, use the fully qualified mangling.
|
||||
// Otherwise, try to substitute it.
|
||||
if (tryMangleTypeSubstitution(type))
|
||||
return;
|
||||
|
||||
// Use the fully elaborated explicit mangling.
|
||||
appendOpaqueDeclName(opaqueDecl);
|
||||
bool isFirstArgList = true;
|
||||
appendBoundGenericArgs(opaqueDecl->getInnermostDeclContext(),
|
||||
opaqueType->getSubstitutions(),
|
||||
isFirstArgList);
|
||||
appendOperator("Qo");
|
||||
appendRetroactiveConformances(opaqueType->getSubstitutions(),
|
||||
opaqueDecl->getParentModule());
|
||||
|
||||
// TODO: If we support multiple opaque types in a return, put the
|
||||
// ordinal for this archetype here.
|
||||
appendOperator("Qo", Index(0));
|
||||
|
||||
addTypeSubstitution(type);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1297,6 +1310,29 @@ static bool containsRetroactiveConformance(
|
||||
return false;
|
||||
}
|
||||
|
||||
void ASTMangler::appendRetroactiveConformances(SubstitutionMap subMap,
|
||||
ModuleDecl *fromModule) {
|
||||
if (subMap.empty()) return;
|
||||
|
||||
unsigned numProtocolRequirements = 0;
|
||||
for (auto conformance : subMap.getConformances()) {
|
||||
SWIFT_DEFER {
|
||||
++numProtocolRequirements;
|
||||
};
|
||||
|
||||
// Ignore abstract conformances.
|
||||
if (!conformance.isConcrete())
|
||||
continue;
|
||||
|
||||
// Skip non-retroactive conformances.
|
||||
if (!containsRetroactiveConformance(conformance.getConcrete(), fromModule))
|
||||
continue;
|
||||
|
||||
appendConcreteProtocolConformance(conformance.getConcrete());
|
||||
appendOperator("g", Index(numProtocolRequirements));
|
||||
}
|
||||
}
|
||||
|
||||
void ASTMangler::appendRetroactiveConformances(Type type) {
|
||||
// Dig out the substitution map to use.
|
||||
SubstitutionMap subMap;
|
||||
@@ -1315,25 +1351,7 @@ void ASTMangler::appendRetroactiveConformances(Type type) {
|
||||
subMap = type->getContextSubstitutionMap(module, nominal);
|
||||
}
|
||||
|
||||
if (subMap.empty()) return;
|
||||
|
||||
unsigned numProtocolRequirements = 0;
|
||||
for (auto conformance : subMap.getConformances()) {
|
||||
SWIFT_DEFER {
|
||||
++numProtocolRequirements;
|
||||
};
|
||||
|
||||
// Ignore abstract conformances.
|
||||
if (!conformance.isConcrete())
|
||||
continue;
|
||||
|
||||
// Skip non-retroactive conformances.
|
||||
if (!containsRetroactiveConformance(conformance.getConcrete(), module))
|
||||
continue;
|
||||
|
||||
appendConcreteProtocolConformance(conformance.getConcrete());
|
||||
appendOperator("g", Index(numProtocolRequirements));
|
||||
}
|
||||
appendRetroactiveConformances(subMap, module);
|
||||
}
|
||||
|
||||
static char getParamConvention(ParameterConvention conv) {
|
||||
@@ -1700,8 +1718,7 @@ void ASTMangler::appendProtocolName(const ProtocolDecl *protocol,
|
||||
return;
|
||||
|
||||
// We can use a symbolic reference if they're allowed in this context.
|
||||
if (AllowSymbolicReferences
|
||||
&& (!CanSymbolicReference || CanSymbolicReference(protocol))) {
|
||||
if (canSymbolicReference(protocol)) {
|
||||
// Try to use a symbolic reference substitution.
|
||||
if (tryMangleSubstitution(protocol))
|
||||
return;
|
||||
@@ -1762,15 +1779,12 @@ void ASTMangler::appendAnyGenericType(const GenericTypeDecl *decl) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Try to mangle a symbolic reference for a nominal type.
|
||||
if (AllowSymbolicReferences) {
|
||||
if (nominal && (!CanSymbolicReference || CanSymbolicReference(nominal))) {
|
||||
appendSymbolicReference(nominal);
|
||||
// Substitutions can refer back to the symbolic reference.
|
||||
addTypeSubstitution(nominal->getDeclaredType());
|
||||
return;
|
||||
}
|
||||
if (nominal && canSymbolicReference(nominal)) {
|
||||
appendSymbolicReference(nominal);
|
||||
// Substitutions can refer back to the symbolic reference.
|
||||
addTypeSubstitution(nominal->getDeclaredType());
|
||||
return;
|
||||
}
|
||||
|
||||
appendContextOf(decl);
|
||||
|
||||
@@ -1521,8 +1521,9 @@ NodePointer Demangler::demangleRetroactiveConformance() {
|
||||
return createWithChildren(Node::Kind::RetroactiveConformance, index, conformance);
|
||||
}
|
||||
|
||||
NodePointer Demangler::demangleBoundGenericType() {
|
||||
NodePointer RetroactiveConformances = nullptr;
|
||||
bool Demangler::demangleBoundGenerics(Vector<NodePointer> &TypeListList,
|
||||
NodePointer &RetroactiveConformances) {
|
||||
RetroactiveConformances = nullptr;
|
||||
while (auto RetroactiveConformance =
|
||||
popNode(Node::Kind::RetroactiveConformance)) {
|
||||
if (!RetroactiveConformances)
|
||||
@@ -1532,7 +1533,6 @@ NodePointer Demangler::demangleBoundGenericType() {
|
||||
if (RetroactiveConformances)
|
||||
RetroactiveConformances->reverseChildren();
|
||||
|
||||
Vector<NodePointer> TypeListList(*this, 4);
|
||||
for (;;) {
|
||||
NodePointer TList = createNode(Node::Kind::TypeList);
|
||||
TypeListList.push_back(TList, *this);
|
||||
@@ -1544,10 +1544,24 @@ NodePointer Demangler::demangleBoundGenericType() {
|
||||
if (popNode(Node::Kind::EmptyList))
|
||||
break;
|
||||
if (!popNode(Node::Kind::FirstElementMarker))
|
||||
return nullptr;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
NodePointer Demangler::demangleBoundGenericType() {
|
||||
NodePointer RetroactiveConformances;
|
||||
Vector<NodePointer> TypeListList(*this, 4);
|
||||
|
||||
if (!demangleBoundGenerics(TypeListList, RetroactiveConformances))
|
||||
return nullptr;
|
||||
|
||||
NodePointer Nominal = popTypeAndGetAnyGeneric();
|
||||
if (!Nominal)
|
||||
return nullptr;
|
||||
NodePointer BoundNode = demangleBoundGenericArgs(Nominal, TypeListList, 0);
|
||||
if (!BoundNode)
|
||||
return nullptr;
|
||||
addChild(BoundNode, RetroactiveConformances);
|
||||
NodePointer NTy = createType(BoundNode);
|
||||
addSubstitution(NTy);
|
||||
@@ -1811,7 +1825,7 @@ NodePointer Demangler::demangleMetatype() {
|
||||
case 'p':
|
||||
return createWithChild(Node::Kind::ProtocolDescriptor, popProtocol());
|
||||
case 'Q':
|
||||
return createWithPoppedType(Node::Kind::OpaqueTypeDescriptor);
|
||||
return createWithChild(Node::Kind::OpaqueTypeDescriptor, popNode());
|
||||
case 'S':
|
||||
return createWithChild(Node::Kind::ProtocolSelfConformanceDescriptor,
|
||||
popProtocol());
|
||||
@@ -1909,14 +1923,25 @@ NodePointer Demangler::demangleArchetype() {
|
||||
}
|
||||
case 'O': {
|
||||
auto definingContext = popContext();
|
||||
return createType(
|
||||
createWithChild(Node::Kind::OpaqueReturnTypeOf, definingContext));
|
||||
return createWithChild(Node::Kind::OpaqueReturnTypeOf, definingContext);
|
||||
}
|
||||
case 'o': {
|
||||
auto GenericArgs = popNode(/*Node::Kind::BoundGenericArgs*/);
|
||||
auto index = demangleIndex();
|
||||
Vector<NodePointer> boundGenericArgs;
|
||||
NodePointer retroactiveConformances;
|
||||
if (!demangleBoundGenerics(boundGenericArgs, retroactiveConformances))
|
||||
return nullptr;
|
||||
auto Name = popNode();
|
||||
return createType(
|
||||
createWithChildren(Node::Kind::OpaqueType, Name, GenericArgs));
|
||||
auto opaque = createWithChildren(Node::Kind::OpaqueType, Name,
|
||||
createNode(Node::Kind::Index, index));
|
||||
auto boundGenerics = createNode(Node::Kind::TypeList);
|
||||
for (unsigned i = boundGenericArgs.size(); i-- > 0;)
|
||||
boundGenerics->addChild(boundGenericArgs[i], *this);
|
||||
opaque->addChild(boundGenerics, *this);
|
||||
if (retroactiveConformances)
|
||||
opaque->addChild(retroactiveConformances, *this);
|
||||
|
||||
return createType(opaque);
|
||||
}
|
||||
case 'r': {
|
||||
return createType(createNode(Node::Kind::OpaqueReturnType));
|
||||
|
||||
@@ -513,6 +513,7 @@ private:
|
||||
case Node::Kind::DynamicallyReplaceableFunctionImpl:
|
||||
case Node::Kind::DynamicallyReplaceableFunctionVar:
|
||||
case Node::Kind::OpaqueType:
|
||||
case Node::Kind::OpaqueTypeDescriptorSymbolicReference:
|
||||
case Node::Kind::OpaqueReturnType:
|
||||
case Node::Kind::OpaqueReturnTypeOf:
|
||||
return false;
|
||||
@@ -1587,6 +1588,10 @@ NodePointer NodePrinter::print(NodePointer Node, bool asPrefixContext) {
|
||||
Printer << "type symbolic reference 0x";
|
||||
Printer.writeHex(Node->getIndex());
|
||||
return nullptr;
|
||||
case Node::Kind::OpaqueTypeDescriptorSymbolicReference:
|
||||
Printer << "opaque type symbolic reference 0x";
|
||||
Printer.writeHex(Node->getIndex());
|
||||
return nullptr;
|
||||
case Node::Kind::DynamicallyReplaceableFunctionKey:
|
||||
if (!Options.ShortenThunk) {
|
||||
Printer << "dynamically replaceable key for ";
|
||||
|
||||
@@ -2006,6 +2006,10 @@ void Remangler::mangleProtocolSymbolicReference(Node *node, EntityContext&) {
|
||||
unreachable("unsupported");
|
||||
}
|
||||
|
||||
void Remangler::mangleOpaqueTypeDescriptorSymbolicReference(Node *node) {
|
||||
unreachable("unsupported");
|
||||
}
|
||||
|
||||
void Remangler::mangleSugaredOptional(Node *node) {
|
||||
unreachable("unsupported");
|
||||
}
|
||||
|
||||
@@ -2307,6 +2307,11 @@ void Remangler::mangleProtocolSymbolicReference(Node *node) {
|
||||
(const void *)node->getIndex()));
|
||||
}
|
||||
|
||||
void Remangler::mangleOpaqueTypeDescriptorSymbolicReference(Node *node) {
|
||||
return mangle(Resolver(SymbolicReferenceKind::Context,
|
||||
(const void *)node->getIndex()));
|
||||
}
|
||||
|
||||
void Remangler::mangleSugaredOptional(Node *node) {
|
||||
mangleType(node->getChild(0));
|
||||
Buffer << "XSq";
|
||||
@@ -2337,8 +2342,19 @@ void Remangler::mangleOpaqueReturnTypeOf(Node *node) {
|
||||
}
|
||||
void Remangler::mangleOpaqueType(Node *node) {
|
||||
mangle(node->getChild(0));
|
||||
mangle(node->getChild(1));
|
||||
auto boundGenerics = node->getChild(2);
|
||||
for (unsigned i = 0; i < boundGenerics->getNumChildren(); ++i) {
|
||||
Buffer << (i == 0 ? 'y' : '_');
|
||||
mangleChildNodes(boundGenerics->getChild(i));
|
||||
}
|
||||
if (node->getNumChildren() >= 4) {
|
||||
auto retroactiveConformances = node->getChild(3);
|
||||
for (unsigned i = 0; i < retroactiveConformances->getNumChildren(); ++i) {
|
||||
mangle(retroactiveConformances->getChild(i));
|
||||
}
|
||||
}
|
||||
Buffer << "Qo";
|
||||
mangleIndex(node->getChild(1)->getIndex());
|
||||
}
|
||||
void Remangler::mangleAccessorFunctionReference(Node *node) {
|
||||
unreachable("can't remangle");
|
||||
|
||||
@@ -114,6 +114,9 @@ IRGenMangler::withSymbolicReferences(IRGenModule &IGM,
|
||||
if (proto->isObjC())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
} else if (auto opaque = s.dyn_cast<const OpaqueTypeDecl *>()) {
|
||||
// Always symbolically reference opaque types.
|
||||
return true;
|
||||
} else {
|
||||
llvm_unreachable("symbolic referent not handled");
|
||||
@@ -247,6 +250,8 @@ mangleSymbolNameForSymbolicMangling(const SymbolicMangling &mangling,
|
||||
Buffer << ' ';
|
||||
if (auto ty = referent.dyn_cast<const NominalTypeDecl*>())
|
||||
appendContext(ty);
|
||||
else if (auto opaque = referent.dyn_cast<const OpaqueTypeDecl*>())
|
||||
appendOpaqueDeclName(opaque);
|
||||
else
|
||||
llvm_unreachable("unhandled referent");
|
||||
}
|
||||
|
||||
@@ -359,6 +359,12 @@ llvm::Constant *IRGenModule::getAddrOfStringForTypeRef(
|
||||
}
|
||||
// \1 - direct reference, \2 - indirect reference
|
||||
baseKind = 1;
|
||||
} else if (auto copaque = symbolic.first.dyn_cast<const OpaqueTypeDecl*>()){
|
||||
auto opaque = const_cast<OpaqueTypeDecl*>(copaque);
|
||||
IRGen.noteUseOfOpaqueTypeDescriptor(opaque);
|
||||
ref = getAddrOfLLVMVariableOrGOTEquivalent(
|
||||
LinkEntity::forOpaqueTypeDescriptor(opaque));
|
||||
baseKind = 1;
|
||||
} else {
|
||||
llvm_unreachable("unhandled symbolic referent");
|
||||
}
|
||||
|
||||
@@ -85,6 +85,11 @@ ResolveAsSymbolicReference::operator()(SymbolicReferenceKind kind,
|
||||
isType = false;
|
||||
break;
|
||||
|
||||
case ContextDescriptorKind::OpaqueType:
|
||||
nodeKind = Node::Kind::OpaqueTypeDescriptorSymbolicReference;
|
||||
isType = false;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (auto typeContext = dyn_cast<TypeContextDescriptor>(descriptor)) {
|
||||
nodeKind = Node::Kind::TypeSymbolicReference;
|
||||
@@ -864,6 +869,112 @@ bool swift::_gatherGenericParameterCounts(
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Retrieve the generic parameters introduced in this context.
|
||||
static ArrayRef<GenericParamDescriptor> getLocalGenericParams(
|
||||
const ContextDescriptor *context) {
|
||||
if (!context->isGeneric())
|
||||
return { };
|
||||
|
||||
// Determine where to start looking at generic parameters.
|
||||
unsigned startParamIndex;
|
||||
if (auto parent = context->Parent.get())
|
||||
startParamIndex = parent->getNumGenericParams();
|
||||
else
|
||||
startParamIndex = 0;
|
||||
|
||||
auto genericContext = context->getGenericContext();
|
||||
return genericContext->getGenericParams().slice(startParamIndex);
|
||||
}
|
||||
|
||||
static bool _gatherGenericParameters(
|
||||
const ContextDescriptor *context,
|
||||
ArrayRef<const Metadata *> genericArgs,
|
||||
const Metadata *parent,
|
||||
SmallVectorImpl<unsigned> &genericParamCounts,
|
||||
SmallVectorImpl<const void *> &allGenericArgsVec,
|
||||
Demangler &demangler) {
|
||||
// Figure out the various levels of generic parameters we have in
|
||||
// this type.
|
||||
(void)_gatherGenericParameterCounts(context,
|
||||
genericParamCounts, demangler);
|
||||
unsigned numTotalGenericParams =
|
||||
genericParamCounts.empty() ? 0 : genericParamCounts.back();
|
||||
|
||||
// Check whether we have the right number of generic arguments.
|
||||
if (genericArgs.size() == getLocalGenericParams(context).size()) {
|
||||
// Okay: genericArgs is the innermost set of generic arguments.
|
||||
} else if (genericArgs.size() == numTotalGenericParams && !parent) {
|
||||
// Okay: genericArgs is the complete set of generic arguments.
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If there are generic parameters at any level, check the generic
|
||||
// requirements and fill in the generic arguments vector.
|
||||
if (!genericParamCounts.empty()) {
|
||||
// Compute the set of generic arguments "as written".
|
||||
SmallVector<const Metadata *, 8> allGenericArgs;
|
||||
|
||||
// If we have a parent, gather it's generic arguments "as written".
|
||||
if (parent) {
|
||||
gatherWrittenGenericArgs(parent, parent->getTypeContextDescriptor(),
|
||||
allGenericArgs, demangler);
|
||||
}
|
||||
|
||||
// Add the generic arguments we were given.
|
||||
allGenericArgs.insert(allGenericArgs.end(),
|
||||
genericArgs.begin(), genericArgs.end());
|
||||
|
||||
// Copy the generic arguments needed for metadata from the generic
|
||||
// arguments "as written".
|
||||
auto generics = context->getGenericContext();
|
||||
assert(generics);
|
||||
{
|
||||
auto genericParams = generics->getGenericParams();
|
||||
unsigned n = genericParams.size();
|
||||
if (allGenericArgs.size() != n) {
|
||||
return false;
|
||||
}
|
||||
for (unsigned i = 0; i != n; ++i) {
|
||||
const auto ¶m = genericParams[i];
|
||||
if (param.getKind() != GenericParamKind::Type)
|
||||
return false;
|
||||
if (param.hasExtraArgument())
|
||||
return false;
|
||||
|
||||
if (param.hasKeyArgument())
|
||||
allGenericArgsVec.push_back(allGenericArgs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// If we have the wrong number of generic arguments, fail.
|
||||
|
||||
// Check whether the generic requirements are satisfied, collecting
|
||||
// any extra arguments we need for the instantiation function.
|
||||
SubstGenericParametersFromWrittenArgs substitutions(allGenericArgs,
|
||||
genericParamCounts);
|
||||
bool failed =
|
||||
_checkGenericRequirements(generics->getGenericRequirements(),
|
||||
allGenericArgsVec,
|
||||
[&substitutions](unsigned depth, unsigned index) {
|
||||
return substitutions.getMetadata(depth, index);
|
||||
},
|
||||
[&substitutions](const Metadata *type, unsigned index) {
|
||||
return substitutions.getWitnessTable(type, index);
|
||||
});
|
||||
if (failed)
|
||||
return false;
|
||||
|
||||
// If we still have the wrong number of generic arguments, this is
|
||||
// some kind of metadata mismatch.
|
||||
if (generics->getGenericContextHeader().getNumArguments() !=
|
||||
allGenericArgsVec.size())
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
/// Find the offset of the protocol requirement for an associated type with
|
||||
@@ -913,21 +1024,18 @@ Optional<const ProtocolRequirement *> findAssociatedTypeByName(
|
||||
swift_runtime_unreachable("associated type names don't line up");
|
||||
}
|
||||
|
||||
/// Retrieve the generic parameters introduced in this context.
|
||||
static ArrayRef<GenericParamDescriptor> getLocalGenericParams(
|
||||
const ContextDescriptor *context) {
|
||||
if (!context->isGeneric())
|
||||
return { };
|
||||
static const OpaqueTypeDescriptor *
|
||||
_findOpaqueTypeDescriptor(NodePointer demangleNode,
|
||||
Demangler &dem) {
|
||||
// Directly resolve a symbolic reference.
|
||||
if (demangleNode->getKind()
|
||||
== Node::Kind::OpaqueTypeDescriptorSymbolicReference) {
|
||||
auto context = (const ContextDescriptor *)demangleNode->getIndex();
|
||||
return cast<OpaqueTypeDescriptor>(context);
|
||||
}
|
||||
|
||||
// Determine where to start looking at generic parameters.
|
||||
unsigned startParamIndex;
|
||||
if (auto parent = context->Parent.get())
|
||||
startParamIndex = parent->getNumGenericParams();
|
||||
else
|
||||
startParamIndex = 0;
|
||||
|
||||
auto genericContext = context->getGenericContext();
|
||||
return genericContext->getGenericParams().slice(startParamIndex);
|
||||
// TODO: Find non-symbolic-referenced opaque decls.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Constructs metadata by decoding a mangled type name, for use with
|
||||
@@ -960,14 +1068,45 @@ public:
|
||||
|
||||
Demangle::NodeFactory &getNodeFactory() { return demangler; }
|
||||
|
||||
BuiltType resolveOpaqueType(NodePointer opaqueDecl,
|
||||
ArrayRef<BuiltType> genericArgs,
|
||||
unsigned ordinal) {
|
||||
auto descriptor = _findOpaqueTypeDescriptor(opaqueDecl, demangler);
|
||||
if (!descriptor)
|
||||
return BuiltType();
|
||||
auto outerContext = descriptor->Parent.get();
|
||||
|
||||
// Gather the generic parameters we need to parameterize the opaque decl.
|
||||
SmallVector<unsigned, 8> genericParamCounts;
|
||||
SmallVector<const void *, 8> allGenericArgsVec;
|
||||
|
||||
if (!_gatherGenericParameters(outerContext,
|
||||
genericArgs,
|
||||
BuiltType(), /* no parent */
|
||||
genericParamCounts, allGenericArgsVec,
|
||||
demangler))
|
||||
return BuiltType();
|
||||
|
||||
auto mangledName = descriptor->getUnderlyingTypeArgument(ordinal);
|
||||
SubstGenericParametersFromMetadata substitutions(descriptor,
|
||||
allGenericArgsVec.data());
|
||||
return swift_getTypeByMangledName(MetadataState::Complete,
|
||||
mangledName, allGenericArgsVec.data(),
|
||||
[&substitutions](unsigned depth, unsigned index) {
|
||||
return substitutions.getMetadata(depth, index);
|
||||
},
|
||||
[&substitutions](const Metadata *type, unsigned index) {
|
||||
return substitutions.getWitnessTable(type, index);
|
||||
}).getMetadata();
|
||||
}
|
||||
|
||||
BuiltTypeDecl createTypeDecl(NodePointer node,
|
||||
bool &typeAlias) const {
|
||||
// Look for a nominal type descriptor based on its mangled name.
|
||||
return _findNominalTypeDescriptor(node, demangler);
|
||||
}
|
||||
|
||||
BuiltProtocolDecl createProtocolDecl(
|
||||
NodePointer node) const {
|
||||
BuiltProtocolDecl createProtocolDecl(NodePointer node) const {
|
||||
// Look for a protocol descriptor based on its mangled name.
|
||||
std::string mangledName;
|
||||
if (auto protocol = _findProtocolDescriptor(node, demangler, mangledName))
|
||||
@@ -1026,8 +1165,8 @@ public:
|
||||
}
|
||||
|
||||
BuiltType createBoundGenericType(BuiltTypeDecl anyTypeDecl,
|
||||
const ArrayRef<BuiltType> genericArgs,
|
||||
const BuiltType parent) const {
|
||||
ArrayRef<BuiltType> genericArgs,
|
||||
BuiltType parent) const {
|
||||
auto typeDecl = dyn_cast<TypeContextDescriptor>(anyTypeDecl);
|
||||
if (!typeDecl) {
|
||||
if (auto protocol = dyn_cast<ProtocolDescriptor>(anyTypeDecl))
|
||||
@@ -1039,81 +1178,14 @@ public:
|
||||
// Figure out the various levels of generic parameters we have in
|
||||
// this type.
|
||||
SmallVector<unsigned, 8> genericParamCounts;
|
||||
(void)_gatherGenericParameterCounts(typeDecl, genericParamCounts, demangler);
|
||||
unsigned numTotalGenericParams =
|
||||
genericParamCounts.empty() ? 0 : genericParamCounts.back();
|
||||
|
||||
// Check whether we have the right number of generic arguments.
|
||||
if (genericArgs.size() == getLocalGenericParams(typeDecl).size()) {
|
||||
// Okay: genericArgs is the innermost set of generic arguments.
|
||||
} else if (genericArgs.size() == numTotalGenericParams && !parent) {
|
||||
// Okay: genericArgs is the complete set of generic arguments.
|
||||
} else {
|
||||
return BuiltType();
|
||||
}
|
||||
|
||||
SmallVector<const void *, 8> allGenericArgsVec;
|
||||
|
||||
// If there are generic parameters at any level, check the generic
|
||||
// requirements and fill in the generic arguments vector.
|
||||
if (!genericParamCounts.empty()) {
|
||||
// Compute the set of generic arguments "as written".
|
||||
SmallVector<const Metadata *, 8> allGenericArgs;
|
||||
|
||||
// If we have a parent, gather it's generic arguments "as written".
|
||||
if (parent) {
|
||||
gatherWrittenGenericArgs(parent, parent->getTypeContextDescriptor(),
|
||||
allGenericArgs, demangler);
|
||||
}
|
||||
|
||||
// Add the generic arguments we were given.
|
||||
allGenericArgs.insert(allGenericArgs.end(),
|
||||
genericArgs.begin(), genericArgs.end());
|
||||
|
||||
// Copy the generic arguments needed for metadata from the generic
|
||||
// arguments "as written".
|
||||
auto genericContext = typeDecl->getGenericContext();
|
||||
{
|
||||
auto genericParams = genericContext->getGenericParams();
|
||||
unsigned n = genericParams.size();
|
||||
if (allGenericArgs.size() != n)
|
||||
return BuiltType();
|
||||
for (unsigned i = 0; i != n; ++i) {
|
||||
const auto ¶m = genericParams[i];
|
||||
if (param.getKind() != GenericParamKind::Type)
|
||||
return BuiltType();
|
||||
if (param.hasExtraArgument())
|
||||
return BuiltType();
|
||||
|
||||
if (param.hasKeyArgument())
|
||||
allGenericArgsVec.push_back(allGenericArgs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// If we have the wrong number of generic arguments, fail.
|
||||
|
||||
// Check whether the generic requirements are satisfied, collecting
|
||||
// any extra arguments we need for the instantiation function.
|
||||
SubstGenericParametersFromWrittenArgs substitutions(allGenericArgs,
|
||||
genericParamCounts);
|
||||
bool failed =
|
||||
_checkGenericRequirements(genericContext->getGenericRequirements(),
|
||||
allGenericArgsVec,
|
||||
[&substitutions](unsigned depth, unsigned index) {
|
||||
return substitutions.getMetadata(depth, index);
|
||||
},
|
||||
[&substitutions](const Metadata *type, unsigned index) {
|
||||
return substitutions.getWitnessTable(type, index);
|
||||
});
|
||||
if (failed)
|
||||
return BuiltType();
|
||||
|
||||
// If we still have the wrong number of generic arguments, this is
|
||||
// some kind of metadata mismatch.
|
||||
if (typeDecl->getGenericContextHeader().getNumArguments() !=
|
||||
allGenericArgsVec.size())
|
||||
return BuiltType();
|
||||
}
|
||||
if (!_gatherGenericParameters(typeDecl,
|
||||
genericArgs,
|
||||
parent,
|
||||
genericParamCounts, allGenericArgsVec,
|
||||
demangler))
|
||||
return BuiltType();
|
||||
|
||||
// Call the access function.
|
||||
auto accessFunction = typeDecl->getAccessFunction();
|
||||
@@ -1442,15 +1514,17 @@ swift_getOpaqueTypeMetadata(MetadataRequest request,
|
||||
const void * const *arguments,
|
||||
const OpaqueTypeDescriptor *descriptor,
|
||||
unsigned index) {
|
||||
auto mangledName = Demangle::makeSymbolicMangledNameStringRef(
|
||||
descriptor->getUnderlyingTypeArgument(index));
|
||||
auto mangledName = descriptor->getUnderlyingTypeArgument(index);
|
||||
SubstGenericParametersFromMetadata substitutions(descriptor, arguments);
|
||||
|
||||
return swift_getTypeByMangledName(request.getState(),
|
||||
mangledName,
|
||||
arguments,
|
||||
substitutions, substitutions)
|
||||
.getResponse();
|
||||
mangledName, arguments,
|
||||
[&substitutions](unsigned depth, unsigned index) {
|
||||
return substitutions.getMetadata(depth, index);
|
||||
},
|
||||
[&substitutions](const Metadata *type, unsigned index) {
|
||||
return substitutions.getWitnessTable(type, index);
|
||||
}).getResponse();
|
||||
}
|
||||
|
||||
SWIFT_CC(swift) SWIFT_RUNTIME_EXPORT
|
||||
@@ -1491,6 +1565,7 @@ getObjCClassByMangledName(const char * _Nonnull typeName,
|
||||
return NO;
|
||||
metadata = swift_getTypeByMangledNode(
|
||||
MetadataState::Complete, demangler, node,
|
||||
nullptr,
|
||||
/* no substitutions */
|
||||
[&](unsigned depth, unsigned index) {
|
||||
return nullptr;
|
||||
|
||||
Reference in New Issue
Block a user