Mangling: mangler, demangler and remangler classes for the new mangling scheme.

Following classes provide symbol mangling for specific purposes:
*) Mangler: the base mangler class, just providing some basic utilities
*) ASTMangler: for mangling AST declarations
*) SpecializationMangler: to be used in the optimizer for mangling specialized function names
*) IRGenMangler: mangling all kind of symbols in IRGen

All those classes are not used yet, so it’s basically a NFC.

Another change is that some demangler node types are added (either because they were missing or the new demangler needs them).
Those new nodes also need to be handled in the old demangler, but this should also be a NFC as those nodes are not created by the old demangler.

My plan is to keep the old and new mangling implementation in parallel for some time. After that we can remove the old mangler.
Currently the new implementation is scoped in the NewMangling namespace. This namespace should be renamed after the old mangler is removed.
This commit is contained in:
Erik Eckstein
2016-12-02 13:53:35 -08:00
parent f751d0139e
commit 684092d7d1
24 changed files with 6957 additions and 19 deletions

View File

@@ -0,0 +1,225 @@
//===--- ASTMangler.h - Swift AST 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_ASTMANGLER_H__
#define __SWIFT_AST_ASTMANGLER_H__
#include "swift/Basic/Mangler.h"
#include "swift/AST/Types.h"
#include "swift/AST/Decl.h"
#include "swift/AST/GenericSignature.h"
namespace swift {
class AbstractClosureExpr;
namespace NewMangling {
/// Utility function which selects either the old or new mangling for a type.
std::string mangleTypeForDebugger(Type Ty, const DeclContext *DC);
/// Utility function which selects either the old or new mangling for a type and
/// mangles the type as USR.
std::string mangleTypeAsUSR(Type Ty);
/// The mangler for AST declarations.
class ASTMangler : public Mangler {
protected:
CanGenericSignature CurGenericSignature;
ModuleDecl *Mod = nullptr;
const DeclContext *DeclCtx = nullptr;
/// Optimize out protocol names if a type only conforms to one protocol.
bool OptimizeProtocolNames;
/// If enabled, Arche- and Alias types are mangled with context.
bool DWARFMangling;
public:
enum class SymbolKind {
Default,
VTableMethod,
DynamicThunk,
SwiftAsObjCThunk,
ObjCAsSwiftThunk,
DirectMethodReferenceThunk,
};
ASTMangler(bool DWARFMangling = false,
bool usePunycode = true,
bool OptimizeProtocolNames = true)
: Mangler(usePunycode),
OptimizeProtocolNames(OptimizeProtocolNames),
DWARFMangling(DWARFMangling) {}
std::string mangleClosureEntity(const AbstractClosureExpr *closure,
SymbolKind SKind);
std::string mangleEntity(const ValueDecl *decl, bool isCurried,
SymbolKind SKind = SymbolKind::Default);
std::string mangleDestructorEntity(const DestructorDecl *decl,
bool isDeallocating, SymbolKind SKind);
std::string mangleConstructorEntity(const ConstructorDecl *ctor,
bool isAllocating, bool isCurried,
SymbolKind SKind = SymbolKind::Default);
std::string mangleIVarInitDestroyEntity(const ClassDecl *decl,
bool isDestroyer, SymbolKind SKind);
std::string mangleAccessorEntity(AccessorKind kind,
AddressorKind addressorKind,
const ValueDecl *decl,
bool isStatic,
SymbolKind SKind);
std::string mangleGlobalGetterEntity(ValueDecl *decl,
SymbolKind SKind = SymbolKind::Default);
std::string mangleDefaultArgumentEntity(const DeclContext *func,
unsigned index,
SymbolKind SKind);
std::string mangleInitializerEntity(const VarDecl *var, SymbolKind SKind);
std::string mangleNominalType(const NominalTypeDecl *decl);
std::string mangleWitnessTable(NormalProtocolConformance *C);
std::string mangleWitnessThunk(ProtocolConformance *Conformance,
ValueDecl *Requirement);
std::string mangleClosureWitnessThunk(ProtocolConformance *Conformance,
AbstractClosureExpr *Closure);
std::string mangleBehaviorInitThunk(const VarDecl *decl);
std::string mangleGlobalVariableFull(const VarDecl *decl);
std::string mangleGlobalInit(const VarDecl *decl, int counter,
bool isInitFunc);
std::string mangleReabstructionThunkHelper(CanSILFunctionType ThunkType,
Type FromType, Type ToType,
ModuleDecl *Module);
std::string mangleType(Type decl, const DeclContext *DC);
std::string mangleTypeAsUSR(Type type);
std::string mangleTypeAsContextUSR(const NominalTypeDecl *type);
std::string mangleDeclAsUSR(ValueDecl *Decl, StringRef USRPrefix);
protected:
void appendSymbolKind(SymbolKind SKind);
void appendType(Type type);
void appendDeclName(const ValueDecl *decl);
void appendProtocolList(ArrayRef<Type> Protocols, bool &First);
GenericTypeParamType *appendAssocType(DependentMemberType *DepTy,
bool &isAssocTypeAtDepth);
void appendOpWithGenericParamIndex(StringRef,
GenericTypeParamType *paramTy);
void bindGenericParameters(const DeclContext *DC);
void bindGenericParameters(CanGenericSignature sig);
/// \brief Mangles a sugared type iff we are mangling for the debugger.
template <class T> void appendSugaredType(Type type) {
assert(DWARFMangling &&
"sugared types are only legal when mangling for the debugger");
auto *BlandTy = cast<T>(type.getPointer())->getSinglyDesugaredType();
appendType(BlandTy);
}
void appendBoundGenericArgs(Type type);
void appendImplFunctionType(SILFunctionType *fn);
void appendContextOf(const ValueDecl *decl);
void appendContext(const DeclContext *ctx);
void appendModule(const ModuleDecl *module);
void appendProtocolName(const ProtocolDecl *protocol);
void appendNominalType(const NominalTypeDecl *decl);
void appendFunctionType(AnyFunctionType *fn);
void appendFunctionSignature(AnyFunctionType *fn);
void appendParams(Type ParamsTy);
void appendTypeList(Type listTy);
void appendGenericSignature(const GenericSignature *sig);
void appendRequirement(const Requirement &reqt);
void appendGenericSignatureParts(ArrayRef<GenericTypeParamType*> params,
unsigned initialParamDepth,
ArrayRef<Requirement> requirements);
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,
const DeclContext *localContext);
void appendDefaultArgumentEntity(const DeclContext *ctx, unsigned index);
void appendInitializerEntity(const VarDecl *var);
Type getDeclTypeForMangling(const ValueDecl *decl,
ArrayRef<GenericTypeParamType *> &genericParams,
unsigned &initialParamIndex,
ArrayRef<Requirement> &requirements,
SmallVectorImpl<Requirement> &requirementsBuf);
void appendDeclType(const ValueDecl *decl);
bool tryAppendStandardSubstitution(const NominalTypeDecl *type);
void appendConstructorEntity(const ConstructorDecl *ctor, bool isAllocating);
void appendDestructorEntity(const DestructorDecl *decl, bool isDeallocating);
void appendAccessorEntity(AccessorKind kind,
AddressorKind addressorKind,
const ValueDecl *decl,
bool isStatic);
void appendEntity(const ValueDecl *decl, StringRef EntityOp, bool isStatic);
void appendEntity(const ValueDecl *decl);
void appendProtocolConformance(const ProtocolConformance *conformance);
};
} // end namespace NewMangling
} // end namespace swift
#endif // __SWIFT_AST_ASTMANGLER_H__

View File

@@ -316,6 +316,8 @@ void mangleIdentifier(const char *data, size_t length,
/// This should always round-trip perfectly with demangleSymbolAsNode.
std::string mangleNode(const NodePointer &root);
std::string mangleNodeNew(const NodePointer &root);
/// \brief Transform the node structure to a string.
///
/// Typical usage:
@@ -387,10 +389,19 @@ public:
std::string &&str() && { return std::move(Stream); }
llvm::StringRef getStringRef() const { return Stream; }
/// Returns a mutable reference to the last character added to the printer.
char &lastChar() { return Stream.back(); }
private:
std::string Stream;
};
bool mangleStandardSubstitution(Node *node, DemanglerPrinter &Out);
bool isSpecialized(Node *node);
NodePointer getUnspecialized(Node *node);
/// Is a character considered a digit by the demangling grammar?
///
/// Yes, this is equivalent to the standard C isdigit(3), but some platforms

View File

@@ -161,7 +161,14 @@ NODE(VTableAttribute)
NODE(Weak)
CONTEXT_NODE(WillSet)
NODE(WitnessTableOffset)
NODE(ReflectionMetadataBuiltinDescriptor)
NODE(ReflectionMetadataFieldDescriptor)
NODE(ReflectionMetadataAssocTypeDescriptor)
NODE(ReflectionMetadataSuperclassDescriptor)
CONTEXT_NODE(CurryThunk)
NODE(ThrowsAnnotation)
NODE(EmptyList)
NODE(FirstElementMarker)
NODE(VariadicMarker)
#undef CONTEXT_NODE
#undef NODE

View File

