| //===--- Mangle.h - Interface to Swift symbol mangling ----------*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See http://swift.org/LICENSE.txt for license information |
| // See http://swift.org/CONTRIBUTORS.txt for the list of Swift project authors |
| // |
| //===----------------------------------------------------------------------===// |
| |
| #ifndef __SWIFT_AST_MANGLE_H__ |
| #define __SWIFT_AST_MANGLE_H__ |
| |
| #include "llvm/ADT/DenseMap.h" |
| #include "swift/AST/Types.h" |
| #include "swift/AST/Decl.h" |
| #include "swift/AST/GenericSignature.h" |
| |
| namespace swift { |
| |
| class AbstractClosureExpr; |
| |
| namespace Mangle { |
| |
| enum class IncludeType : bool { No, Yes }; |
| |
| enum class OperatorFixity { |
| NotOperator, |
| Infix, |
| Prefix, |
| Postfix |
| }; |
| |
| |
| /// A class for mangling declarations. The Mangler accumulates name fragments |
| /// with the mangleXXX methods, and the final string is constructed with the |
| /// `finalize` method, after which the Mangler should not be used. |
| class Mangler { |
| llvm::SmallVector<char, 128> Storage; |
| llvm::raw_svector_ostream Buffer; |
| |
| llvm::DenseMap<const void *, unsigned> Substitutions; |
| CanGenericSignature CurGenericSignature; |
| ModuleDecl *Mod = nullptr; |
| const DeclContext *DeclCtx = nullptr; |
| /// If enabled, Arche- and Alias types are mangled with context. |
| bool DWARFMangling; |
| /// If enabled, non-ASCII names are encoded in modified Punycode. |
| bool UsePunycode; |
| /// Optimize out protocol names if a type only conforms to one protocol. |
| bool OptimizeProtocolNames; |
| |
| public: |
| /// Finish the mangling of the symbol and return the mangled name. |
| std::string finalize(); |
| |
| /// Finish the mangling of the symbol and write the mangled name into |
| /// \p stream. |
| void finalize(llvm::raw_ostream &stream); |
| |
| void setModuleContext(ModuleDecl *M) { Mod = M; } |
| |
| /// \param DWARFMangling - use the 'Qq' mangling format for |
| /// archetypes and the 'a' mangling for alias types. |
| /// \param usePunycode - emit modified Punycode instead of UTF-8. |
| Mangler(bool DWARFMangling = false, |
| bool usePunycode = true, |
| bool OptimizeProtocolNames = true) |
| : Buffer(Storage), DWARFMangling(DWARFMangling), UsePunycode(usePunycode), |
| OptimizeProtocolNames(OptimizeProtocolNames) {} |
| void mangleContextOf(const ValueDecl *decl); |
| void mangleContext(const DeclContext *ctx); |
| void mangleModule(const ModuleDecl *module); |
| void mangleDeclName(const ValueDecl *decl); |
| void mangleDeclType(const ValueDecl *decl, unsigned uncurryingLevel); |
| |
| void mangleEntity(const ValueDecl *decl, unsigned uncurryingLevel); |
| void mangleConstructorEntity(const ConstructorDecl *ctor, bool isAllocating, |
| unsigned uncurryingLevel); |
| void mangleDestructorEntity(const DestructorDecl *decl, bool isDeallocating); |
| void mangleIVarInitDestroyEntity(const ClassDecl *decl, bool isDestroyer); |
| void mangleAccessorEntity(AccessorKind kind, AddressorKind addressorKind, |
| const AbstractStorageDecl *decl); |
| void mangleAddressorEntity(const ValueDecl *decl); |
| void mangleGlobalGetterEntity(ValueDecl *decl); |
| void mangleDefaultArgumentEntity(const DeclContext *ctx, unsigned index); |
| void mangleInitializerEntity(const VarDecl *var); |
| void mangleClosureEntity(const SerializedAbstractClosureExpr *closure, |
| unsigned uncurryingLevel); |
| void mangleClosureEntity(const AbstractClosureExpr *closure, |
| unsigned uncurryingLevel); |
| void mangleNominalType(const NominalTypeDecl *decl); |
| void mangleBoundGenericType(Type type); |
| void mangleProtocolDecl(const ProtocolDecl *protocol); |
| void mangleType(Type type, unsigned uncurryingLevel); |
| void mangleDirectness(bool isIndirect); |
| void mangleProtocolName(const ProtocolDecl *protocol); |
| void mangleProtocolConformance(const ProtocolConformance *conformance); |
| void bindGenericParameters(CanGenericSignature sig); |
| void bindGenericParameters(const DeclContext *DC); |
| void addSubstitution(const void *ptr); |
| |
| void mangleDeclTypeForDebugger(const ValueDecl *decl); |
| void mangleTypeForDebugger(Type decl, const DeclContext *DC); |
| void mangleGenericSignature(const GenericSignature *sig); |
| |
| void mangleFieldOffsetFull(const ValueDecl *decl, bool isIndirect); |
| void mangleTypeMetadataFull(CanType ty, bool isPattern); |
| void mangleTypeFullMetadataFull(CanType ty); |
| void mangleGlobalVariableFull(const VarDecl *decl); |
| |
| /// Adds the string \p S into the mangled name. |
| void append(StringRef S); |
| |
| /// Adds the char \p C into the mangled name. |
| void append(char C); |
| |
| /// Add the already mangled symbol \p Name as an identifier. (using the |
| /// length prefix). |
| void mangleIdentifierSymbol(StringRef Name); |
| |
| /// Add the already mangled symbol \p Name. This gives the mangler the |
| /// opportunity to decode \p Name before adding it to the mangled name. |
| void appendSymbol(StringRef Name); |
| |
| /// Mangle the integer \p Nat into the name. |
| void mangleNatural(const APInt &Nat); |
| |
| /// Mangles globalinit_token and globalinit_func, which are used to |
| /// initialize global variables. |
| /// \param decl The global variable or one of the global variables of a |
| /// pattern, e.g. var (a, b) = (1, 2) |
| /// \param counter A consecutive number inside the compiled file. |
| /// \param isInitFunc If true it's a globalinit_func, otherwise a |
| /// globalinit_token. |
| void mangleGlobalInit(const VarDecl *decl, int counter, bool isInitFunc); |
| |
| void mangleBehaviorInitThunk(const VarDecl *decl); |
| |
| void mangleIdentifier(StringRef ref, |
| OperatorFixity fixity = OperatorFixity::NotOperator, |
| bool isOperator=false); |
| private: |
| void mangleFunctionType(AnyFunctionType *fn, unsigned uncurryingLevel); |
| void mangleProtocolList(ArrayRef<ProtocolDecl*> protocols); |
| void mangleProtocolList(ArrayRef<Type> protocols); |
| void mangleIdentifier(Identifier ident, |
| OperatorFixity fixity = OperatorFixity::NotOperator); |
| |
| void mangleClosureComponents(Type Ty, unsigned discriminator, bool isImplicit, |
| const DeclContext *parentContext, |
| const DeclContext *localContext); |
| |
| bool tryMangleStandardSubstitution(const NominalTypeDecl *type); |
| bool tryMangleSubstitution(const void *ptr); |
| |
| /// \brief Mangles a sugared type iff we are mangling for the debugger. |
| template <class T> void mangleSugaredType(Type type) { |
| assert(DWARFMangling && |
| "sugared types are only legal when mangling for the debugger"); |
| auto *BlandTy = cast<T>(type.getPointer())->getSinglyDesugaredType(); |
| mangleType(BlandTy, 0); |
| } |
| |
| void mangleGenericSignatureParts(ArrayRef<GenericTypeParamType *> params, |
| unsigned initialParamDepth, |
| ArrayRef<Requirement> requirements); |
| Type getDeclTypeForMangling(const ValueDecl *decl, |
| ArrayRef<GenericTypeParamType *> &genericParams, |
| unsigned &initialParamIndex, |
| ArrayRef<Requirement> &requirements, |
| SmallVectorImpl<Requirement> &requirementsBuf); |
| |
| void mangleGenericParamIndex(GenericTypeParamType *paramTy); |
| void mangleAssociatedTypeName(DependentMemberType *dmt, |
| bool canAbbreviate); |
| void mangleConstrainedType(CanType type); |
| }; |
| |
| } // end namespace Mangle |
| } // end namespace swift |
| |
| #endif |