mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
replace ProtocolConformanceTypeKind with TypeMetadataRecordKind metadata reference does not need to be indirectable more efficient check for protocol conformances remove swift_getMangledTypeName(), not needed yet kill off Remangle.cpp for non-ObjC builds cleanup cleanup cleanup comments
230 lines
8.7 KiB
C++
230 lines
8.7 KiB
C++
#include "../../../lib/Basic/Demangle.cpp"
|
|
#include "../../../lib/Basic/Punycode.cpp"
|
|
#include "swift/Runtime/Metadata.h"
|
|
#include "Private.h"
|
|
|
|
#if SWIFT_OBJC_INTEROP
|
|
#include <objc/runtime.h>
|
|
#endif
|
|
|
|
// Build a demangled type tree for a nominal type.
|
|
static Demangle::NodePointer
|
|
_buildDemanglingForNominalType(Demangle::Node::Kind boundGenericKind,
|
|
const Metadata *type,
|
|
const NominalTypeDescriptor *description) {
|
|
using namespace Demangle;
|
|
|
|
// Demangle the base name.
|
|
auto node = demangleTypeAsNode(description->Name,
|
|
strlen(description->Name));
|
|
// If generic, demangle the type parameters.
|
|
if (description->GenericParams.NumPrimaryParams > 0) {
|
|
auto typeParams = NodeFactory::create(Node::Kind::TypeList);
|
|
auto typeBytes = reinterpret_cast<const char *>(type);
|
|
auto genericParam = reinterpret_cast<const Metadata * const *>(
|
|
typeBytes + sizeof(void*) * description->GenericParams.Offset);
|
|
for (unsigned i = 0, e = description->GenericParams.NumPrimaryParams;
|
|
i < e; ++i, ++genericParam) {
|
|
auto demangling = _swift_buildDemanglingForMetadata(*genericParam);
|
|
if (demangling == nullptr)
|
|
return nullptr;
|
|
typeParams->addChild(demangling);
|
|
}
|
|
|
|
auto genericNode = NodeFactory::create(boundGenericKind);
|
|
genericNode->addChild(node);
|
|
genericNode->addChild(typeParams);
|
|
return genericNode;
|
|
}
|
|
return node;
|
|
}
|
|
|
|
// Build a demangled type tree for a type.
|
|
Demangle::NodePointer swift::_swift_buildDemanglingForMetadata(const Metadata *type) {
|
|
using namespace Demangle;
|
|
|
|
switch (type->getKind()) {
|
|
case MetadataKind::Class: {
|
|
auto classType = static_cast<const ClassMetadata *>(type);
|
|
return _buildDemanglingForNominalType(Node::Kind::BoundGenericClass,
|
|
type, classType->getDescription());
|
|
}
|
|
case MetadataKind::Enum:
|
|
case MetadataKind::Optional: {
|
|
auto structType = static_cast<const EnumMetadata *>(type);
|
|
return _buildDemanglingForNominalType(Node::Kind::BoundGenericEnum,
|
|
type, structType->Description);
|
|
}
|
|
case MetadataKind::Struct: {
|
|
auto structType = static_cast<const StructMetadata *>(type);
|
|
return _buildDemanglingForNominalType(Node::Kind::BoundGenericStructure,
|
|
type, structType->Description);
|
|
}
|
|
case MetadataKind::ObjCClassWrapper: {
|
|
#if SWIFT_OBJC_INTEROP
|
|
auto objcWrapper = static_cast<const ObjCClassWrapperMetadata *>(type);
|
|
const char *className = class_getName((Class)objcWrapper->Class);
|
|
|
|
// ObjC classes mangle as being in the magic "__ObjC" module.
|
|
auto module = NodeFactory::create(Node::Kind::Module, "__ObjC");
|
|
|
|
auto node = NodeFactory::create(Node::Kind::Class);
|
|
node->addChild(module);
|
|
node->addChild(NodeFactory::create(Node::Kind::Identifier,
|
|
llvm::StringRef(className)));
|
|
|
|
return node;
|
|
#else
|
|
assert(false && "no ObjC interop");
|
|
return nullptr;
|
|
#endif
|
|
}
|
|
case MetadataKind::ForeignClass: {
|
|
auto foreign = static_cast<const ForeignClassMetadata *>(type);
|
|
return Demangle::demangleTypeAsNode(foreign->getName(),
|
|
strlen(foreign->getName()));
|
|
}
|
|
case MetadataKind::Existential: {
|
|
auto exis = static_cast<const ExistentialTypeMetadata *>(type);
|
|
NodePointer proto_list = NodeFactory::create(Node::Kind::ProtocolList);
|
|
NodePointer type_list = NodeFactory::create(Node::Kind::TypeList);
|
|
|
|
proto_list->addChild(type_list);
|
|
|
|
std::vector<const ProtocolDescriptor *> protocols;
|
|
protocols.reserve(exis->Protocols.NumProtocols);
|
|
for (unsigned i = 0, e = exis->Protocols.NumProtocols; i < e; ++i)
|
|
protocols.push_back(exis->Protocols[i]);
|
|
|
|
// Sort the protocols by their mangled names.
|
|
// The ordering in the existential type metadata is by metadata pointer,
|
|
// which isn't necessarily stable across invocations.
|
|
std::sort(protocols.begin(), protocols.end(),
|
|
[](const ProtocolDescriptor *a, const ProtocolDescriptor *b) -> bool {
|
|
return strcmp(a->Name, b->Name) < 0;
|
|
});
|
|
|
|
for (auto *protocol : protocols) {
|
|
// The protocol name is mangled as a type symbol, with the _Tt prefix.
|
|
auto protocolNode = demangleSymbolAsNode(protocol->Name,
|
|
strlen(protocol->Name));
|
|
|
|
// ObjC protocol names aren't mangled.
|
|
if (!protocolNode) {
|
|
auto module = NodeFactory::create(Node::Kind::Module,
|
|
MANGLING_MODULE_OBJC);
|
|
auto node = NodeFactory::create(Node::Kind::Protocol);
|
|
node->addChild(module);
|
|
node->addChild(NodeFactory::create(Node::Kind::Identifier,
|
|
llvm::StringRef(protocol->Name)));
|
|
auto typeNode = NodeFactory::create(Node::Kind::Type);
|
|
typeNode->addChild(node);
|
|
type_list->addChild(typeNode);
|
|
continue;
|
|
}
|
|
|
|
// FIXME: We have to dig through a ridiculous number of nodes to get
|
|
// to the Protocol node here.
|
|
protocolNode = protocolNode->getChild(0); // Global -> TypeMangling
|
|
protocolNode = protocolNode->getChild(0); // TypeMangling -> Type
|
|
protocolNode = protocolNode->getChild(0); // Type -> ProtocolList
|
|
protocolNode = protocolNode->getChild(0); // ProtocolList -> TypeList
|
|
protocolNode = protocolNode->getChild(0); // TypeList -> Type
|
|
|
|
assert(protocolNode->getKind() == Node::Kind::Type);
|
|
assert(protocolNode->getChild(0)->getKind() == Node::Kind::Protocol);
|
|
type_list->addChild(protocolNode);
|
|
}
|
|
|
|
return proto_list;
|
|
}
|
|
case MetadataKind::ExistentialMetatype: {
|
|
auto metatype = static_cast<const ExistentialMetatypeMetadata *>(type);
|
|
auto instance = _swift_buildDemanglingForMetadata(metatype->InstanceType);
|
|
auto node = NodeFactory::create(Node::Kind::ExistentialMetatype);
|
|
node->addChild(instance);
|
|
return node;
|
|
}
|
|
case MetadataKind::Function: {
|
|
auto func = static_cast<const FunctionTypeMetadata *>(type);
|
|
|
|
Node::Kind kind;
|
|
switch (func->getConvention()) {
|
|
case FunctionMetadataConvention::Swift:
|
|
kind = Node::Kind::FunctionType;
|
|
break;
|
|
case FunctionMetadataConvention::Block:
|
|
kind = Node::Kind::ObjCBlock;
|
|
break;
|
|
case FunctionMetadataConvention::CFunctionPointer:
|
|
kind = Node::Kind::CFunctionPointer;
|
|
break;
|
|
case FunctionMetadataConvention::Thin:
|
|
kind = Node::Kind::ThinFunctionType;
|
|
break;
|
|
}
|
|
|
|
std::vector<NodePointer> inputs;
|
|
for (unsigned i = 0, e = func->getNumArguments(); i < e; ++i) {
|
|
auto arg = func->getArguments()[i];
|
|
auto input = _swift_buildDemanglingForMetadata(arg.getPointer());
|
|
if (arg.getFlag()) {
|
|
NodePointer inout = NodeFactory::create(Node::Kind::InOut);
|
|
inout->addChild(input);
|
|
input = inout;
|
|
}
|
|
inputs.push_back(input);
|
|
}
|
|
|
|
NodePointer totalInput;
|
|
if (inputs.size() > 1) {
|
|
auto tuple = NodeFactory::create(Node::Kind::NonVariadicTuple);
|
|
for (auto &input : inputs)
|
|
tuple->addChild(input);
|
|
totalInput = tuple;
|
|
} else {
|
|
totalInput = inputs.front();
|
|
}
|
|
|
|
NodePointer args = NodeFactory::create(Node::Kind::ArgumentTuple);
|
|
args->addChild(totalInput);
|
|
|
|
NodePointer resultTy = _swift_buildDemanglingForMetadata(func->ResultType);
|
|
NodePointer result = NodeFactory::create(Node::Kind::ReturnType);
|
|
result->addChild(resultTy);
|
|
|
|
auto funcNode = NodeFactory::create(kind);
|
|
if (func->throws())
|
|
funcNode->addChild(NodeFactory::create(Node::Kind::ThrowsAnnotation));
|
|
funcNode->addChild(args);
|
|
funcNode->addChild(result);
|
|
return funcNode;
|
|
}
|
|
case MetadataKind::Metatype: {
|
|
auto metatype = static_cast<const MetatypeMetadata *>(type);
|
|
auto instance = _swift_buildDemanglingForMetadata(metatype->InstanceType);
|
|
auto node = NodeFactory::create(Node::Kind::Metatype);
|
|
node->addChild(instance);
|
|
return node;
|
|
}
|
|
case MetadataKind::Tuple: {
|
|
auto tuple = static_cast<const TupleTypeMetadata *>(type);
|
|
auto tupleNode = NodeFactory::create(Node::Kind::NonVariadicTuple);
|
|
for (unsigned i = 0, e = tuple->NumElements; i < e; ++i) {
|
|
auto elt = _swift_buildDemanglingForMetadata(tuple->getElement(i).Type);
|
|
tupleNode->addChild(elt);
|
|
}
|
|
return tupleNode;
|
|
}
|
|
case MetadataKind::Opaque:
|
|
// FIXME: Some opaque types do have manglings, but we don't have enough info
|
|
// to figure them out.
|
|
case MetadataKind::HeapLocalVariable:
|
|
case MetadataKind::HeapGenericLocalVariable:
|
|
case MetadataKind::ErrorObject:
|
|
break;
|
|
}
|
|
// Not a type.
|
|
return nullptr;
|
|
}
|