//===----------------------------------------------------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// #include "swift/Runtime/Metadata.h" #include "swift/Strings.h" #include "Private.h" #include #if SWIFT_OBJC_INTEROP #include #endif using namespace swift; // FIXME: This stuff should be merged with the existing logic in // include/swift/Reflection/TypeRefBuilder.h as part of the rewrite // to change stdlib reflection over to using remote mirrors. Demangle::NodePointer swift::_swift_buildDemanglingForMetadata(const Metadata *type, Demangle::Demangler &Dem); // Build a demangled type tree for a nominal type. static Demangle::NodePointer _buildDemanglingForNominalType(const Metadata *type, Demangle::Demangler &Dem) { using namespace Demangle; const Metadata *parent; Node::Kind boundGenericKind; const NominalTypeDescriptor *description; // Demangle the parent type, if any. switch (type->getKind()) { case MetadataKind::Class: { auto classType = static_cast(type); #if SWIFT_OBJC_INTEROP // Peek through artificial subclasses. while (classType->isTypeMetadata() && classType->isArtificialSubclass()) classType = classType->SuperClass; #endif parent = classType->getParentType(classType->getDescription()); boundGenericKind = Node::Kind::BoundGenericClass; description = classType->getDescription(); break; } case MetadataKind::Enum: case MetadataKind::Optional: { auto enumType = static_cast(type); parent = enumType->Parent; boundGenericKind = Node::Kind::BoundGenericEnum; description = enumType->Description; break; } case MetadataKind::Struct: { auto structType = static_cast(type); parent = structType->Parent; boundGenericKind = Node::Kind::BoundGenericStructure; description = structType->Description; break; } default: return nullptr; } // Demangle the base name. auto node = Dem.demangleType(StringRef(description->Name)); assert(node->getKind() == Node::Kind::Type); // Demangle the parent. if (parent) { auto parentNode = _swift_buildDemanglingForMetadata(parent, Dem); if (parentNode->getKind() == Node::Kind::Type) parentNode = parentNode->getChild(0); auto typeNode = node->getChild(0); auto newTypeNode = Dem.createNode(typeNode->getKind()); newTypeNode->addChild(parentNode, Dem); newTypeNode->addChild(typeNode->getChild(1), Dem); auto newNode = Dem.createNode(Node::Kind::Type); newNode->addChild(newTypeNode, Dem); node = newNode; } // If generic, demangle the type parameters. if (description->GenericParams.NumPrimaryParams > 0) { auto typeParams = Dem.createNode(Node::Kind::TypeList); auto typeBytes = reinterpret_cast(type); auto genericParam = reinterpret_cast( typeBytes + sizeof(void*) * description->GenericParams.Offset); for (unsigned i = 0, e = description->GenericParams.NumPrimaryParams; i < e; ++i, ++genericParam) { auto demangling = _swift_buildDemanglingForMetadata(*genericParam, Dem); if (demangling == nullptr) return nullptr; typeParams->addChild(demangling, Dem); } auto genericNode = Dem.createNode(boundGenericKind); genericNode->addChild(node, Dem); genericNode->addChild(typeParams, Dem); return genericNode; } return node; } // Build a demangled type tree for a type. Demangle::NodePointer swift::_swift_buildDemanglingForMetadata(const Metadata *type, Demangle::Demangler &Dem) { using namespace Demangle; switch (type->getKind()) { case MetadataKind::Class: case MetadataKind::Enum: case MetadataKind::Optional: case MetadataKind::Struct: return _buildDemanglingForNominalType(type, Dem); case MetadataKind::ObjCClassWrapper: { #if SWIFT_OBJC_INTEROP auto objcWrapper = static_cast(type); const char *className = class_getName((Class)objcWrapper->Class); // ObjC classes mangle as being in the magic "__ObjC" module. auto module = Dem.createNode(Node::Kind::Module, "__ObjC"); auto node = Dem.createNode(Node::Kind::Class); node->addChild(module, Dem); node->addChild(Dem.createNode(Node::Kind::Identifier, llvm::StringRef(className)), Dem); return node; #else assert(false && "no ObjC interop"); return nullptr; #endif } case MetadataKind::ForeignClass: { auto foreign = static_cast(type); return Dem.demangleType(foreign->getName()); } case MetadataKind::Existential: { auto exis = static_cast(type); std::vector protocols; protocols.reserve(exis->Protocols.NumProtocols); for (unsigned i = 0, e = exis->Protocols.NumProtocols; i < e; ++i) protocols.push_back(exis->Protocols[i]); auto type_list = Dem.createNode(Node::Kind::TypeList); auto proto_list = Dem.createNode(Node::Kind::ProtocolList); proto_list->addChild(type_list, Dem); // The protocol descriptors should be pre-sorted since the compiler will // only ever make a swift_getExistentialTypeMetadata invocation using // its canonical ordering of protocols. for (auto *protocol : protocols) { // The protocol name is mangled as a type symbol, with the _Tt prefix. StringRef ProtoName(protocol->Name); NodePointer protocolNode = Dem.demangleSymbol(ProtoName); // ObjC protocol names aren't mangled. if (!protocolNode) { auto module = Dem.createNode(Node::Kind::Module, MANGLING_MODULE_OBJC); auto node = Dem.createNode(Node::Kind::Protocol); node->addChild(module, Dem); node->addChild(Dem.createNode(Node::Kind::Identifier, llvm::StringRef(protocol->Name)), Dem); auto typeNode = Dem.createNode(Node::Kind::Type); typeNode->addChild(node, Dem); type_list->addChild(typeNode, Dem); 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, Dem); } if (auto superclass = exis->getSuperclassConstraint()) { // If there is a superclass constraint, we mangle it specially. auto result = Dem.createNode(Node::Kind::ProtocolListWithClass); auto superclassNode = _swift_buildDemanglingForMetadata(superclass, Dem); result->addChild(proto_list, Dem); result->addChild(superclassNode, Dem); return result; } if (exis->isClassBounded()) { // Check if the class constraint is implied by any of our // protocols. bool requiresClassImplicit = false; for (auto *protocol : protocols) { if (protocol->Flags.getClassConstraint() == ProtocolClassConstraint::Class) requiresClassImplicit = true; } // If it was implied, we don't do anything special. if (requiresClassImplicit) return proto_list; // If the existential type has an explicit AnyObject constraint, // we must mangle it as such. auto result = Dem.createNode(Node::Kind::ProtocolListWithAnyObject); result->addChild(proto_list, Dem); return result; } // Just a simple composition of protocols. return proto_list; } case MetadataKind::ExistentialMetatype: { auto metatype = static_cast(type); auto instance = _swift_buildDemanglingForMetadata(metatype->InstanceType, Dem); auto node = Dem.createNode(Node::Kind::ExistentialMetatype); node->addChild(instance, Dem); return node; } case MetadataKind::Function: { auto func = static_cast(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 inputs; for (unsigned i = 0, e = func->getNumArguments(); i < e; ++i) { auto arg = func->getArguments()[i]; auto input = _swift_buildDemanglingForMetadata(arg.getPointer(), Dem); if (arg.getFlag()) { NodePointer inout = Dem.createNode(Node::Kind::InOut); inout->addChild(input, Dem); input = inout; } inputs.push_back(input); } NodePointer totalInput = nullptr; if (inputs.size() > 1) { auto tuple = Dem.createNode(Node::Kind::Tuple); for (auto &input : inputs) tuple->addChild(input, Dem); totalInput = tuple; } else { totalInput = inputs.front(); } NodePointer args = Dem.createNode(Node::Kind::ArgumentTuple); args->addChild(totalInput, Dem); NodePointer resultTy = _swift_buildDemanglingForMetadata(func->ResultType, Dem); NodePointer result = Dem.createNode(Node::Kind::ReturnType); result->addChild(resultTy, Dem); auto funcNode = Dem.createNode(kind); if (func->throws()) funcNode->addChild(Dem.createNode(Node::Kind::ThrowsAnnotation), Dem); funcNode->addChild(args, Dem); funcNode->addChild(result, Dem); return funcNode; } case MetadataKind::Metatype: { auto metatype = static_cast(type); auto instance = _swift_buildDemanglingForMetadata(metatype->InstanceType, Dem); auto typeNode = Dem.createNode(Node::Kind::Type); typeNode->addChild(instance, Dem); auto node = Dem.createNode(Node::Kind::Metatype); node->addChild(typeNode, Dem); return node; } case MetadataKind::Tuple: { auto tuple = static_cast(type); const char *labels = tuple->Labels; auto tupleNode = Dem.createNode(Node::Kind::Tuple); for (unsigned i = 0, e = tuple->NumElements; i < e; ++i) { auto elt = Dem.createNode(Node::Kind::TupleElement); // Add a label child if applicable: if (labels) { // Look for the next space in the labels string. if (const char *space = strchr(labels, ' ')) { // If there is one, and the label isn't empty, add a label child. if (labels != space) { auto eltName = Dem.createNode(Node::Kind::TupleElementName, llvm::StringRef(labels, space - labels)); elt->addChild(eltName, Dem); } // Skip past the space. labels = space + 1; } } // Add the element type child. auto eltType = _swift_buildDemanglingForMetadata(tuple->getElement(i).Type, Dem); elt->addChild(eltType, Dem); // Add the completed element to the tuple. tupleNode->addChild(elt, Dem); } 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; }