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

@@ -84,7 +84,12 @@ ResolveAsSymbolicReference::operator()(SymbolicReferenceKind kind,
nodeKind = Node::Kind::ProtocolSymbolicReference;
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 { };
// 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 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);
}
// 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,82 +1178,15 @@ 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();
if (!accessFunction) return BuiltType();
@@ -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;