| //===--- ASTMangler.h - Swift AST symbol mangling ---------------*- 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 |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef SWIFT_AST_ASTMANGLER_H |
| #define SWIFT_AST_ASTMANGLER_H |
| |
| #include "swift/Basic/Mangler.h" |
| #include "swift/AST/Types.h" |
| #include "swift/AST/Decl.h" |
| |
| namespace clang { |
| class NamedDecl; |
| } |
| |
| namespace swift { |
| |
| class AbstractClosureExpr; |
| class ConformanceAccessPath; |
| class RootProtocolConformance; |
| |
| namespace Mangle { |
| |
| /// The mangler for AST declarations. |
| class ASTMangler : public Mangler { |
| protected: |
| CanGenericSignature CurGenericSignature; |
| ModuleDecl *Mod = nullptr; |
| |
| /// Optimize out protocol names if a type only conforms to one protocol. |
| bool OptimizeProtocolNames = true; |
| |
| /// If enabled, use Objective-C runtime names when mangling @objc Swift |
| /// protocols and classes. |
| bool UseObjCRuntimeNames = false; |
| |
| /// If enabled, non-canonical types are allowed and type alias types get a |
| /// special mangling. |
| bool DWARFMangling; |
| |
| /// If enabled, entities that ought to have names but don't get a placeholder. |
| /// |
| /// If disabled, it is an error to try to mangle such an entity. |
| bool AllowNamelessEntities = false; |
| |
| /// If enabled, some entities will be emitted as symbolic reference |
| /// placeholders. The offsets of these references will be stored in the |
| /// `SymbolicReferences` vector, and it is up to the consumer of the mangling |
| /// to fill these in. |
| bool AllowSymbolicReferences = false; |
| |
| public: |
| using SymbolicReferent = llvm::PointerUnion<const NominalTypeDecl *, |
| const OpaqueTypeDecl *>; |
| protected: |
| |
| /// If set, the mangler calls this function to determine whether to symbolic |
| /// reference a given entity. If null, the mangler acts as if it's set to |
| /// always return true. |
| std::function<bool (SymbolicReferent)> CanSymbolicReference; |
| |
| bool canSymbolicReference(SymbolicReferent referent) { |
| return AllowSymbolicReferences |
| && (!CanSymbolicReference || CanSymbolicReference(referent)); |
| } |
| |
| std::vector<std::pair<SymbolicReferent, unsigned>> SymbolicReferences; |
| |
| public: |
| enum class SymbolKind { |
| Default, |
| AsyncHandlerBody, |
| DynamicThunk, |
| SwiftAsObjCThunk, |
| ObjCAsSwiftThunk, |
| }; |
| |
| ASTMangler(bool DWARFMangling = false) |
| : DWARFMangling(DWARFMangling) {} |
| |
| void addTypeSubstitution(Type type) { |
| type = dropProtocolsFromAssociatedTypes(type); |
| addSubstitution(type.getPointer()); |
| } |
| bool tryMangleTypeSubstitution(Type type) { |
| type = dropProtocolsFromAssociatedTypes(type); |
| return tryMangleSubstitution(type.getPointer()); |
| } |
| |
| std::string mangleClosureEntity(const AbstractClosureExpr *closure, |
| SymbolKind SKind); |
| |
| std::string mangleEntity(const ValueDecl *decl, |
| SymbolKind SKind = SymbolKind::Default); |
| |
| std::string mangleDestructorEntity(const DestructorDecl *decl, |
| bool isDeallocating, |
| SymbolKind SKind = SymbolKind::Default); |
| |
| std::string mangleConstructorEntity(const ConstructorDecl *ctor, |
| bool isAllocating, |
| SymbolKind SKind = SymbolKind::Default); |
| |
| std::string mangleIVarInitDestroyEntity(const ClassDecl *decl, |
| bool isDestroyer, SymbolKind SKind); |
| |
| std::string mangleAccessorEntity(AccessorKind kind, |
| const AbstractStorageDecl *decl, |
| bool isStatic, |
| SymbolKind SKind); |
| |
| std::string mangleGlobalGetterEntity(const ValueDecl *decl, |
| SymbolKind SKind = SymbolKind::Default); |
| |
| std::string mangleDefaultArgumentEntity(const DeclContext *func, |
| unsigned index, |
| SymbolKind SKind = SymbolKind::Default); |
| |
| std::string mangleInitializerEntity(const VarDecl *var, SymbolKind SKind); |
| std::string mangleBackingInitializerEntity(const VarDecl *var, |
| SymbolKind SKind = SymbolKind::Default); |
| |
| std::string mangleNominalType(const NominalTypeDecl *decl); |
| |
| std::string mangleVTableThunk(const FuncDecl *Base, |
| const FuncDecl *Derived); |
| |
| std::string mangleConstructorVTableThunk(const ConstructorDecl *Base, |
| const ConstructorDecl *Derived, |
| bool isAllocating); |
| |
| std::string mangleWitnessTable(const RootProtocolConformance *C); |
| |
| std::string mangleWitnessThunk(const ProtocolConformance *Conformance, |
| const ValueDecl *Requirement); |
| |
| std::string mangleClosureWitnessThunk(const ProtocolConformance *Conformance, |
| const AbstractClosureExpr *Closure); |
| |
| std::string mangleGlobalVariableFull(const VarDecl *decl); |
| |
| std::string mangleGlobalInit(const PatternBindingDecl *decl, |
| unsigned entry, |
| bool isInitFunc); |
| |
| std::string mangleReabstractionThunkHelper(CanSILFunctionType ThunkType, |
| Type FromType, Type ToType, |
| Type SelfType, |
| ModuleDecl *Module); |
| |
| /// Mangle a completion handler block implementation function, used for importing ObjC |
| /// APIs as async. |
| /// |
| /// - If `predefined` is true, this mangles the symbol name of the completion handler |
| /// predefined in the Swift runtime for the given type signature. |
| std::string mangleObjCAsyncCompletionHandlerImpl(CanSILFunctionType BlockType, |
| CanType ResultType, |
| bool predefined); |
| |
| /// Mangle the derivative function (JVP/VJP) for the given: |
| /// - Mangled original function name. |
| /// - Derivative function kind. |
| /// - Derivative function configuration: parameter/result indices and |
| /// derivative generic signature. |
| std::string |
| mangleAutoDiffDerivativeFunctionHelper(StringRef name, |
| AutoDiffDerivativeFunctionKind kind, |
| AutoDiffConfig config); |
| |
| /// Mangle the linear map (differential/pullback) for the given: |
| /// - Mangled original function name. |
| /// - Linear map kind. |
| /// - Derivative function configuration: parameter/result indices and |
| /// derivative generic signature. |
| std::string mangleAutoDiffLinearMapHelper(StringRef name, |
| AutoDiffLinearMapKind kind, |
| AutoDiffConfig config); |
| |
| /// Mangle the AutoDiff generated declaration for the given: |
| /// - Generated declaration kind: linear map struct or branching trace enum. |
| /// - Mangled original function name. |
| /// - Basic block number. |
| /// - Linear map kind: differential or pullback. |
| /// - Derivative function configuration: parameter/result indices and |
| /// derivative generic signature. |
| std::string |
| mangleAutoDiffGeneratedDeclaration(AutoDiffGeneratedDeclarationKind declKind, |
| StringRef origFnName, unsigned bbId, |
| AutoDiffLinearMapKind linearMapKind, |
| AutoDiffConfig config); |
| |
| /// Mangle a SIL differentiability witness key: |
| /// - Mangled original function name. |
| /// - Parameter indices. |
| /// - Result indices. |
| /// - Derivative generic signature (optional). |
| std::string |
| mangleSILDifferentiabilityWitnessKey(SILDifferentiabilityWitnessKey key); |
| |
| std::string mangleKeyPathGetterThunkHelper(const AbstractStorageDecl *property, |
| GenericSignature signature, |
| CanType baseType, |
| SubstitutionMap subs, |
| ResilienceExpansion expansion); |
| std::string mangleKeyPathSetterThunkHelper(const AbstractStorageDecl *property, |
| GenericSignature signature, |
| CanType baseType, |
| SubstitutionMap subs, |
| ResilienceExpansion expansion); |
| std::string mangleKeyPathEqualsHelper(ArrayRef<CanType> indices, |
| GenericSignature signature, |
| ResilienceExpansion expansion); |
| std::string mangleKeyPathHashHelper(ArrayRef<CanType> indices, |
| GenericSignature signature, |
| ResilienceExpansion expansion); |
| |
| std::string mangleTypeForDebugger(Type decl, const DeclContext *DC); |
| |
| /// Create a mangled name to be used for _typeName constant propagation. |
| std::string mangleTypeForTypeName(Type type); |
| |
| std::string mangleOpaqueTypeDescriptor(const OpaqueTypeDecl *decl); |
| |
| std::string mangleDeclType(const ValueDecl *decl); |
| |
| std::string mangleObjCRuntimeName(const NominalTypeDecl *Nominal); |
| |
| std::string mangleTypeWithoutPrefix(Type type) { |
| appendType(type); |
| return finalize(); |
| } |
| |
| std::string mangleTypeAsUSR(Type decl); |
| |
| std::string mangleTypeAsContextUSR(const NominalTypeDecl *type); |
| |
| std::string mangleDeclAsUSR(const ValueDecl *Decl, StringRef USRPrefix); |
| |
| std::string mangleAccessorEntityAsUSR(AccessorKind kind, |
| const AbstractStorageDecl *decl, |
| StringRef USRPrefix, |
| bool IsStatic); |
| |
| std::string mangleLocalTypeDecl(const TypeDecl *type); |
| |
| std::string mangleOpaqueTypeDecl(const OpaqueTypeDecl *decl); |
| |
| std::string mangleOpaqueTypeDecl(const ValueDecl *decl); |
| |
| enum SpecialContext { |
| ObjCContext, |
| ClangImporterContext, |
| }; |
| |
| static Optional<SpecialContext> |
| getSpecialManglingContext(const ValueDecl *decl, bool useObjCProtocolNames); |
| |
| static const clang::NamedDecl * |
| getClangDeclForMangling(const ValueDecl *decl); |
| |
| protected: |
| |
| void appendSymbolKind(SymbolKind SKind); |
| |
| void appendType(Type type, const ValueDecl *forDecl = nullptr); |
| |
| void appendDeclName(const ValueDecl *decl); |
| |
| GenericTypeParamType *appendAssocType(DependentMemberType *DepTy, |
| bool &isAssocTypeAtDepth); |
| |
| void appendOpWithGenericParamIndex(StringRef, |
| const GenericTypeParamType *paramTy); |
| |
| void bindGenericParameters(const DeclContext *DC); |
| |
| void bindGenericParameters(CanGenericSignature sig); |
| |
| /// Mangles a sugared type iff we are mangling for the debugger. |
| template <class T> void appendSugaredType(Type type, |
| const ValueDecl *forDecl) { |
| assert(DWARFMangling && |
| "sugared types are only legal when mangling for the debugger"); |
| auto *BlandTy = cast<T>(type.getPointer())->getSinglyDesugaredType(); |
| appendType(BlandTy, forDecl); |
| } |
| |
| void appendBoundGenericArgs(Type type, bool &isFirstArgList); |
| |
| /// Append the bound generics arguments for the given declaration context |
| /// based on a complete substitution map. |
| /// |
| /// \returns the number of generic parameters that were emitted |
| /// thus far. |
| unsigned appendBoundGenericArgs(DeclContext *dc, |
| SubstitutionMap subs, |
| bool &isFirstArgList); |
| |
| /// Append the bound generic arguments as a flat list, disregarding depth. |
| void appendFlatGenericArgs(SubstitutionMap subs); |
| |
| /// Append any retroactive conformances. |
| void appendRetroactiveConformances(Type type); |
| void appendRetroactiveConformances(SubstitutionMap subMap, |
| ModuleDecl *fromModule); |
| void appendImplFunctionType(SILFunctionType *fn); |
| |
| void appendContextOf(const ValueDecl *decl); |
| |
| void appendContext(const DeclContext *ctx, StringRef useModuleName); |
| |
| void appendModule(const ModuleDecl *module, StringRef useModuleName); |
| |
| void appendProtocolName(const ProtocolDecl *protocol, |
| bool allowStandardSubstitution = true); |
| |
| void appendAnyGenericType(const GenericTypeDecl *decl); |
| |
| enum FunctionManglingKind { |
| NoFunctionMangling, |
| FunctionMangling, |
| AsyncHandlerBodyMangling |
| }; |
| |
| void appendFunction(AnyFunctionType *fn, |
| FunctionManglingKind functionMangling = NoFunctionMangling, |
| const ValueDecl *forDecl = nullptr); |
| void appendFunctionType(AnyFunctionType *fn, bool isAutoClosure = false, |
| const ValueDecl *forDecl = nullptr); |
| void appendClangType(AnyFunctionType *fn); |
| template <typename FnType> |
| void appendClangType(FnType *fn, llvm::raw_svector_ostream &os); |
| |
| void appendFunctionSignature(AnyFunctionType *fn, |
| const ValueDecl *forDecl, |
| FunctionManglingKind functionMangling); |
| |
| void appendFunctionInputType(ArrayRef<AnyFunctionType::Param> params, |
| const ValueDecl *forDecl = nullptr); |
| void appendFunctionResultType(Type resultType, |
| const ValueDecl *forDecl = nullptr); |
| |
| void appendTypeList(Type listTy, const ValueDecl *forDecl = nullptr); |
| void appendTypeListElement(Identifier name, Type elementType, |
| ParameterTypeFlags flags, |
| const ValueDecl *forDecl = nullptr); |
| |
| /// Append a generic signature to the mangling. |
| /// |
| /// \param sig The generic signature. |
| /// |
| /// \param contextSig The signature of the known context. This function |
| /// will only mangle the difference between \c sig and \c contextSig. |
| /// |
| /// \returns \c true if a generic signature was appended, \c false |
| /// if it was empty. |
| bool appendGenericSignature(GenericSignature sig, |
| GenericSignature contextSig = nullptr); |
| |
| void appendRequirement(const Requirement &reqt); |
| |
| void appendGenericSignatureParts(TypeArrayView<GenericTypeParamType> params, |
| unsigned initialParamDepth, |
| ArrayRef<Requirement> requirements); |
| |
| DependentMemberType *dropProtocolFromAssociatedType(DependentMemberType *dmt); |
| Type dropProtocolsFromAssociatedTypes(Type type); |
| |
| void appendAssociatedTypeName(DependentMemberType *dmt); |
| |
| void appendClosureEntity(const SerializedAbstractClosureExpr *closure); |
| |
| void appendClosureEntity(const AbstractClosureExpr *closure); |
| |
| void appendClosureComponents(Type Ty, unsigned discriminator, bool isImplicit, |
| const DeclContext *parentContext); |
| |
| void appendDefaultArgumentEntity(const DeclContext *ctx, unsigned index); |
| |
| void appendInitializerEntity(const VarDecl *var); |
| void appendBackingInitializerEntity(const VarDecl *var); |
| |
| CanType getDeclTypeForMangling(const ValueDecl *decl, |
| GenericSignature &genericSig, |
| GenericSignature &parentGenericSig); |
| |
| |
| |
| void appendDeclType(const ValueDecl *decl, |
| FunctionManglingKind functionMangling = NoFunctionMangling); |
| |
| bool tryAppendStandardSubstitution(const GenericTypeDecl *type); |
| |
| void appendConstructorEntity(const ConstructorDecl *ctor, bool isAllocating); |
| |
| void appendDestructorEntity(const DestructorDecl *decl, bool isDeallocating); |
| |
| /// \param accessorKindCode The code to describe the accessor and addressor |
| /// kind. Usually retrieved using getCodeForAccessorKind. |
| /// \param decl The storage decl for which to mangle the accessor |
| /// \param isStatic Whether or not the accessor is static |
| void appendAccessorEntity(StringRef accessorKindCode, |
| const AbstractStorageDecl *decl, bool isStatic); |
| |
| void appendEntity(const ValueDecl *decl, StringRef EntityOp, bool isStatic); |
| |
| void appendEntity(const ValueDecl *decl, bool isAsyncHandlerBody = false); |
| |
| void appendProtocolConformance(const ProtocolConformance *conformance); |
| void appendProtocolConformanceRef(const RootProtocolConformance *conformance); |
| void appendAnyProtocolConformance(CanGenericSignature genericSig, |
| CanType conformingType, |
| ProtocolConformanceRef conformance); |
| void appendConcreteProtocolConformance( |
| const ProtocolConformance *conformance); |
| void appendDependentProtocolConformance(const ConformanceAccessPath &path); |
| void appendOpParamForLayoutConstraint(LayoutConstraint Layout); |
| |
| void appendSymbolicReference(SymbolicReferent referent); |
| |
| void appendOpaqueDeclName(const OpaqueTypeDecl *opaqueDecl); |
| }; |
| |
| } // end namespace Mangle |
| } // end namespace swift |
| |
| #endif // SWIFT_AST_ASTMANGLER_H |