@@ -0,0 +1,247 @@
//===--- Demangler.h - String to Node-Tree Demangling -----------*- 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_BASIC_DEMANGLER_H
#define SWIFT_BASIC_DEMANGLER_H
#include "swift/Basic/Demangle.h"
#include <vector>
using namespace swift::Demangle;
using llvm::StringRef;
namespace swift {
namespace NewMangling {
class Demangler {
StringRef Text;
size_t Pos;
struct NodeWithPos {
NodePointer Node;
size_t Pos;
};
std::vector<NodeWithPos> NodeStack;
std::vector<NodePointer> Substitutions;
std::vector<unsigned> PendingSubstitutions;
std::vector<StringRef> Words;
static NodePointer pop_back_val(std::vector<NodePointer> &NodeVector) {
if (NodeVector.empty())
return nullptr;
NodePointer Val = NodeVector.back();
NodeVector.pop_back();
return Val;
}
bool nextIf(StringRef str) {
if (!Text.substr(Pos).startswith(str)) return false;
Pos += str.size();
return true;
}
char peekChar() {
if (Pos >= Text.size())
return 0;
return Text[Pos];
}
char nextChar() {
if (Pos >= Text.size())
return 0;
return Text[Pos++];
}
bool nextIf(char c) {
if (peekChar() != c)
return false;
Pos++;
return true;
}
void pushBack() {
assert(Pos > 0);
Pos--;
}
void pushNode(NodePointer Nd) {
NodeStack.push_back({ Nd, Pos });
}
NodePointer popNode() {
if (!NodeStack.empty()) {
NodePointer Val = NodeStack.back().Node;
NodeStack.pop_back();
return Val;
}
return nullptr;
}
NodePointer popNode(Node::Kind kind) {
if (NodeStack.empty())
return nullptr;
Node::Kind NdKind = NodeStack.back().Node->getKind();
if (NdKind != kind)
return nullptr;
return popNode();
}
template <typename Pred> NodePointer popNode(Pred pred) {
if (NodeStack.empty())
return nullptr;
Node::Kind NdKind = NodeStack.back().Node->getKind();
if (!pred(NdKind))
return nullptr;
return popNode();
}
public:
Demangler(llvm::StringRef mangled) : Text(mangled), Pos(0) {}
NodePointer demangleTopLevel();
private:
void addSubstitution(NodePointer Nd) {
if (Nd)
Substitutions.push_back(Nd);
}
static NodePointer addChild(NodePointer Parent, NodePointer Child) {
if (!Parent || !Child)
return nullptr;
Parent->addChild(Child);
return Parent;
}
static NodePointer createWithChild(Node::Kind kind, NodePointer Child) {
if (!Child)
return nullptr;
NodePointer Nd = NodeFactory::create(kind);
Nd->addChild(Child);
return Nd;
}
static NodePointer createType(NodePointer Child) {
return createWithChild(Node::Kind::Type, Child);
}
static NodePointer createWithChildren(Node::Kind kind, NodePointer Child1,
NodePointer Child2) {
if (!Child1 || !Child2)
return nullptr;
NodePointer Nd = NodeFactory::create(kind);
Nd->addChild(Child1);
Nd->addChild(Child2);
return Nd;
}
static NodePointer createWithChildren(Node::Kind kind, NodePointer Child1,
NodePointer Child2,
NodePointer Child3) {
if (!Child1 || !Child2 || !Child3)
return nullptr;
NodePointer Nd = NodeFactory::create(kind);
Nd->addChild(Child1);
Nd->addChild(Child2);
Nd->addChild(Child3);
return Nd;
}
NodePointer createWithPoppedType(Node::Kind kind) {
return createWithChild(kind, popNode(Node::Kind::Type));
}
NodePointer swapWith(Node::Kind kind) {
NodePointer Nd = popNode();
pushNode(NodeFactory::create(kind));
return Nd;
}
NodePointer changeKind(NodePointer Node, Node::Kind NewKind);
NodePointer demangleOperator();
int demangleNatural();
int demangleIndex();
NodePointer demangleIndexAsNode();
NodePointer demangleIdentifier();
NodePointer demangleOperatorIdentifier();
NodePointer demangleMultiSubstitutions();
static NodePointer createSwiftType(Node::Kind typeKind, StringRef name);
NodePointer demangleKnownType();
NodePointer demangleLocalIdentifier();
NodePointer popModule();
NodePointer popContext();
NodePointer popTypeAndGetChild();
NodePointer popTypeAndGetNominal();
NodePointer demangleBuiltinType();
NodePointer demangleNominalType(Node::Kind kind);
NodePointer demangleTypeAlias();
NodePointer demangleExtensionContext();
NodePointer demanglePlainFunction();
NodePointer popFunctionType(Node::Kind kind);
NodePointer popFunctionParams(Node::Kind kind);
NodePointer popTuple();
NodePointer popTypeList();
NodePointer popProtocol();
NodePointer demangleBoundGenericType();
NodePointer demangleBoundGenericArgs(NodePointer nominalType);
NodePointer demangleInitializer();
NodePointer demangleImplParamConvention();
NodePointer demangleImplResultConvention(Node::Kind ConvKind);
NodePointer demangleImplFunctionType();
NodePointer demangleMetatype();
static NodePointer createArchetypeRef(int depth, int i);
NodePointer demangleArchetype();
NodePointer demangleAssociatedTypeSimple(NodePointer GenericParamIdx);
NodePointer demangleAssociatedTypeCompound(NodePointer GenericParamIdx);
NodePointer popAssocTypeName();
static NodePointer getDependentGenericParamType(int depth, int index);
NodePointer demangleGenericParamIndex();
NodePointer popProtocolConformance();
NodePointer demangleThunkOrSpecialization();
NodePointer demangleGenericSpecialization(Node::Kind SpecKind);
NodePointer demangleFunctionSpecialization();
NodePointer demangleFuncSpecParam(Node::IndexType ParamIdx);
NodePointer addFuncSpecParamIdentifier(NodePointer Param,
FunctionSigSpecializationParamKind Kind,
StringRef FirstParam = StringRef());
NodePointer addFuncSpecParamNumber(NodePointer Param,
FunctionSigSpecializationParamKind Kind);
NodePointer demangleSpecAttributes(Node::Kind SpecKind);
NodePointer demangleWitness();
NodePointer demangleSpecialType();
NodePointer demangleMetatypeRepresentation();
NodePointer demangleFunctionEntity();
NodePointer demangleEntity(Node::Kind Kind);
NodePointer demangleProtocolListType();
NodePointer demangleGenericSignature(bool hasParamCounts);
NodePointer demangleGenericRequirement();
NodePointer demangleGenericType();
NodePointer demangleValueWitness();
};
} // end namespace NewMangling
} // end namespace swift
#endif // SWIFT_BASIC_DEMANGLER_H

View File

@@ -0,0 +1,170 @@
//===--- Mangler.h - Base class for Swift name 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_BASIC_MANGLER_H
#define SWIFT_BASIC_MANGLER_H
#include "swift/Basic/ManglingUtils.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/raw_ostream.h"
using llvm::StringRef;
using llvm::ArrayRef;
namespace swift {
namespace NewMangling {
/// Returns true if the new mangling scheme should be used.
///
/// TODO: remove this function when the old mangling is removed.
bool useNewMangling();
/// Select an old or new mangled string, based on useNewMangling().
///
/// Also performs test to check if the demangling of both string yield the same
/// demangling tree.
/// TODO: remove this function when the old mangling is removed.
std::string selectMangling(const std::string &Old, const std::string &New);
void printManglingStats();
/// The basic Swift symbol mangler.
///
/// This class serves as a abstract base class for specific manglers. It
/// provides some basic utilities, like handling of substitutions, mangling of
/// identifiers, etc.
class Mangler {
protected:
template <typename Mangler>
friend void mangleIdentifier(Mangler &M, StringRef ident);
/// The storage for the mangled symbol.
llvm::SmallVector<char, 128> Storage;
/// The output stream for the mangled symbol.
llvm::raw_svector_ostream Buffer;
/// A temporary storage needed by the ::mangleIdentifier() template function.
llvm::SmallVector<WordReplacement, 8> SubstWordsInIdent;
/// Substitutions, except identifier substitutions.
llvm::DenseMap<const void *, unsigned> Substitutions;
/// Identifier substitutions.
llvm::StringMap<unsigned> StringSubstitutions;
/// The position in the Buffer where the last substitution was written.
int lastSubstIdx = -2;
/// Word substitutions in mangled identifiers.
llvm::SmallVector<SubstitutionWord, 26> Words;
/// If enabled, non-ASCII names are encoded in modified Punycode.
bool UsePunycode;
/// A helpful little wrapper for an integer value that should be mangled
/// in a particular, compressed value.
class Index {
unsigned N;
public:
explicit Index(unsigned n) : N(n) {}
friend llvm::raw_ostream &operator<<(llvm::raw_ostream &out, Index n) {
if (n.N != 0) out << (n.N - 1);
return (out << '_');
}
};
/// Returns the buffer as a StringRef, needed by mangleIdentifier().
StringRef getBufferStr() const {
return StringRef(Storage.data(), Storage.size());
}
protected:
Mangler(bool usePunycode) : Buffer(Storage), UsePunycode(usePunycode) { }
/// Adds the mangling prefix.
void beginMangling();
/// 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);
/// Appends a mangled identifier string.
void appendIdentifier(StringRef ident);
void addSubstitution(const void *ptr) {
Substitutions[ptr] = Substitutions.size() + StringSubstitutions.size();
}
void addSubstitution(StringRef Str) {
StringSubstitutions[Str] = Substitutions.size() + StringSubstitutions.size();
}
bool tryMangleSubstitution(const void *ptr);
void mangleSubstitution(unsigned Index);
#ifndef NDEBUG
void recordOpStatImpl(StringRef op, size_t OldPos);
#endif
void recordOpStat(StringRef op, size_t OldPos) {
#ifndef NDEBUG
recordOpStatImpl(op, OldPos);
#endif
}
void appendOperator(StringRef op) {
size_t OldPos = Storage.size();
Buffer << op;
recordOpStat(op, OldPos);
}
void appendOperator(StringRef op, int natural) {
size_t OldPos = Storage.size();
Buffer << op << natural << '_';
recordOpStat(op, OldPos);
}
void appendOperator(StringRef op, Index index) {
size_t OldPos = Storage.size();
Buffer << op << index;
recordOpStat(op, OldPos);
}
void appendOperator(StringRef op, Index index1, Index index2) {
size_t OldPos = Storage.size();
Buffer << op << index1 << index2;
recordOpStat(op, OldPos);
}
void appendOperator(StringRef op, StringRef arg) {
size_t OldPos = Storage.size();
Buffer << op << arg;
recordOpStat(op, OldPos);
}
void appendListSeparator() {
appendOperator("_");
}
void appendListSeparator(bool &isFirstListItem) {
if (isFirstListItem) {
appendListSeparator();
isFirstListItem = false;
}
}
};
} // end namespace Mangle
} // end namespace swift
#endif // SWIFT_BASIC_MANGLER_H

