//===--- ASTDemangler.h - Swift AST symbol demangling -----------*- C++ -*-===// // // 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 // //===----------------------------------------------------------------------===// // // Defines a builder concept for the TypeDecoder and MetadataReader which builds // AST Types, and a utility function wrapper which takes a mangled string and // feeds it through the TypeDecoder instance. // // The RemoteAST library defines a MetadataReader instance that uses this // concept, together with some additional utilities. // //===----------------------------------------------------------------------===// #ifndef SWIFT_AST_ASTDEMANGLER_H #define SWIFT_AST_ASTDEMANGLER_H #include "swift/AST/ASTContext.h" #include "swift/AST/Types.h" #include "swift/Demangling/Demangler.h" #include "swift/Demangling/NamespaceMacros.h" #include "swift/Demangling/TypeDecoder.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" #include namespace swift { class Decl; class TypeDecl; class DeclName; namespace Demangle { SWIFT_BEGIN_INLINE_NAMESPACE Type getTypeForMangling(ASTContext &ctx, llvm::StringRef mangling, GenericSignature genericSig=GenericSignature()); TypeDecl *getTypeDeclForMangling(ASTContext &ctx, llvm::StringRef mangling, GenericSignature genericSig=GenericSignature()); TypeDecl *getTypeDeclForUSR(ASTContext &ctx, llvm::StringRef usr, GenericSignature genericSig=GenericSignature()); Decl *getDeclForUSR(ASTContext &ctx, llvm::StringRef usr, GenericSignature genericSig = GenericSignature()); /// An implementation of MetadataReader's BuilderType concept that /// just finds and builds things in the AST. class ASTBuilder { ASTContext &Ctx; Mangle::ManglingFlavor ManglingFlavor; Demangle::NodeFactory Factory; /// The notional context in which we're writing and type-checking code. /// Created lazily. DeclContext *NotionalDC = nullptr; /// The depth and index of each parameter pack in the current generic /// signature. We need this because the mangling for a type parameter /// doesn't record whether it is a pack or not; we find the correct /// depth and index in this array, and use its pack-ness. llvm::SmallVector, 2> ParameterPacks; /// For saving and restoring generic parameters. llvm::SmallVector ParameterPackStack; /// The depth and index of each value parameter in the current generic /// signature. We need this becasue the mangling for a type parameter /// doesn't record whether it is a value or not; we find the correct /// depth and index in this array, and use its value-ness. llvm::SmallVector, Type>, 1> ValueParameters; /// For saving and restoring generic parameters. llvm::SmallVector ValueParametersStack; /// This builder doesn't perform "on the fly" substitutions, so we preserve /// all pack expansions. We still need an active expansion stack though, /// for the dummy implementation of these methods: /// - beginPackExpansion() /// - advancePackExpansion() /// - createExpandedPackElement() /// - endPackExpansion() llvm::SmallVector ActivePackExpansions; public: using BuiltType = swift::Type; using BuiltTypeDecl = swift::GenericTypeDecl *; // nominal or type alias using BuiltProtocolDecl = swift::ProtocolDecl *; using BuiltGenericSignature = swift::GenericSignature; using BuiltRequirement = swift::Requirement; using BuiltInverseRequirement = swift::InverseRequirement; using BuiltSubstitutionMap = swift::SubstitutionMap; static constexpr bool needsToPrecomputeParentGenericContextShapes = false; explicit ASTBuilder(ASTContext &ctx, GenericSignature genericSig) : Ctx(ctx) { ManglingFlavor = ctx.LangOpts.hasFeature(Feature::Embedded) ? Mangle::ManglingFlavor::Embedded : Mangle::ManglingFlavor::Default; for (auto *paramTy : genericSig.getGenericParams()) { if (paramTy->isParameterPack()) ParameterPacks.emplace_back(paramTy->getDepth(), paramTy->getIndex()); if (paramTy->isValue()) { auto pair = std::make_pair(paramTy->getDepth(), paramTy->getIndex()); auto tuple = std::make_tuple(pair, paramTy->getValueType()); ValueParameters.emplace_back(tuple); } } } ASTContext &getASTContext() { return Ctx; } Mangle::ManglingFlavor getManglingFlavor() { return ManglingFlavor; } DeclContext *getNotionalDC(); Demangle::NodeFactory &getNodeFactory() { return Factory; } /// Finds the \c Decl associated with the provided \p node. /// Attempts to find a type declaration using \c createTypeDecl, if not found, /// it performs a lookup for the declaration and returns the first declaration /// for which \c isMatchingValueDecl returns true. /// /// \note \p isMatchingValueDecl is not evaluated for type declarations, it's /// only used to choose among lookup results when \c createTypeDecl fails. Decl * findDecl(NodePointer node, llvm::function_ref isMatchingValueDecl); Type decodeMangledType(NodePointer node, bool forRequirement = true); Type createBuiltinType(StringRef builtinName, StringRef mangledName); TypeDecl *createTypeDecl(NodePointer node); GenericTypeDecl *createTypeDecl(StringRef mangledName, bool &typeAlias); GenericTypeDecl *createTypeDecl(NodePointer node, bool &typeAlias); ProtocolDecl *createProtocolDecl(NodePointer node); Type createNominalType(GenericTypeDecl *decl); Type createNominalType(GenericTypeDecl *decl, Type parent); Type createTypeAliasType(GenericTypeDecl *decl, Type parent); Type createBoundGenericType(GenericTypeDecl *decl, ArrayRef args); Type resolveOpaqueType(NodePointer opaqueDescriptor, ArrayRef> args, unsigned ordinal); Type createBoundGenericType(GenericTypeDecl *decl, ArrayRef args, Type parent); Type createTupleType(ArrayRef eltTypes, ArrayRef labels); Type createPackType(ArrayRef eltTypes); Type createSILPackType(ArrayRef eltTypes, bool isElementAddress); size_t beginPackExpansion(Type countType); void advancePackExpansion(size_t index); Type createExpandedPackElement(Type patternType); void endPackExpansion(); Type createFunctionType( ArrayRef> params, Type output, FunctionTypeFlags flags, ExtendedFunctionTypeFlags extFlags, FunctionMetadataDifferentiabilityKind diffKind, Type globalActor, Type thrownError); Type createImplFunctionType( Demangle::ImplParameterConvention calleeConvention, Demangle::ImplCoroutineKind coroutineKind, ArrayRef> params, ArrayRef> yields, ArrayRef> results, std::optional> errorResult, ImplFunctionTypeFlags flags); Type createProtocolCompositionType(ArrayRef protocols, Type superclass, bool isClassBound, bool forRequirement = true); Type createProtocolTypeFromDecl(ProtocolDecl *protocol); Type createConstrainedExistentialType( Type base, ArrayRef constraints, ArrayRef inverseRequirements); Type createSymbolicExtendedExistentialType(NodePointer shapeNode, ArrayRef genArgs); Type createExistentialMetatypeType( Type instance, std::optional repr = std::nullopt); Type createMetatypeType( Type instance, std::optional repr = std::nullopt); void pushGenericParams(ArrayRef> parameterPacks); void popGenericParams(); Type createGenericTypeParameterType(unsigned depth, unsigned index); Type createDependentMemberType(StringRef member, Type base); Type createDependentMemberType(StringRef member, Type base, ProtocolDecl *protocol); #define REF_STORAGE(Name, ...) \ Type create##Name##StorageType(Type base); #include "swift/AST/ReferenceStorage.def" Type createSILBoxType(Type base); using BuiltSILBoxField = llvm::PointerIntPair; using BuiltSubstitution = std::pair; using BuiltLayoutConstraint = swift::LayoutConstraint; Type createSILBoxTypeWithLayout( ArrayRef Fields, ArrayRef Substitutions, ArrayRef Requirements, ArrayRef inverseRequirements); bool isExistential(Type type) { return type->isExistentialType(); } Type createObjCClassType(StringRef name); Type createBoundGenericObjCClassType(StringRef name, ArrayRef args); ProtocolDecl *createObjCProtocolDecl(StringRef name); Type createDynamicSelfType(Type selfType); Type createForeignClassType(StringRef mangledName); Type getUnnamedForeignClassType(); Type getOpaqueType(); Type createOptionalType(Type base); Type createArrayType(Type base); Type createInlineArrayType(Type count, Type element); Type createDictionaryType(Type key, Type value); Type createIntegerType(intptr_t value); Type createNegativeIntegerType(intptr_t value); Type createBuiltinFixedArrayType(Type size, Type element); BuiltGenericSignature createGenericSignature(ArrayRef params, ArrayRef requirements); BuiltSubstitutionMap createSubstitutionMap(BuiltGenericSignature sig, ArrayRef replacements); Type subst(Type subject, const BuiltSubstitutionMap &Subs) const; LayoutConstraint getLayoutConstraint(LayoutConstraintKind kind); LayoutConstraint getLayoutConstraintWithSizeAlign(LayoutConstraintKind kind, unsigned size, unsigned alignment); InverseRequirement createInverseRequirement( Type subject, InvertibleProtocolKind kind); private: bool validateParentType(TypeDecl *decl, Type parent); CanGenericSignature demangleGenericSignature( NominalTypeDecl *nominalDecl, NodePointer node); DeclContext *findDeclContext(NodePointer node); /// Find all the ModuleDecls that correspond to a module node's identifier. /// The module name encoded in the node is either the module's real or ABI /// name. Multiple modules can share the same name. This function returns /// all modules that contain that name. llvm::ArrayRef findPotentialModules(NodePointer node, ModuleDecl *&scratch); Demangle::NodePointer findModuleNode(NodePointer node); enum class ForeignModuleKind { Imported, SynthesizedByImporter }; std::optional getForeignModuleKind(NodePointer node); GenericTypeDecl *findTypeDecl(DeclContext *dc, Identifier name, Identifier privateDiscriminator, Demangle::Node::Kind kind); GenericTypeDecl *findForeignTypeDecl(StringRef name, StringRef relatedEntityKind, ForeignModuleKind lookupKind, Demangle::Node::Kind kind); static GenericTypeDecl *getAcceptableTypeDeclCandidate(ValueDecl *decl, Demangle::Node::Kind kind); /// Returns an identifier with the given name, automatically removing any /// surrounding backticks that are present for raw identifiers. Identifier getIdentifier(StringRef name); }; SWIFT_END_INLINE_NAMESPACE } // namespace Demangle } // namespace swift #endif // SWIFT_AST_ASTDEMANGLER_H