NodePointer Remangler::getUnspecialized(Node *node) { switch (node->getKind()) { case Node::Kind::Structure: case Node::Kind::Enum: case Node::Kind::Class: { NodePointer result = NodeFactory::create(node->getKind()); NodePointer parentOrModule = node->getChild(0); if (isSpecialized(parentOrModule.get())) result->addChild(getUnspecialized(parentOrModule.get())); else result->addChild(parentOrModule); result->addChild(node->getChild(1)); return result; } case Node::Kind::BoundGenericStructure: case Node::Kind::BoundGenericEnum: case Node::Kind::BoundGenericClass: { NodePointer unboundType = node->getChild(0); assert(unboundType->getKind() == Node::Kind::Type); NodePointer nominalType = unboundType->getChild(0); if (isSpecialized(nominalType.get())) return getUnspecialized(nominalType.get()); else return nominalType; } default: unreachable("bad nominal type kind"); } }
TypeInfo swift::_getTypeByMangledName(StringRef typeName, SubstGenericParameterFn substGenericParam) { auto demangler = getDemanglerForRuntimeTypeResolution(); NodePointer node; // Check whether this is the convenience syntax "ModuleName.ClassName". auto getDotPosForConvenienceSyntax = [&]() -> size_t { size_t dotPos = typeName.find('.'); if (dotPos == llvm::StringRef::npos) return llvm::StringRef::npos; if (typeName.find('.', dotPos + 1) != llvm::StringRef::npos) return llvm::StringRef::npos; if (typeName.find('\1') != llvm::StringRef::npos) return llvm::StringRef::npos; return dotPos; }; auto dotPos = getDotPosForConvenienceSyntax(); if (dotPos != llvm::StringRef::npos) { // Form a demangle tree for this class. NodePointer classNode = demangler.createNode(Node::Kind::Class); NodePointer moduleNode = demangler.createNode(Node::Kind::Module, typeName.substr(0, dotPos)); NodePointer nameNode = demangler.createNode(Node::Kind::Identifier, typeName.substr(dotPos + 1)); classNode->addChild(moduleNode, demangler); classNode->addChild(nameNode, demangler); node = classNode; } else { // Demangle the type name. node = demangler.demangleType(typeName); if (!node) return TypeInfo(); } DecodedMetadataBuilder builder(demangler, substGenericParam, [](const Metadata *base, StringRef assocType, const ProtocolDescriptor *protocol) -> const Metadata * { // Look for a conformance of the base type to the protocol. auto witnessTable = swift_conformsToProtocol(base, protocol); if (!witnessTable) return nullptr; // Look for the named associated type within the protocol. auto assocTypeReq = findAssociatedTypeByName(protocol, assocType); if (!assocTypeReq) return nullptr; // Call the associated type access function. return swift_getAssociatedTypeWitness( MetadataState::Abstract, const_cast<WitnessTable *>(witnessTable), base, *assocTypeReq).Value; }); auto type = Demangle::decodeMangledType(builder, node); return {type, builder.getReferenceOwnership()}; }
TypeInfo swift::_getTypeByMangledName(StringRef typeName, SubstGenericParameterFn substGenericParam) { Demangler demangler; NodePointer node; // Check whether this is the convenience syntax "ModuleName.ClassName". size_t dotPos = typeName.find('.'); if (dotPos != llvm::StringRef::npos && typeName.find('.', dotPos + 1) == llvm::StringRef::npos) { // Form a demangle tree for this class. NodePointer classNode = demangler.createNode(Node::Kind::Class); NodePointer moduleNode = demangler.createNode(Node::Kind::Module, typeName.substr(0, dotPos)); NodePointer nameNode = demangler.createNode(Node::Kind::Identifier, typeName.substr(dotPos + 1)); classNode->addChild(moduleNode, demangler); classNode->addChild(nameNode, demangler); node = classNode; } else { // Demangle the type name. node = demangler.demangleType(typeName); if (!node) return TypeInfo(); } DecodedMetadataBuilder builder(demangler, substGenericParam, [](const Metadata *base, StringRef assocType, const ProtocolDescriptor *protocol) -> const Metadata * { // Look for a conformance of the base type to the protocol. auto witnessTable = swift_conformsToProtocol(base, protocol); if (!witnessTable) return nullptr; // Look for the named associated type within the protocol. auto assocTypeReqIndex = findAssociatedTypeByName(protocol, assocType); if (!assocTypeReqIndex) return nullptr; // Call the associated type access function. using AssociatedTypeAccessFn = const Metadata *(*)(const Metadata *base, const WitnessTable *); return ((const AssociatedTypeAccessFn *)witnessTable)[*assocTypeReqIndex] (base, witnessTable); }); auto type = Demangle::decodeMangledType(builder, node); return {type, builder.getOwnership()}; }
std::string SpecializationMangler::finalize() { StringRef MangledSpecialization(Storage.data(), Storage.size()); AttributeDemangler D; NodePointer TopLevel = D.createNode(Node::Kind::Global); D.demangleAndAddAsChildren(MangledSpecialization, TopLevel); StringRef FuncName = Function->getName(); NodePointer FuncTopLevel = nullptr; if (FuncName.startswith(MANGLING_PREFIX_STR)) { FuncTopLevel = D.demangleSymbol(FuncName); assert(FuncTopLevel); } if (!FuncTopLevel) { FuncTopLevel = D.createNode(Node::Kind::Global); FuncTopLevel->addChild(D.createNode(Node::Kind::Identifier, FuncName), D); } for (NodePointer FuncChild : *FuncTopLevel) { TopLevel->addChild(FuncChild, D); } std::string mangledName = Demangle::mangleNode(TopLevel); verify(mangledName); return mangledName; }
// 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<const ObjCClassWrapperMetadata *>(type); const char *className = class_getName(objcWrapper->getObjCClassObject()); // 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<const ForeignClassMetadata *>(type); return Dem.demangleType(foreign->getName()); } case MetadataKind::Existential: { auto exis = static_cast<const ExistentialTypeMetadata *>(type); 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]); 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<const ExistentialMetatypeMetadata *>(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<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->getNumParameters(); i < e; ++i) { auto param = func->getParameter(i); auto flags = func->getParameterFlags(i); auto input = _swift_buildDemanglingForMetadata(param, Dem); if (flags.isInOut()) { NodePointer inout = Dem.createNode(Node::Kind::InOut); inout->addChild(input, Dem); input = inout; } else if (flags.isShared()) { NodePointer shared = Dem.createNode(Node::Kind::Shared); shared->addChild(input, Dem); input = shared; } inputs.push_back(input); } NodePointer totalInput = nullptr; switch (inputs.size()) { case 1: totalInput = inputs.front(); break; // This covers both none and multiple parameters. default: auto tuple = Dem.createNode(Node::Kind::Tuple); for (auto &input : inputs) tuple->addChild(input, Dem); totalInput = tuple; break; } 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<const MetatypeMetadata *>(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<const TupleTypeMetadata *>(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; }
// 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; }