View File

@@ -0,0 +1,107 @@
//===--- ManglingMacros.h - Macros for 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_BASIC_MANGLING_MACROS_H
#define SWIFT_BASIC_MANGLING_MACROS_H
// The following macro enables the "new" mangling, which has an _S prefix rather
// then the original _T prefix.
// TODO: When we get rid of the old mangling, the term "new mangling" should
// just be renamed to "mangling".
//#define USE_NEW_MANGLING
#define STRINGIFY_MANGLING(M) #M
#define MANGLE_AS_STRING(M) STRINGIFY_MANGLING(M)
/// The mangling prefix for the new mangling.
#define MANGLING_PREFIX _S
#define MANGLING_PREFIX_STR MANGLE_AS_STRING(MANGLING_PREFIX)
// The following macros help to create symbol manglings. They can be used
// if a mangled name is needed at compile-time, e.g. for variable names in the
// swift runtime libraries.
#define MANGLING_CONCAT2_IMPL(a, b) a##b
#define MANGLING_CONCAT3_IMPL(a, b, c) a##b##c
#ifdef USE_NEW_MANGLING
#define MANGLE_SYM(Ops) MANGLING_CONCAT2_IMPL(MANGLING_PREFIX, Ops)
#define MANGLING_CONCAT2(a, b) MANGLING_CONCAT2_IMPL(a, b)
#define MANGLING_CONCAT3(a, b, c) MANGLING_CONCAT3_IMPL(a, b, c)
#define SELECT_MANGLING(Old, New) New
#define METADATA_MANGLING N
#define METATYPE_MANGLING m
#define EMPTY_TUPLE_MANGLING yt
#define NO_ARGS_MANGLING yy
#define FUNC_TYPE_MANGLING c
#else
#define MANGLE_SYM(Ops) MANGLING_CONCAT2_IMPL(_T, Ops)
#define MANGLING_CONCAT2(a, b) MANGLING_CONCAT2_IMPL(b, a)
#define MANGLING_CONCAT3(a, b, c) MANGLING_CONCAT3_IMPL(c, b, a)
#define SELECT_MANGLING(Old, New) Old
#define METADATA_MANGLING M
#define METATYPE_MANGLING M
#define EMPTY_TUPLE_MANGLING T_
#define NO_ARGS_MANGLING T_T_
#define FUNC_TYPE_MANGLING F
#endif
#define FUNCTION_MANGLING \
MANGLING_CONCAT2(NO_ARGS_MANGLING, FUNC_TYPE_MANGLING)
#define THIN_FUNCTION_MANGLING \
MANGLING_CONCAT2(NO_ARGS_MANGLING, Xf)
#define OPTIONAL_MANGLING(Ty) \
MANGLING_CONCAT3(MANGLING_CONCAT2_IMPL(Ty, _), Sq, G)
#define METADATA_SYM(Ty) \
MANGLE_SYM(MANGLING_CONCAT2(Ty, METADATA_MANGLING))
#define STRUCT_METADATA_SYM(Ty) \
MANGLE_SYM(MANGLING_CONCAT3(Ty, V, METADATA_MANGLING))
#define CLASS_METADATA_SYM(Ty) \
MANGLE_SYM(MANGLING_CONCAT3(Ty, C, METADATA_MANGLING))
#define STRUCT_MD_ACCESSOR_SYM(Ty) \
MANGLE_SYM(MANGLING_CONCAT3(Ty, V, Ma))
#define VALUE_WITNESS_SYM(Ty) \
MANGLE_SYM(MANGLING_CONCAT2(Ty, WV))
#define UNOWNED_VALUE_WITNESS_SYM(Ty) \
MANGLE_SYM(MANGLING_CONCAT3(Ty, Xo, WV))
#define WEAK_VALUE_WITNESS_SYM(Ty) \
MANGLE_SYM(MANGLING_CONCAT3(OPTIONAL_MANGLING(Ty), Xw, WV))
#define METATYPE_VALUE_WITNESS_SYM(Ty) \
MANGLE_SYM(MANGLING_CONCAT3(Ty, METATYPE_MANGLING, WV))
#define NOMINAL_TYPE_DESCR_SYM(Ty) \
MANGLE_SYM(MANGLING_CONCAT2(Ty, Mn))
#define STRUCT_TYPE_DESCR_SYM(Ty) \
MANGLE_SYM(MANGLING_CONCAT3(Ty, V, Mn))
#define PROTOCOL_DESCR_SYM(Ty) \
MANGLE_SYM(MANGLING_CONCAT2(Ty, Mp))
#endif // SWIFT_BASIC_MANGLING_MACROS_H

View File

