Decode opaque types in the runtime demangler.

This commit is contained in:
Joe Groff
2019-03-14 20:53:26 -07:00
parent a3c17bd080
commit 95c43f4e18
17 changed files with 397 additions and 171 deletions

View File

@@ -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

View File

@@ -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.");
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -562,6 +562,9 @@ protected:
NodePointer demangleSymbolicReference(unsigned char rawKind,
const void *at);
bool demangleBoundGenerics(Vector<NodePointer> &TypeListList,
NodePointer &RetroactiveConformances);
void dump();
public:

View File

@@ -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();
}

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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);

View File

@@ -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));

View File

@@ -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 ";

View File

@@ -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");
}

View File

@@ -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");

View File

@@ -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");
}

View File

@@ -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");
}

View File

@@ -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 &param = 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 &param = 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;