std::vector<FieldTypeInfo> TypeRefBuilder::getFieldTypeRefs(const TypeRef *TR, const FieldDescriptor *FD) { if (FD == nullptr) return {}; auto Subs = TR->getSubstMap(); Demangle::Demangler Dem; std::vector<FieldTypeInfo> Fields; for (auto &Field : *FD) { auto FieldName = Field.getFieldName(); // Empty cases of enums do not have a type if (FD->isEnum() && !Field.hasMangledTypeName()) { Fields.push_back(FieldTypeInfo::forEmptyCase(FieldName)); continue; } auto Demangled = Dem.demangleType(Field.getMangledTypeName()); auto Unsubstituted = swift::remote::decodeMangledType(*this, Demangled); if (!Unsubstituted) return {}; auto Substituted = Unsubstituted->subst(*this, Subs); if (FD->isEnum() && Field.isIndirectCase()) { Fields.push_back(FieldTypeInfo::forIndirectCase(FieldName, Substituted)); continue; } Fields.push_back(FieldTypeInfo::forField(FieldName, Substituted)); } return Fields; }
GenericTypeDecl *ASTBuilder::createTypeDecl(StringRef mangledName, bool &typeAlias) { Demangle::Demangler Dem; Demangle::NodePointer node = Dem.demangleType(mangledName); if (!node) return nullptr; return createTypeDecl(node, typeAlias); }
void TypeRefBuilder::dumpTypeRef(const std::string &MangledName, std::ostream &OS, bool printTypeName) { auto TypeName = Demangle::demangleTypeAsString(MangledName); OS << TypeName << '\n'; Demangle::Demangler Dem; auto DemangleTree = Dem.demangleType(MangledName); auto TR = swift::remote::decodeMangledType(*this, DemangleTree); if (!TR) { OS << "!!! Invalid typeref: " << MangledName << '\n'; return; } TR->dump(OS); OS << '\n'; }
const TypeRef * TypeRefBuilder:: lookupTypeWitness(const std::string &MangledTypeName, const std::string &Member, const TypeRef *Protocol) { TypeRefID key; key.addString(MangledTypeName); key.addString(Member); key.addPointer(Protocol); auto found = AssociatedTypeCache.find(key); if (found != AssociatedTypeCache.end()) return found->second; // Cache missed - we need to look through all of the assocty sections // for all images that we've been notified about. for (auto &Info : ReflectionInfos) { for (const auto &AssocTyDescriptor : Info.assocty) { std::string ConformingTypeName(AssocTyDescriptor.ConformingTypeName); if (ConformingTypeName.compare(MangledTypeName) != 0) continue; std::string ProtocolMangledName(AssocTyDescriptor.ProtocolTypeName); Demangle::Demangler Dem; auto DemangledProto = Dem.demangleType(ProtocolMangledName); auto TR = swift::remote::decodeMangledType(*this, DemangledProto); if (Protocol != TR) continue; for (auto &AssocTy : AssocTyDescriptor) { if (Member.compare(AssocTy.getName()) != 0) continue; auto SubstitutedTypeName = AssocTy.getMangledSubstitutedTypeName(); auto Demangled = Dem.demangleType(SubstitutedTypeName); auto *TypeWitness = swift::remote::decodeMangledType(*this, Demangled); AssociatedTypeCache.insert(std::make_pair(key, TypeWitness)); return TypeWitness; } } } return nullptr; }
/// Get the unsubstituted capture types for a closure context. ClosureContextInfo TypeRefBuilder::getClosureContextInfo(const CaptureDescriptor &CD) { ClosureContextInfo Info; Demangle::Demangler Dem; for (auto i = CD.capture_begin(), e = CD.capture_end(); i != e; ++i) { const TypeRef *TR = nullptr; if (i->hasMangledTypeName()) { auto MangledName = i->getMangledTypeName(); auto DemangleTree = Dem.demangleType(MangledName); TR = swift::remote::decodeMangledType(*this, DemangleTree); } Info.CaptureTypes.push_back(TR); } for (auto i = CD.source_begin(), e = CD.source_end(); i != e; ++i) { const TypeRef *TR = nullptr; if (i->hasMangledTypeName()) { auto MangledName = i->getMangledTypeName(); auto DemangleTree = Dem.demangleType(MangledName); TR = swift::remote::decodeMangledType(*this, DemangleTree); } const MetadataSource *MS = nullptr; if (i->hasMangledMetadataSource()) { auto MangledMetadataSource = i->getMangledMetadataSource(); MS = MetadataSource::decode(MSB, MangledMetadataSource); } Info.MetadataSources.push_back({TR, MS}); } Info.NumBindings = CD.NumBindings; return Info; }
// Build a demangled type tree for a nominal type. static Demangle::NodePointer _buildDemanglingForNominalType(const Metadata *type, Demangle::Demangler &Dem) { using namespace Demangle; const NominalTypeDescriptor *description; // Demangle the parent type, if any. switch (type->getKind()) { case MetadataKind::Class: { auto classType = static_cast<const ClassMetadata *>(type); #if SWIFT_OBJC_INTEROP // Peek through artificial subclasses. while (classType->isTypeMetadata() && classType->isArtificialSubclass()) classType = classType->SuperClass; #endif description = classType->getDescription(); break; } case MetadataKind::Enum: case MetadataKind::Optional: { auto enumType = static_cast<const EnumMetadata *>(type); description = enumType->Description; break; } case MetadataKind::Struct: { auto structType = static_cast<const StructMetadata *>(type); description = structType->Description; break; } default: return nullptr; } // Demangle the base name. auto node = Dem.demangleType(StringRef(description->Name)); assert(node->getKind() == Node::Kind::Type); auto typeBytes = reinterpret_cast<const char *>(type); auto genericArgs = reinterpret_cast<const Metadata * const *>( typeBytes + sizeof(void*) * description->GenericParams.Offset); return _applyGenericArguments(genericArgs, description, node, description->GenericParams.NestingDepth, Dem); }
static Demangle::NodePointer _applyGenericArguments(const Metadata * const *genericArgs, const NominalTypeDescriptor *description, Demangle::NodePointer node, unsigned depth, Demangle::Demangler &Dem) { assert(depth > 0); auto typeNode = node; if (typeNode->getKind() == Node::Kind::Type) typeNode = typeNode->getChild(0); auto parentNode = typeNode->getChild(0); // It might be more accurate to keep this sugar, but the old version // of this function dropped it, and I want to keep things compatible. if (parentNode->getKind() == Node::Kind::Extension) { parentNode = parentNode->getChild(1); } switch (parentNode->getKind()) { case Node::Kind::Class: case Node::Kind::Structure: case Node::Kind::Enum: { // The parent type is a nominal type which may have its own generic // arguments. auto newParentNode = _applyGenericArguments(genericArgs, description, parentNode, depth - 1, Dem); if (newParentNode == nullptr) return nullptr; auto newTypeNode = Dem.createNode(typeNode->getKind()); newTypeNode->addChild(newParentNode, Dem); newTypeNode->addChild(typeNode->getChild(1), Dem); typeNode = newTypeNode; break; } default: // Parent is a local context or module. Leave it as-is, and just apply // generic arguments below. break; } // See if we have any generic arguments at this depth. unsigned numArgumentsAtDepth = description->GenericParams.getContext(depth - 1).NumPrimaryParams; if (numArgumentsAtDepth == 0) { // No arguments here, just return the original node (except we may have // replaced its parent type above). return typeNode; } // Ok, we have generic arguments. Figure out where the arguments for this // depth begin in the generic type metadata. unsigned firstArgumentAtDepth = 0; for (unsigned i = 0; i < depth - 1; i++) { firstArgumentAtDepth += description->GenericParams.getContext(i).NumPrimaryParams; } // Demangle them. auto typeParams = Dem.createNode(Node::Kind::TypeList); for (unsigned i = firstArgumentAtDepth, e = firstArgumentAtDepth + numArgumentsAtDepth; i < e; ++i) { auto demangling = _swift_buildDemanglingForMetadata(genericArgs[i], Dem); if (demangling == nullptr) return nullptr; typeParams->addChild(demangling, Dem); } Node::Kind boundGenericKind; switch (typeNode->getKind()) { case Node::Kind::Class: boundGenericKind = Node::Kind::BoundGenericClass; break; case Node::Kind::Structure: boundGenericKind = Node::Kind::BoundGenericStructure; break; case Node::Kind::Enum: boundGenericKind = Node::Kind::BoundGenericEnum; break; default: return nullptr; } auto newNode = Dem.createNode(Node::Kind::Type); newNode->addChild(typeNode, Dem); auto genericNode = Dem.createNode(boundGenericKind); genericNode->addChild(newNode, Dem); genericNode->addChild(typeParams, Dem); return genericNode; }
// 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; }
static int doDumpReflectionSections(ArrayRef<std::string> binaryFilenames, StringRef arch, ActionType action, std::ostream &OS) { // Note: binaryOrError and objectOrError own the memory for our ObjectFile; // once they go out of scope, we can no longer do anything. std::vector<OwningBinary<Binary>> binaryOwners; std::vector<std::unique_ptr<ObjectFile>> objectOwners; // Construct the TypeRefBuilder TypeRefBuilder builder; for (auto binaryFilename : binaryFilenames) { auto binaryOwner = unwrap(createBinary(binaryFilename)); Binary *binaryFile = binaryOwner.getBinary(); // The object file we are doing lookups in -- either the binary itself, or // a particular slice of a universal binary. std::unique_ptr<ObjectFile> objectOwner; const ObjectFile *objectFile; if (auto o = dyn_cast<ObjectFile>(binaryFile)) { objectFile = o; } else { auto universal = cast<MachOUniversalBinary>(binaryFile); objectOwner = unwrap(universal->getObjectForArch(arch)); objectFile = objectOwner.get(); } builder.addReflectionInfo(findReflectionInfo(objectFile)); // Retain the objects that own section memory binaryOwners.push_back(std::move(binaryOwner)); objectOwners.push_back(std::move(objectOwner)); } switch (action) { case ActionType::DumpReflectionSections: // Dump everything builder.dumpAllSections(OS); break; case ActionType::DumpTypeLowering: { for (std::string line; std::getline(std::cin, line); ) { if (line.empty()) continue; if (StringRef(line).startswith("//")) continue; Demangle::Demangler Dem; auto demangled = Dem.demangleType(line); auto *typeRef = swift::remote::decodeMangledType(builder, demangled); if (typeRef == nullptr) { OS << "Invalid typeref: " << line << "\n"; continue; } typeRef->dump(OS); auto *typeInfo = builder.getTypeConverter().getTypeInfo(typeRef); if (typeInfo == nullptr) { OS << "Invalid lowering\n"; continue; } typeInfo->dump(OS); } break; } } return EXIT_SUCCESS; }
bool NominalTypeTrait::isClass() const { Demangle::Demangler Dem; Demangle::NodePointer Demangled = Dem.demangleType(MangledName); return ::isClass(Demangled); }