@@ -0,0 +1,222 @@
//===--- ManglingUtils.h - Utilities for Swift name 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_BASIC_MANGLINGUTILS_H
#define SWIFT_BASIC_MANGLINGUTILS_H
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/ArrayRef.h"
#include "swift/Basic/Punycode.h"
namespace swift {
namespace NewMangling {
inline bool isLowerLetter(char ch) {
return ch >= 'a' && ch <= 'z';
}
inline bool isUpperLetter(char ch) {
return ch >= 'A' && ch <= 'Z';
}
inline bool isDigit(char ch) {
return ch >= '0' && ch <= '9';
}
inline bool isLetter(char ch) {
return isLowerLetter(ch) || isUpperLetter(ch);
}
/// Returns true if \p ch is a character which defines the begin of a
/// substitution word.
inline bool isWordStart(char ch) {
return !isDigit(ch) && ch != '_' && ch != 0;
}
/// Returns true if \p ch is a character (following \p prevCh) which defines
/// the end of a substitution word.
inline bool isWordEnd(char ch, char prevCh) {
if (ch == '_' || ch == 0)
return true;
if (!isUpperLetter(prevCh) && isUpperLetter(ch))
return true;
return false;
}
/// Returns true if \p ch is a valid character which may appear in a symbol
/// mangling.
inline bool isValidSymbolChar(char ch) {
return isLetter(ch) || isDigit(ch) || ch == '_' || ch == '$';
}
/// Returns true if \p str contains any character which may not appear in a
/// mangled symbol string and therefore must be punycode encoded.
bool needsPunycodeEncoding(StringRef str);
/// Returns true if \p str contains any non-ASCII character.
bool isNonAscii(StringRef str);
/// Describes a Word in a mangled identifier.
struct SubstitutionWord {
/// The position of the first word character in the mangled string.
size_t start;
/// The length of the word.
size_t length;
};
/// Helper struct which represents a word substitution.
struct WordReplacement {
/// The position in the identifier where the word is substituted.
size_t StringPos;
/// The index into the mangler's Words array (-1 if invalid).
int WordIdx;
};
/// Translate the given operator character into its mangled form.
///
/// Current operator characters: @/=-+*%<>!&|^~ and the special operator '..'
char translateOperatorChar(char op);
/// Returns a string where all characters of the operator \Op are translated to
/// their mangled form.
std::string translateOperator(StringRef Op);
/// Mangles an identifier using a generic Mangler class.
///
/// The Mangler class must provide the following:
/// *) Words: An array of SubstitutionWord which holds the current list of
/// found words which can be used for substitutions.
/// *) SubstWordsInIdent: An array of WordReplacement, which is just used
/// as a temporary storage during mangling. Must be empty.
/// *) Buffer: A stream where the mangled identifier is written to.
/// *) getBufferStr(): Returns a StringRef of the current content of Buffer.
/// *) UsePunycode: A flag indicating if punycode encoding should be done.
template <typename Mangler>
void mangleIdentifier(Mangler &M, StringRef ident) {
size_t WordsInBuffer = M.Words.size();
assert(M.SubstWordsInIdent.empty());
std::string punycodeBuf;
if (M.UsePunycode && needsPunycodeEncoding(ident)) {
// If the identifier contains non-ASCII character, we mangle
// with an initial '00' and Punycode the identifier string.
Punycode::encodePunycodeUTF8(ident, punycodeBuf,
/*mapNonSymbolChars*/ true);
ident = punycodeBuf;
M.Buffer << "00";
} else {
// Search for word substitutions and for new words.
const size_t NotInsideWord = ~0;
size_t wordStartPos = NotInsideWord;
for (size_t Pos = 0, Len = ident.size(); Pos <= Len; ++Pos) {
char ch = (Pos < Len ? ident[Pos] : 0);
if (wordStartPos != NotInsideWord && isWordEnd(ch, ident[Pos - 1])) {
// This position is the end of a word, i.e. the next character after a
// word.
assert(Pos > wordStartPos);
size_t wordLen = Pos - wordStartPos;
StringRef Word = ident.substr(wordStartPos, wordLen);
// Helper function to lookup the Word in a string.
auto lookupWord = [&] (StringRef Str,
size_t FromWordIdx, size_t ToWordIdx) -> int {
for (size_t Idx = FromWordIdx; Idx < ToWordIdx; ++Idx) {
const SubstitutionWord &w = M.Words[Idx];
StringRef existingWord = Str.substr(w.start, w.length);
if (Word == existingWord)
return (int)Idx;
}
return -1;
};
// Is the word already present in the so far mangled string?
int WordIdx = lookupWord(M.getBufferStr(), 0, WordsInBuffer);
// Otherwise, is the word already present in this identifier?
if (WordIdx < 0)
WordIdx = lookupWord(ident, WordsInBuffer, M.Words.size());
if (WordIdx >= 0) {
// We found a word substitution!
assert(WordIdx < 26);
M.SubstWordsInIdent.push_back({wordStartPos, WordIdx});
} else if (wordLen >= 2 && M.Words.size() < 26) {
// It's a new word: remember it.
// Note: at this time the word's start position is relative to the
// begin of the identifier. We must update it afterwards so that it is
// relative to the begin of the whole mangled Buffer.
M.Words.push_back({wordStartPos, wordLen});
}
wordStartPos = NotInsideWord;
}
if (wordStartPos == NotInsideWord && isWordStart(ch)) {
// This position is the begin of a word.
wordStartPos = Pos;
}
}
// If we have word substitutions mangle an initial '0'.
if (!M.SubstWordsInIdent.empty())
M.Buffer << '0';
}
size_t Pos = 0;
// Add a dummy-word at the end of the list.
M.SubstWordsInIdent.push_back({ident.size(), -1});
// Mangle a sequence of word substitutions and sub-strings.
for (size_t Idx = 0, End = M.SubstWordsInIdent.size(); Idx < End; ++Idx) {
const WordReplacement &Repl = M.SubstWordsInIdent[Idx];
if (Pos < Repl.StringPos) {
// Mangle the sub-string up to the next word substitution (or to the end
// of the identifier - that's why we added the dummy-word).
// The first thing: we add the encoded sub-string length.
M.Buffer << (Repl.StringPos - Pos);
assert(!isDigit(ident[Pos]) &&
"first char of sub-string may not be a digit");
do {
// Update the start position of new added words, so that they refer to
// the begin of the whole mangled Buffer.
if (WordsInBuffer < M.Words.size() &&
M.Words[WordsInBuffer].start == Pos) {
M.Words[WordsInBuffer].start = M.getBufferStr().size();
WordsInBuffer++;
}
// Add a literal character of the sub-string.
M.Buffer << ident[Pos];
Pos++;
} while (Pos < Repl.StringPos);
}
// Is it a "real" word substitution (and not the dummy-word)?
if (Repl.WordIdx >= 0) {
assert(Repl.WordIdx <= (int)WordsInBuffer);
Pos += M.Words[Repl.WordIdx].length;
if (Idx < End - 2) {
M.Buffer << (char)(Repl.WordIdx + 'a');
} else {
// The last word substitution is a captial letter.
M.Buffer << (char)(Repl.WordIdx + 'A');
if (Pos == ident.size())
M.Buffer << '0';
}
}
}
M.SubstWordsInIdent.clear();
}
} // end namespace Mangle
} // end namespace swift
#endif // SWIFT_BASIC_MANGLINGUTILS_H

View File

@@ -0,0 +1,151 @@
//===--- SpecializationMangler.h - mangling of specializations --*- 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_SILOPTIMIZER_UTILS_SPECIALIZATIONMANGLER_H
#define SWIFT_SILOPTIMIZER_UTILS_SPECIALIZATIONMANGLER_H
#include "swift/Basic/Demangler.h"
#include "swift/Basic/NullablePtr.h"
#include "swift/AST/ASTMangler.h"
#include "swift/SIL/SILLinkage.h"
#include "swift/SIL/SILFunction.h"
namespace swift {
namespace NewMangling {
enum class SpecializationKind : uint8_t {
Generic,
NotReAbstractedGeneric,
FunctionSignature,
};
/// Inject SpecializationPass into the Mangle namespace.
using SpecializationPass = Demangle::SpecializationPass;
/// The base class for specialization mangles.
class SpecializationMangler : public NewMangling::ASTMangler {
protected:
/// The specialization pass.
SpecializationPass Pass;
IsFragile_t Fragile;
/// The original function which is specialized.
SILFunction *Function;
llvm::SmallVector<char, 32> ArgOpStorage;
llvm::raw_svector_ostream ArgOpBuffer;
protected:
SpecializationMangler(SpecializationPass P, IsFragile_t Fragile,
SILFunction *F)
: Pass(P), Fragile(Fragile), Function(F), ArgOpBuffer(ArgOpStorage) {}
SILFunction *getFunction() const { return Function; }
void beginMangling();
/// Finish the mangling of the symbol and return the mangled name.
std::string finalize();
void appendSpecializationOperator(StringRef Op) {
appendOperator(Op, StringRef(ArgOpStorage.data(), ArgOpStorage.size()));
}
};
// The mangler for specialized generic functions.
class GenericSpecializationMangler : public SpecializationMangler {
ArrayRef<Substitution> Subs;
public:
bool isReAbstracted;
GenericSpecializationMangler(SILFunction *F,
ArrayRef<Substitution> Subs,
IsFragile_t Fragile,
bool isReAbstracted)
: SpecializationMangler(SpecializationPass::GenericSpecializer, Fragile, F),
Subs(Subs), isReAbstracted(isReAbstracted) {}
std::string mangle();
};
// The mangler for functions where arguments are specialized.
class FunctionSignatureSpecializationMangler : public SpecializationMangler {
using ReturnValueModifierIntBase = uint16_t;
enum class ReturnValueModifier : ReturnValueModifierIntBase {
// Option Space 4 bits (i.e. 16 options).
Unmodified=0,
First_Option=0, Last_Option=31,
// Option Set Space. 12 bits (i.e. 12 option).
Dead=32,
OwnedToUnowned=64,
First_OptionSetEntry=32, LastOptionSetEntry=32768,
};
// We use this private typealias to make it easy to expand ArgumentModifier's
// size if we need to.
using ArgumentModifierIntBase = uint16_t;
enum class ArgumentModifier : ArgumentModifierIntBase {
// Option Space 4 bits (i.e. 16 options).
Unmodified=0,
ConstantProp=1,
ClosureProp=2,
BoxToValue=3,
BoxToStack=4,
First_Option=0, Last_Option=31,
// Option Set Space. 12 bits (i.e. 12 option).
Dead=32,
OwnedToGuaranteed=64,
SROA=128,
First_OptionSetEntry=32, LastOptionSetEntry=32768,
};
using ArgInfo = std::pair<ArgumentModifierIntBase,
NullablePtr<SILInstruction>>;
llvm::SmallVector<ArgInfo, 8> Args;
ReturnValueModifierIntBase ReturnValue;
public:
FunctionSignatureSpecializationMangler(SpecializationPass Pass,
IsFragile_t Fragile,
SILFunction *F);
void setArgumentConstantProp(unsigned ArgNo, LiteralInst *LI);
void setArgumentClosureProp(unsigned ArgNo, PartialApplyInst *PAI);
void setArgumentClosureProp(unsigned ArgNo, ThinToThickFunctionInst *TTTFI);
void setArgumentDead(unsigned ArgNo);
void setArgumentOwnedToGuaranteed(unsigned ArgNo);
void setArgumentSROA(unsigned ArgNo);
void setArgumentBoxToValue(unsigned ArgNo);
void setArgumentBoxToStack(unsigned ArgNo);
void setReturnValueOwnedToUnowned();
std::string mangle();
private:
void mangleConstantProp(LiteralInst *LI);
void mangleClosureProp(SILInstruction *Inst);
void mangleArgument(ArgumentModifierIntBase ArgMod,
NullablePtr<SILInstruction> Inst);
void mangleReturnValue(ReturnValueModifierIntBase RetMod);
};
} // end namespace NewMangling
} // end namespace swift
#endif

1675
lib/AST/ASTMangler.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -2,6 +2,7 @@ add_swift_library(swiftAST STATIC
ArchetypeBuilder.cpp
ASTContext.cpp
ASTDumper.cpp
ASTMangler.cpp
ASTNode.cpp
ASTPrinter.cpp
ASTScope.cpp

View File

@@ -65,6 +65,7 @@ add_swift_library(swiftBasic STATIC
Cache.cpp
ClusteredBitVector.cpp
Demangle.cpp
Demangler.cpp
DemangleWrappers.cpp
DiagnosticConsumer.cpp
DiverseStack.cpp
@@ -74,6 +75,8 @@ add_swift_library(swiftBasic STATIC
JSONSerialization.cpp
LangOptions.cpp
LLVMContext.cpp
Mangler.cpp
ManglingUtils.cpp
Platform.cpp
PrefixMap.cpp
PrettyStackTrace.cpp
@@ -83,6 +86,7 @@ add_swift_library(swiftBasic STATIC
PunycodeUTF8.cpp
QuotedString.cpp
Remangle.cpp
Remangler.cpp
SourceLoc.cpp
StringExtras.cpp
TaskQueue.cpp

View File

@@ -2375,6 +2375,7 @@ private:
case Node::Kind::AutoClosureType:
case Node::Kind::CFunctionPointer:
case Node::Kind::Constructor:
case Node::Kind::CurryThunk:
case Node::Kind::Deallocator:
case Node::Kind::DeclContext:
case Node::Kind::DefaultArgumentInitializer:
@@ -2474,7 +2475,14 @@ private:
case Node::Kind::Weak:
case Node::Kind::WillSet:
case Node::Kind::WitnessTableOffset:
case Node::Kind::ReflectionMetadataBuiltinDescriptor:
case Node::Kind::ReflectionMetadataFieldDescriptor:
case Node::Kind::ReflectionMetadataAssocTypeDescriptor:
case Node::Kind::ReflectionMetadataSuperclassDescriptor:
case Node::Kind::ThrowsAnnotation:
case Node::Kind::EmptyList:
case Node::Kind::FirstElementMarker:
case Node::Kind::VariadicMarker:
return false;
}
unreachable("bad node kind");
@@ -2864,6 +2872,10 @@ void NodePrinter::print(NodePointer pointer, bool asContext, bool suppressType)
Printer << "static ";
print(pointer->getChild(0), asContext, suppressType);
return;
case Node::Kind::CurryThunk:
Printer << "curry thunk of ";
print(pointer->getChild(0), asContext, suppressType);
return;
case Node::Kind::Directness:
Printer << toString(Directness(pointer->getIndex())) << " ";
return;
@@ -3639,10 +3651,35 @@ void NodePrinter::print(NodePointer pointer, bool asContext, bool suppressType)
Printer << pointer->getText();
return;
}
case Node::Kind::ThrowsAnnotation: {
case Node::Kind::ReflectionMetadataBuiltinDescriptor:
Printer << "reflection metadata builtin descriptor ";
print(pointer->getChild(0));
return;
case Node::Kind::ReflectionMetadataFieldDescriptor:
Printer << "reflection metadata field descriptor ";
print(pointer->getChild(0));
return;
case Node::Kind::ReflectionMetadataAssocTypeDescriptor:
Printer << "reflection metadata associated type descriptor ";
print(pointer->getChild(0));
return;
case Node::Kind::ReflectionMetadataSuperclassDescriptor:
Printer << "reflection metadata superclass descriptor ";
print(pointer->getChild(0));
return;
case Node::Kind::ThrowsAnnotation:
Printer<< " throws ";
return;
}
case Node::Kind::EmptyList:
Printer << " empty-list ";
return;
case Node::Kind::FirstElementMarker:
Printer << " first-element-marker ";
return;
case Node::Kind::VariadicMarker:
Printer << " variadic-marker ";
return;
}
unreachable("bad node kind!");
}

1531
lib/Basic/Demangler.cpp Normal file

File diff suppressed because it is too large Load Diff

318
lib/Basic/Mangler.cpp Normal file
View File

@@ -0,0 +1,318 @@
//===--- Mangler.cpp - Base class for Swift name mangling -----------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#define CHECK_MANGLING_AGAINST_OLD
#include "swift/Basic/Mangler.h"
#include "swift/Basic/Punycode.h"
#include "swift/Basic/ManglingMacros.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/CommandLine.h"
#ifdef CHECK_MANGLING_AGAINST_OLD
#include "swift/Basic/Demangle.h"
#include "swift/Basic/DemangleWrappers.h"
#endif
#include <algorithm>
using namespace swift;
using namespace NewMangling;
bool NewMangling::useNewMangling() {
#ifdef USE_NEW_MANGLING
return true;
#else
return false;
#endif
}
#ifndef NDEBUG
llvm::cl::opt<bool> PrintSwiftManglingStats(
"print-swift-mangling-stats", llvm::cl::init(false),
llvm::cl::desc("Print statistics about Swift symbol mangling"));
namespace {
#ifdef CHECK_MANGLING_AGAINST_OLD
static bool areTreesEqual(Demangle::NodePointer Old, Demangle::NodePointer New) {
if ((Old != nullptr) != (New != nullptr))
return false;
if (!Old)
return true;
if (Old->getKind() == Demangle::Node::Kind::CurryThunk)
Old = Old->getFirstChild();
if (New->getKind() == Demangle::Node::Kind::CurryThunk)
New = New->getFirstChild();
if (Old->getKind() != New->getKind()) {
if (Old->getKind() != Demangle::Node::Kind::UncurriedFunctionType ||
New->getKind() != Demangle::Node::Kind::FunctionType)
return false;
}
if (Old->hasText() != New->hasText())
return false;
if (Old->hasIndex() != New->hasIndex())
return false;
if (Old->hasText() && Old->getText() != New->getText())
return false;
if (Old->hasIndex() && Old->getIndex() != New->getIndex())
return false;
size_t OldNum = Old->getNumChildren();
size_t NewNum = New->getNumChildren();
if (OldNum >= 1 && NewNum == 1 &&
Old->getChild(OldNum - 1)->getKind() == Demangle::Node::Kind::Suffix) {
switch (New->getFirstChild()->getKind()) {
case Demangle::Node::Kind::ReflectionMetadataBuiltinDescriptor:
case Demangle::Node::Kind::ReflectionMetadataFieldDescriptor:
case Demangle::Node::Kind::ReflectionMetadataAssocTypeDescriptor:
case Demangle::Node::Kind::ReflectionMetadataSuperclassDescriptor:
return true;
default:
return false;
}
}
if (Old->getKind() == Demangle::Node::Kind::DependentAssociatedTypeRef &&
OldNum + NewNum == 1) {
OldNum = 0;
NewNum = 0;
}
if (Old->getKind() == Demangle::Node::Kind::GenericSpecializationParam &&
OldNum > 1 && NewNum == 1)
OldNum = 1;
if (OldNum != NewNum) {
return false;
}
for (unsigned Idx = 0, End = OldNum; Idx < End; ++Idx) {
if (!areTreesEqual(Old->getChild(Idx), New->getChild(Idx)))
return false;
}
return true;
}
static bool containsDependentAssociatedTypeRef(Demangle::NodePointer Nd) {
if (Nd->getKind() == Demangle::Node::Kind::DependentAssociatedTypeRef)
return true;
for (auto Child : *Nd) {
if (containsDependentAssociatedTypeRef(Child))
return true;
}
return false;
}
#endif // CHECK_MANGLING_AGAINST_OLD
struct SizeStatEntry {
int sizeDiff;
std::string Old;
std::string New;
};
static std::vector<SizeStatEntry> SizeStats;
static int numSmaller = 0;
static int numEqual = 0;
static int numLarger = 0;
static int totalOldSize = 0;
static int totalNewSize = 0;
static int mergedSubsts = 0;
struct OpStatEntry {
OpStatEntry() : num(0), size(0) { }
int num;
int size;
};
static llvm::StringMap<OpStatEntry> OpStats;
} // end anonymous namespace
void Mangler::recordOpStatImpl(StringRef op, size_t OldPos) {
if (PrintSwiftManglingStats) {
OpStatEntry &E = OpStats[op];
E.num++;
E.size += Storage.size() - OldPos;
}
}
#endif // NDEBUG
std::string NewMangling::selectMangling(const std::string &Old,
const std::string &New) {
#ifndef NDEBUG
#ifdef CHECK_MANGLING_AGAINST_OLD
static int numCmp = 0;
using namespace Demangle;
NodePointer OldNode = demangleSymbolAsNode(Old);
NodePointer NewNode = demangleSymbolAsNode(New);
if (OldNode) {
if (!areTreesEqual(OldNode, NewNode)) {
llvm::errs() << "Mangling differs at #" << numCmp << ":\n"
"old: " << Old << "\n"
"new: " << New << "\n\n"
"### old tree: ###\n";
demangle_wrappers::NodeDumper(OldNode).print(llvm::errs());
llvm::errs() << "\n### new tree: ###\n";
demangle_wrappers::NodeDumper(NewNode).print(llvm::errs());
llvm::errs() << '\n';
assert(false);
}
if (StringRef(New).startswith(MANGLING_PREFIX_STR)) {
std::string Remangled = mangleNodeNew(NewNode);
if (New != Remangled) {
bool isEqual = false;
if (containsDependentAssociatedTypeRef(NewNode)) {
NodePointer RemangledNode = demangleSymbolAsNode(Remangled);
isEqual = areTreesEqual(RemangledNode, NewNode);
}
if (!isEqual) {
llvm::errs() << "Remangling failed at #" << numCmp << ":\n"
"original: " << New << "\n"
"remangled: " << Remangled << "\n";
assert(false);
}
}
}
}
numCmp++;
#endif // CHECK_MANGLING_AGAINST_OLD
if (PrintSwiftManglingStats) {
int OldSize = (int)Old.size();
int NewSize = (int)New.size();
if (NewSize > OldSize) {
numLarger++;
SizeStats.push_back({NewSize - OldSize, Old, New});
} else if (OldSize > NewSize) {
numSmaller++;
} else {
numEqual++;
}
totalOldSize += OldSize;
totalNewSize += NewSize;
}
#endif // NDEBUG
return useNewMangling() ? New : Old;
}
void NewMangling::printManglingStats() {
#ifndef NDEBUG
if (!PrintSwiftManglingStats)
return;
std::sort(SizeStats.begin(), SizeStats.end(),
[](const SizeStatEntry &LHS, const SizeStatEntry &RHS) {
return LHS.sizeDiff < RHS.sizeDiff;
});
llvm::outs() << "Mangling size stats:\n"
" num smaller: " << numSmaller << "\n"
" num larger: " << numLarger << "\n"
" num equal: " << numEqual << "\n"
" total old size: " << totalOldSize << "\n"
" total new size: " << totalNewSize << "\n"
" new - old size: " << (totalNewSize - totalOldSize) << "\n"
"List or larger:\n";
for (const SizeStatEntry &E : SizeStats) {
llvm::outs() << " delta " << E.sizeDiff << ": " << E.Old << " - " << E.New
<< '\n';
}
llvm::outs() << "Mangling operator stats:\n";
typedef llvm::StringMapEntry<OpStatEntry> MapEntry;
std::vector<const MapEntry *> SortedOpStats;
for (const MapEntry &ME : OpStats) {
SortedOpStats.push_back(&ME);
}
std::sort(SortedOpStats.begin(), SortedOpStats.end(),
[](const MapEntry *LHS, const MapEntry *RHS) {
return LHS->getKey() < RHS->getKey();
});
for (const MapEntry *E : SortedOpStats) {
llvm::outs() << " " << E->getKey() << ": num = " << E->getValue().num
<< ", size = " << E->getValue().size << '\n';
}
llvm::outs() << " merged substitutions: " << mergedSubsts << '\n';
#endif
}
void Mangler::beginMangling() {
Buffer << MANGLING_PREFIX_STR;
}
/// Finish the mangling of the symbol and return the mangled name.
std::string Mangler::finalize() {
assert(Storage.size() && "Mangling an empty name");
std::string result = std::string(Storage.data(), Storage.size());
Storage.clear();
return result;
}
/// Finish the mangling of the symbol and write the mangled name into
/// \p stream.
void Mangler::finalize(llvm::raw_ostream &stream) {
std::string result = finalize();
stream.write(result.data(), result.size());
}
void Mangler::appendIdentifier(StringRef ident) {
auto Iter = StringSubstitutions.find(ident);
if (Iter != StringSubstitutions.end())
return mangleSubstitution(Iter->second);
size_t OldPos = Storage.size();
addSubstitution(ident);
mangleIdentifier(*this, ident);
recordOpStat("<identifier>", OldPos);
}
bool Mangler::tryMangleSubstitution(const void *ptr) {
auto ir = Substitutions.find(ptr);
if (ir == Substitutions.end())
return false;
mangleSubstitution(ir->second);
return true;
}
void Mangler::mangleSubstitution(unsigned Idx) {
if (Idx >= 26)
return appendOperator("A", Index(Idx - 26));
char c = Idx + 'A';
if (lastSubstIdx == (int)Storage.size() - 1) {
assert(isUpperLetter(Storage[lastSubstIdx]));
Storage[lastSubstIdx] = Storage[lastSubstIdx] - 'A' + 'a';
Buffer << c;
#ifndef NDEBUG
mergedSubsts++;
#endif
} else {
appendOperator("A", StringRef(&c, 1));
}
lastSubstIdx = (int)Storage.size() - 1;
}

View File

@@ -0,0 +1,67 @@
//===--- ManglingUtils.cpp - Utilities for Swift name mangling ------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "swift/Basic/ManglingUtils.h"
using namespace swift;
using namespace NewMangling;
bool NewMangling::isNonAscii(StringRef str) {
for (unsigned char c : str) {
if (c >= 0x80)
return true;
}
return false;
}
bool NewMangling::needsPunycodeEncoding(StringRef str) {
for (unsigned char c : str) {
if (!isValidSymbolChar(c))
return true;
}
return false;
}
/// Translate the given operator character into its mangled form.
///
/// Current operator characters: @/=-+*%<>!&|^~ and the special operator '..'
char NewMangling::translateOperatorChar(char op) {
switch (op) {
case '&': return 'a'; // 'and'
case '@': return 'c'; // 'commercial at sign'
case '/': return 'd'; // 'divide'
case '=': return 'e'; // 'equal'
case '>': return 'g'; // 'greater'
case '<': return 'l'; // 'less'
case '*': return 'm'; // 'multiply'
case '!': return 'n'; // 'negate'
case '|': return 'o'; // 'or'
case '+': return 'p'; // 'plus'
case '?': return 'q'; // 'question'
case '%': return 'r'; // 'remainder'
case '-': return 's'; // 'subtract'
case '~': return 't'; // 'tilde'
case '^': return 'x'; // 'xor'
case '.': return 'z'; // 'zperiod' (the z is silent)
default:
return op;
}
}
std::string NewMangling::translateOperator(StringRef Op) {
std::string Encoded;
for (char ch : Op) {
Encoded.push_back(translateOperatorChar(ch));
}
return Encoded;
}

View File

@@ -11,6 +11,7 @@
//===----------------------------------------------------------------------===//
#include "swift/Basic/Punycode.h"
#include "swift/Basic/ManglingUtils.h"
#include <vector>
using namespace swift;
@@ -19,11 +20,6 @@ static bool isContinuationByte(uint8_t unit) {
return (unit & 0xC0) == 0x80;
}
static bool isValidSymbolChar(char ch) {
return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9') || ch == '_' || ch == '$';
}
/// Reencode well-formed UTF-8 as UTF-32.
///
/// This entry point is only called from compiler-internal entry points, so does
@@ -40,7 +36,7 @@ static bool convertUTF8toUTF32(StringRef InputUTF8,
while (ptr < end) {
uint8_t first = *ptr++;
if (first < 0x80) {
if (isValidSymbolChar(first) || !mapNonSymbolChars) {
if (NewMangling::isValidSymbolChar(first) || !mapNonSymbolChars) {
OutUTF32.push_back(first);
} else {
OutUTF32.push_back((uint32_t)first + 0xD800);

View File

@@ -249,7 +249,6 @@ namespace {
unreachable("bad demangling tree node");
}
NodePointer getUnspecialized(Node *node);
void mangleGenericArgs(Node *node, EntityContext &ctx);
void mangleAnyNominalType(Node *node, EntityContext &ctx);
@@ -320,13 +319,13 @@ void Remangler::resetSubstitutions() {
Substitutions.clear();
}
bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry) {
auto isInSwiftModule = [](Node *node) -> bool {
auto context = node->begin()->get();
return (context->getKind() == Node::Kind::Module &&
context->getText() == STDLIB_NAME);
};
static bool isInSwiftModule(Node *node) {
auto context = node->begin()->get();
return (context->getKind() == Node::Kind::Module &&
context->getText() == STDLIB_NAME);
};
bool Demangle::mangleStandardSubstitution(Node *node, DemanglerPrinter &Out) {
// Look for known substitutions.
switch (node->getKind()) {
#define SUCCESS_IF_IS(VALUE, EXPECTED, SUBSTITUTION) \
@@ -378,6 +377,12 @@ bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry) {
#undef SUCCESS_IF_TEXT_IS
#undef SUCCESS_IF_IS
}
return false;
}
bool Remangler::trySubstitution(Node *node, SubstitutionEntry &entry) {
if (Demangle::mangleStandardSubstitution(node, Out))
return true;
// Go ahead and initialize the substitution entry.
entry.TheNode = node;
@@ -1496,7 +1501,7 @@ void Remangler::mangleProtocolWithoutPrefix(Node *node) {
mangleNominalType(node, '\0', ctx);
}
static bool isSpecialized(Node *node) {
bool Demangle::isSpecialized(Node *node) {
switch (node->getKind()) {
case Node::Kind::BoundGenericStructure:
case Node::Kind::BoundGenericEnum:
@@ -1518,7 +1523,7 @@ static bool isSpecialized(Node *node) {
}
}
NodePointer Remangler::getUnspecialized(Node *node) {
NodePointer Demangle::getUnspecialized(Node *node) {
switch (node->getKind()) {
case Node::Kind::Structure:
case Node::Kind::Enum:
@@ -1647,6 +1652,38 @@ void Remangler::mangleTypeList(Node *node) {
Out << '_';
}
void Remangler::mangleReflectionMetadataBuiltinDescriptor(Node *node) {
Out << "MRb";
}
void Remangler::mangleReflectionMetadataFieldDescriptor(Node *node) {
Out << "MRf";
}
void Remangler::mangleReflectionMetadataAssocTypeDescriptor(Node *node) {
Out << "MRa";
}
void Remangler::mangleReflectionMetadataSuperclassDescriptor(Node *node) {
Out << "MRc";
}
void Remangler::mangleCurryThunk(Node *node, EntityContext &ctx) {
Out << "<curry-thunk>";
}
void Remangler::mangleEmptyList(Node *node) {
Out << "<empty>";
}
void Remangler::mangleFirstElementMarker(Node *node) {
Out << "<first>";
}
void Remangler::mangleVariadicMarker(Node *node) {
Out << "<vararg>";
}
/// The top-level interface to the remangler.
std::string Demangle::mangleNode(const NodePointer &node) {
if (!node) return "";

1592
lib/Basic/Remangler.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -28,6 +28,7 @@
#include "swift/AST/DiagnosticsSema.h"
#include "swift/AST/IRGenOptions.h"
#include "swift/AST/Mangle.h"
#include "swift/AST/ASTMangler.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/ReferencedNameTracker.h"
#include "swift/AST/TypeRefinementContext.h"
@@ -1292,6 +1293,10 @@ int swift::performFrontend(ArrayRef<const char *> Args,
performCompile(Instance, Invocation, Args, ReturnValue, observer) ||
Instance.getASTContext().hadError();
if (!HadError) {
NewMangling::printManglingStats();
}
if (!HadError && !Invocation.getFrontendOptions().DumpAPIPath.empty()) {
HadError = dumpAPI(Instance.getMainModule(),
Invocation.getFrontendOptions().DumpAPIPath);

View File

@@ -32,6 +32,7 @@ add_swift_library(swiftIRGen STATIC
IRGen.cpp
IRGenDebugInfo.cpp
IRGenFunction.cpp
IRGenMangler.cpp
IRGenModule.cpp
IRGenSIL.cpp
Linking.cpp

View File

@@ -0,0 +1,35 @@
//===--- IRGenMangler.h - mangling of IRGen symbols -----------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "IRGenMangler.h"
using namespace swift;
using namespace irgen;
std::string IRGenMangler::mangleValueWitness(Type type, ValueWitness witness) {
beginMangling();
appendType(type);
const char *Code = nullptr;
switch (witness) {
#define VALUE_WITNESS(MANGLING, NAME) \
case ValueWitness::NAME: Code = #MANGLING; break;
#include "swift/Basic/ValueWitnessMangling.def"
case ValueWitness::Size:
case ValueWitness::Flags:
case ValueWitness::Stride:
case ValueWitness::ExtraInhabitantFlags:
llvm_unreachable("not a function witness");
}
appendOperator("w", Code);
return finalize();
}

183
lib/IRGen/IRGenMangler.h Normal file
View File

@@ -0,0 +1,183 @@
//===--- IRGenMangler.h - mangling of IRGen symbols -------------*- 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_IRGEN_IRGENMANGLER_H
#define SWIFT_IRGEN_IRGENMANGLER_H
#include "swift/AST/ASTMangler.h"
#include "ValueWitness.h"
namespace swift {
namespace irgen {
/// The mangler for all kind of symbols produced in IRGen.
class IRGenMangler : public NewMangling::ASTMangler {
public:
IRGenMangler() { }
std::string mangleValueWitness(Type type, ValueWitness witness);
std::string mangleValueWitnessTable(Type type) {
return mangleTypeSymbol(type, "WV");
}
std::string mangleTypeMetadataAccessFunction(Type type) {
return mangleTypeSymbol(type, "Ma");
}
std::string mangleTypeMetadataLazyCacheVariable(Type type) {
return mangleTypeSymbol(type, "ML");
}
std::string mangleTypeFullMetadataFull(Type type) {
return mangleTypeSymbol(type, "Mf");
}
std::string mangleTypeMetadataFull(Type type, bool isPattern) {
return mangleTypeSymbol(type, isPattern ? "MP" : "N");
}
std::string mangleClassMetaClass(const ClassDecl *Decl) {
return mangleNominalTypeSymbol(Decl, "Mm");
}
std::string mangleNominalTypeDescriptor(const NominalTypeDecl *Decl) {
return mangleNominalTypeSymbol(Decl, "Mn");
}
std::string mangleProtocolDescriptor(const ProtocolDecl *Decl) {
beginMangling();
appendProtocolName(Decl);
appendOperator("Mp");
return finalize();
}
std::string mangleWitnessTableOffset(const ValueDecl *Decl) {
beginMangling();
if (auto ctor = dyn_cast<ConstructorDecl>(Decl)) {
appendConstructorEntity(ctor, /*isAllocating=*/true);
} else {
appendEntity(Decl);
}
appendOperator("Wo");
return finalize();
}
std::string mangleFieldOffsetFull(const ValueDecl *Decl, bool isIndirect) {
beginMangling();
appendEntity(Decl);
appendOperator("Wv", isIndirect ? "i" : "d");
return finalize();
}
std::string mangleDirectProtocolWitnessTable(const ProtocolConformance *C) {
return mangleConformanceSymbol(Type(), C, "WP");
}
std::string mangleGenericProtocolWitnessTableCache(
const ProtocolConformance *C) {
return mangleConformanceSymbol(Type(), C, "WG");
}
std::string mangleGenericProtocolWitnessTableInstantiationFunction(
const ProtocolConformance *C) {
return mangleConformanceSymbol(Type(), C, "WI");
}
std::string mangleProtocolWitnessTableAccessFunction(
const ProtocolConformance *C) {
return mangleConformanceSymbol(Type(), C, "Wa");
}
std::string mangleProtocolWitnessTableLazyAccessFunction(Type type,
const ProtocolConformance *C) {
return mangleConformanceSymbol(type, C, "Wl");
}
std::string mangleProtocolWitnessTableLazyCacheVariable(Type type,
const ProtocolConformance *C) {
return mangleConformanceSymbol(type, C, "WL");
}
std::string mangleAssociatedTypeMetadataAccessFunction(
const ProtocolConformance *Conformance,
StringRef AssocTyName) {
beginMangling();
appendProtocolConformance(Conformance);
appendIdentifier(AssocTyName);
appendOperator("Wt");
return finalize();
}
std::string mangleAssociatedTypeWitnessTableAccessFunction(
const ProtocolConformance *Conformance,
StringRef AssocTyName,
const ProtocolDecl *Proto) {
beginMangling();
appendProtocolConformance(Conformance);
appendIdentifier(AssocTyName);
appendNominalType(Proto);
appendOperator("WT");
return finalize();
}
std::string mangleReflectionBuiltinDescriptor(Type type) {
return mangleTypeSymbol(type, "MB");
}
std::string mangleReflectionFieldDescriptor(Type type) {
return mangleTypeSymbol(type, "MF");
}
std::string mangleReflectionAssociatedTypeDescriptor(
const ProtocolConformance *C) {
return mangleConformanceSymbol(Type(), C, "MA");
}
std::string mangleReflectionSuperclassDescriptor(const ClassDecl *Decl) {
return mangleNominalTypeSymbol(Decl, "MC");
}
protected:
std::string mangleTypeSymbol(Type type, const char *Op) {
beginMangling();
appendType(type);
appendOperator(Op);
return finalize();
}
std::string mangleNominalTypeSymbol(const NominalTypeDecl *Decl,
const char *Op) {
beginMangling();
appendNominalType(Decl);
appendOperator(Op);
return finalize();
}
std::string mangleConformanceSymbol(Type type,
const ProtocolConformance *Conformance,
const char *Op) {
beginMangling();
if (type)
appendType(type);
appendProtocolConformance(Conformance);
appendOperator(Op);
return finalize();
}
};
} // end namespace irgen
} // end namespace swift
#endif

View File

@@ -12,5 +12,6 @@ set(UTILS_SOURCES
Utils/PerformanceInlinerUtils.cpp
Utils/SILInliner.cpp
Utils/SILSSAUpdater.cpp
Utils/SpecializationMangler.cpp
PARENT_SCOPE)

View File

@@ -0,0 +1,315 @@
//===--- SpecializationMangler.cpp - mangling of specializations ----------===//
//
// 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
//
//===----------------------------------------------------------------------===//
#include "swift/SILOptimizer/Utils/SpecializationMangler.h"
#include "swift/SIL/SILGlobalVariable.h"
#include "swift/Basic/Demangler.h"
#include "swift/Basic/ManglingMacros.h"
using namespace swift;
using namespace NewMangling;
void SpecializationMangler::beginMangling() {
ASTMangler::beginMangling();
if (Fragile)
ArgOpBuffer << 'q';
ArgOpBuffer << char(uint8_t(Pass) + '0');
}
std::string SpecializationMangler::finalize() {
std::string MangledSpecialization = ASTMangler::finalize();
Demangler D(MangledSpecialization);
NodePointer TopLevel = D.demangleTopLevel();
StringRef FuncName = Function->getName();
NodePointer FuncTopLevel;
if (FuncName.startswith(MANGLING_PREFIX_STR)) {
FuncTopLevel = Demangler(FuncName).demangleTopLevel();
assert(FuncTopLevel);
} else if (FuncName.startswith("_T")) {
FuncTopLevel = demangleSymbolAsNode(FuncName.data(), FuncName.size());
}
if (!FuncTopLevel) {
FuncTopLevel = NodeFactory::create(Node::Kind::Global);
FuncTopLevel->addChild(NodeFactory::create(Node::Kind::Identifier, FuncName));
}
for (NodePointer FuncChild : *FuncTopLevel) {
assert(FuncChild->getKind() != Node::Kind::Suffix ||
FuncChild->getText() == "merged");
TopLevel->addChild(FuncChild);
}
return Demangle::mangleNodeNew(TopLevel);
}
//===----------------------------------------------------------------------===//
// Generic Specialization
//===----------------------------------------------------------------------===//
std::string GenericSpecializationMangler::mangle() {
beginMangling();
SILFunctionType *FTy = Function->getLoweredFunctionType();
CanGenericSignature Sig = FTy->getGenericSignature();
unsigned idx = 0;
bool First = true;
for (Type DepType : Sig->getAllDependentTypes()) {
// It is sufficient to only mangle the substitutions of the "primary"
// dependent types. As all other dependent types are just derived from the
// primary types, this will give us unique symbol names.
if (DepType->is<GenericTypeParamType>()) {
appendType(Subs[idx].getReplacement()->getCanonicalType());
appendListSeparator(First);
}
++idx;
}
assert(idx == Subs.size() && "subs not parallel to dependent types");
assert(!First && "no generic substitutions");
appendSpecializationOperator(isReAbstracted ? "Tg" : "TG");
return finalize();
}
//===----------------------------------------------------------------------===//
// Function Signature Optimizations
//===----------------------------------------------------------------------===//
FunctionSignatureSpecializationMangler::
FunctionSignatureSpecializationMangler(SpecializationPass P,
IsFragile_t Fragile, SILFunction *F)
: SpecializationMangler(P, Fragile, F) {
for (unsigned i = 0, e = F->getLoweredFunctionType()->getNumSILArguments();
i != e; ++i) {
(void)i;
Args.push_back({ArgumentModifierIntBase(ArgumentModifier::Unmodified),
nullptr});
}
ReturnValue = ReturnValueModifierIntBase(ReturnValueModifier::Unmodified);
}
void
FunctionSignatureSpecializationMangler::
setArgumentDead(unsigned ArgNo) {
Args[ArgNo].first |= ArgumentModifierIntBase(ArgumentModifier::Dead);
}
void
FunctionSignatureSpecializationMangler::
setArgumentClosureProp(unsigned ArgNo, PartialApplyInst *PAI) {
auto &Info = Args[ArgNo];
Info.first = ArgumentModifierIntBase(ArgumentModifier::ClosureProp);
Info.second = PAI;
}
void
FunctionSignatureSpecializationMangler::
setArgumentClosureProp(unsigned ArgNo, ThinToThickFunctionInst *TTTFI) {
auto &Info = Args[ArgNo];
Info.first = ArgumentModifierIntBase(ArgumentModifier::ClosureProp);
Info.second = TTTFI;
}
void
FunctionSignatureSpecializationMangler::
setArgumentConstantProp(unsigned ArgNo, LiteralInst *LI) {
auto &Info = Args[ArgNo];
Info.first = ArgumentModifierIntBase(ArgumentModifier::ConstantProp);
Info.second = LI;
}
void
FunctionSignatureSpecializationMangler::
setArgumentOwnedToGuaranteed(unsigned ArgNo) {
Args[ArgNo].first |= ArgumentModifierIntBase(ArgumentModifier::OwnedToGuaranteed);
}
void
FunctionSignatureSpecializationMangler::
setArgumentSROA(unsigned ArgNo) {
Args[ArgNo].first |= ArgumentModifierIntBase(ArgumentModifier::SROA);
}
void
FunctionSignatureSpecializationMangler::
setArgumentBoxToValue(unsigned ArgNo) {
Args[ArgNo].first = ArgumentModifierIntBase(ArgumentModifier::BoxToValue);
}
void
FunctionSignatureSpecializationMangler::
setArgumentBoxToStack(unsigned ArgNo) {
Args[ArgNo].first = ArgumentModifierIntBase(ArgumentModifier::BoxToStack);
}
void
FunctionSignatureSpecializationMangler::
setReturnValueOwnedToUnowned() {
ReturnValue |= ReturnValueModifierIntBase(ReturnValueModifier::OwnedToUnowned);
}
void
FunctionSignatureSpecializationMangler::mangleConstantProp(LiteralInst *LI) {
// Append the prefix for constant propagation 'p'.
ArgOpBuffer << 'p';
// Then append the unique identifier of our literal.
switch (LI->getKind()) {
default:
llvm_unreachable("unknown literal");
case ValueKind::FunctionRefInst: {
SILFunction *F = cast<FunctionRefInst>(LI)->getReferencedFunction();
ArgOpBuffer << 'f';
appendIdentifier(F->getName());
break;
}
case ValueKind::GlobalAddrInst: {
SILGlobalVariable *G = cast<GlobalAddrInst>(LI)->getReferencedGlobal();
ArgOpBuffer << 'g';
appendIdentifier(G->getName());
break;
}
case ValueKind::IntegerLiteralInst: {
APInt apint = cast<IntegerLiteralInst>(LI)->getValue();
ArgOpBuffer << 'i' << apint;
break;
}
case ValueKind::FloatLiteralInst: {
APInt apint = cast<FloatLiteralInst>(LI)->getBits();
ArgOpBuffer << 'd' << apint;
break;
}
case ValueKind::StringLiteralInst: {
StringLiteralInst *SLI = cast<StringLiteralInst>(LI);
StringRef V = SLI->getValue();
assert(V.size() <= 32 && "Cannot encode string of length > 32");
std::string VBuffer;
if (V.size() > 0 && (isDigit(V[0]) || V[0] == '_')) {
VBuffer = "_";
VBuffer.append(V.data(), V.size());
V = VBuffer;
}
appendIdentifier(V);
ArgOpBuffer << 's';
switch (SLI->getEncoding()) {
case StringLiteralInst::Encoding::UTF8: ArgOpBuffer << 'b'; break;
case StringLiteralInst::Encoding::UTF16: ArgOpBuffer << 'w'; break;
case StringLiteralInst::Encoding::ObjCSelector: ArgOpBuffer << 'c'; break;
}
break;
}
}
}
void
FunctionSignatureSpecializationMangler::mangleClosureProp(SILInstruction *Inst) {
ArgOpBuffer << 'c';
// Add in the partial applies function name if we can find one. Assert
// otherwise. The reason why this is ok to do is currently we only perform
// closure specialization if we know the function_ref in question. When this
// restriction is removed, the assert here will fire.
if (auto *TTTFI = dyn_cast<ThinToThickFunctionInst>(Inst)) {
auto *FRI = cast<FunctionRefInst>(TTTFI->getCallee());
appendIdentifier(FRI->getReferencedFunction()->getName());
return;
}
auto *PAI = cast<PartialApplyInst>(Inst);
auto *FRI = cast<FunctionRefInst>(PAI->getCallee());
appendIdentifier(FRI->getReferencedFunction()->getName());
// Then we mangle the types of the arguments that the partial apply is
// specializing.
for (auto &Op : PAI->getArgumentOperands()) {
SILType Ty = Op.get()->getType();
appendType(Ty.getSwiftRValueType());
}
}
void FunctionSignatureSpecializationMangler::mangleArgument(
ArgumentModifierIntBase ArgMod, NullablePtr<SILInstruction> Inst) {
if (ArgMod == ArgumentModifierIntBase(ArgumentModifier::ConstantProp)) {
mangleConstantProp(cast<LiteralInst>(Inst.get()));
return;
}
if (ArgMod == ArgumentModifierIntBase(ArgumentModifier::ClosureProp)) {
mangleClosureProp(Inst.get());
return;
}
if (ArgMod == ArgumentModifierIntBase(ArgumentModifier::Unmodified)) {
ArgOpBuffer << 'n';
return;
}
if (ArgMod == ArgumentModifierIntBase(ArgumentModifier::BoxToValue)) {
ArgOpBuffer << 'i';
return;
}
if (ArgMod == ArgumentModifierIntBase(ArgumentModifier::BoxToStack)) {
ArgOpBuffer << 's';
return;
}
bool hasSomeMod = false;
if (ArgMod & ArgumentModifierIntBase(ArgumentModifier::Dead)) {
ArgOpBuffer << 'd';
hasSomeMod = true;
}
if (ArgMod & ArgumentModifierIntBase(ArgumentModifier::OwnedToGuaranteed)) {
ArgOpBuffer << (hasSomeMod ? 'G' : 'g');
hasSomeMod = true;
}
if (ArgMod & ArgumentModifierIntBase(ArgumentModifier::SROA)) {
ArgOpBuffer << (hasSomeMod ? 'X' : 'x');
hasSomeMod = true;
}
assert(hasSomeMod && "Unknown modifier");
}
void FunctionSignatureSpecializationMangler::
mangleReturnValue(ReturnValueModifierIntBase RetMod) {
if (RetMod == ReturnValueModifierIntBase(ReturnValueModifier::Unmodified)) {
ArgOpBuffer << 'n';
return;
}
bool hasSomeMode = false;
if (RetMod & ReturnValueModifierIntBase(ReturnValueModifier::Dead)) {
ArgOpBuffer << 'd';
hasSomeMode = true;
}
if (RetMod & ReturnValueModifierIntBase(ReturnValueModifier::OwnedToUnowned)) {
ArgOpBuffer << (hasSomeMode ? 'G' : 'g');
}
}
std::string FunctionSignatureSpecializationMangler::mangle() {
beginMangling();
for (unsigned i : indices(Args)) {
ArgumentModifierIntBase ArgMod;
NullablePtr<SILInstruction> Inst;
std::tie(ArgMod, Inst) = Args[i];
mangleArgument(ArgMod, Inst);
}
ArgOpBuffer << '_';
mangleReturnValue(ReturnValue);
appendSpecializationOperator("Tf");
return finalize();
}