Files
swift-mirror/lib/AST/Mangle.cpp
Joe Groff 8adaab0233 Fold ExtInfo::isThin and ::isBlock into a "Representation" enum.
These bits are orthogonal to each other, so combine them into one, and diagnose attempts to produce a type that's both. Spot-fix a bunch of places this revealed by inspection that we would have crashed in SILGen or IRGen if blocks were be handled.

Swift SVN r16088
2014-04-09 00:37:26 +00:00

1313 lines
44 KiB
C++

//===--- Mangle.cpp - Swift Name Mangling --------------------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2015 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
//
//===----------------------------------------------------------------------===//
//
// This file implements declaration name mangling in Swift.
//
//===----------------------------------------------------------------------===//
#include "swift/AST/Mangle.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/Attr.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/Module.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/Basic/Punycode.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/SaveAndRestore.h"
#include "llvm/Support/raw_ostream.h"
using namespace swift;
using namespace Mangle;
/// Translate the given operator character into its mangled form.
///
/// Current operator characters: @/=-+*%<>!&|^~ and the special operator '..'
static char mangleOperatorChar(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 '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;
}
}
namespace {
/// A helpful little wrapper for a value that should be mangled
/// in a particular, compressed value.
class Index {
unsigned N;
public:
explicit Index(unsigned n) : N(n) {}
friend raw_ostream &operator<<(raw_ostream &out, Index n) {
if (n.N != 0) out << (n.N - 1);
return (out << '_');
}
};
}
static bool isNonAscii(StringRef str) {
for (unsigned char c : str) {
if (c >= 0x80)
return true;
}
return false;
}
/// Mangle an identifier into the buffer.
void Mangler::mangleIdentifier(Identifier ident, OperatorFixity fixity) {
StringRef str = ident.str();
assert(!str.empty() && "mangling an empty identifier!");
// If the identifier contains non-ASCII character, we mangle with an initial
// X and Punycode the identifier string.
llvm::SmallString<32> punycodeBuf;
if (isNonAscii(str)) {
Buffer << 'X';
Punycode::encodePunycode(str, punycodeBuf);
str = punycodeBuf;
}
// Mangle normal identifiers as
// count identifier-char+
// where the count is the number of characters in the identifier,
// and where individual identifier characters represent themselves.
if (!ident.isOperator()) {
Buffer << str.size() << str;
return;
}
// Mangle operator identifiers as
// operator ::= 'o' operator-fixity count operator-char+
// operator-fixity ::= 'p' // prefix
// operator-fixity ::= 'P' // postfix
// operator-fixity ::= 'i' // infix
// where the count is the number of characters in the operator,
// and where the individual operator characters are translated.
Buffer << 'o';
switch (fixity) {
case OperatorFixity::NotOperator:
llvm_unreachable("operator mangled without fixity specified!");
case OperatorFixity::Infix:
Buffer << 'i';
break;
case OperatorFixity::Prefix:
Buffer << 'p';
break;
case OperatorFixity::Postfix:
Buffer << 'P';
break;
}
// Mangle ASCII operators directly.
Buffer << str.size();
for (char c : str) {
Buffer << mangleOperatorChar(c);
}
}
bool Mangler::tryMangleSubstitution(void *ptr) {
auto ir = Substitutions.find(ptr);
if (ir == Substitutions.end()) return false;
// substitution ::= 'S' integer? '_'
unsigned index = ir->second;
Buffer << 'S';
if (index) Buffer << (index - 1);
Buffer << '_';
return true;
}
void Mangler::addSubstitution(void *ptr) {
Substitutions.insert(std::make_pair(ptr, Substitutions.size()));
}
/// Mangle the context of the given declaration as a <context.
/// This is the top-level entrypoint for mangling <context>.
void Mangler::mangleContextOf(ValueDecl *decl, BindGenerics shouldBind) {
auto clangDecl = decl->getClangDecl();
// Classes and protocols published to Objective-C have a special context
// mangling.
// known-context ::= 'So'
if (isa<ClassDecl>(decl) &&
(clangDecl ||
(decl->isObjC() &&
!decl->getASTContext().LangOpts.MangleObjCClassProtocolNames))) {
assert(!clangDecl || isa<clang::ObjCInterfaceDecl>(clangDecl));
Buffer << "So";
return;
}
if (isa<ProtocolDecl>(decl) &&
(clangDecl ||
(decl->isObjC() &&
!decl->getASTContext().LangOpts.MangleObjCClassProtocolNames))) {
assert(!clangDecl || isa<clang::ObjCProtocolDecl>(clangDecl));
Buffer << "So";
return;
}
// Declarations provided by a C module have a special context mangling.
// known-context ::= 'SC'
// Do a dance to avoid a layering dependency.
if (auto file = dyn_cast<FileUnit>(decl->getDeclContext())) {
if (file->getKind() == FileUnitKind::ClangModule) {
Buffer << "SC";
return;
}
}
// Just mangle the decl's DC.
mangleContext(decl->getDeclContext(), shouldBind);
}
namespace {
class FindFirstVariable :
public PatternVisitor<FindFirstVariable, VarDecl *> {
public:
VarDecl *visitNamedPattern(NamedPattern *P) {
return P->getDecl();
}
VarDecl *visitTuplePattern(TuplePattern *P) {
for (auto &elt : P->getFields()) {
VarDecl *var = visit(elt.getPattern());
if (var) return var;
}
return nullptr;
}
VarDecl *visitParenPattern(ParenPattern *P) {
return visit(P->getSubPattern());
}
VarDecl *visitVarPattern(VarPattern *P) {
return visit(P->getSubPattern());
}
VarDecl *visitTypedPattern(TypedPattern *P) {
return visit(P->getSubPattern());
}
VarDecl *visitAnyPattern(AnyPattern *P) {
return nullptr;
}
// Refutable patterns shouldn't ever come up.
#define REFUTABLE_PATTERN(ID, BASE) \
VarDecl *visit##ID##Pattern(ID##Pattern *P) { \
llvm_unreachable("shouldn't be visiting a refutable pattern here!"); \
}
#define PATTERN(ID, BASE)
#include "swift/AST/PatternNodes.def"
};
}
/// Find the first identifier bound by the given binding. This
/// assumes that field and global-variable bindings always bind at
/// least one name, which is probably a reasonable assumption but may
/// not be adequately enforced.
static VarDecl *findFirstVariable(PatternBindingDecl *binding) {
auto var = FindFirstVariable().visit(binding->getPattern());
assert(var && "pattern-binding bound no variables?");
return var;
}
void Mangler::mangleContext(DeclContext *ctx, BindGenerics shouldBind) {
switch (ctx->getContextKind()) {
case DeclContextKind::Module:
return mangleModule(cast<Module>(ctx));
case DeclContextKind::FileUnit:
assert(!isa<BuiltinUnit>(ctx) && "mangling member of builtin module!");
mangleContext(ctx->getParent(), shouldBind);
return;
case DeclContextKind::NominalTypeDecl:
mangleNominalType(cast<NominalTypeDecl>(ctx), ResilienceExpansion::Minimal,
shouldBind);
return;
case DeclContextKind::ExtensionDecl: {
auto ExtD = cast<ExtensionDecl>(ctx);
auto ExtTy = ExtD->getExtendedType();
// Recover from erroneous extension.
if (ExtTy->is<ErrorType>())
return mangleContext(ExtD->getDeclContext(), shouldBind);
auto decl = ExtTy->getAnyNominal();
assert(decl && "extension of non-nominal type?");
mangleNominalType(decl, ResilienceExpansion::Minimal, shouldBind);
return;
}
case DeclContextKind::AbstractClosureExpr:
return mangleClosureEntity(cast<AbstractClosureExpr>(ctx),
ResilienceExpansion::Minimal, /*uncurry*/ 0);
case DeclContextKind::AbstractFunctionDecl: {
auto fn = cast<AbstractFunctionDecl>(ctx);
// Constructors and destructors as contexts are always mangled
// using the non-(de)allocating variants.
if (auto ctor = dyn_cast<ConstructorDecl>(fn)) {
return mangleConstructorEntity(ctor, /*allocating*/ false,
ResilienceExpansion::Minimal,
/*uncurry*/ 0);
}
if (auto dtor = dyn_cast<DestructorDecl>(fn))
return mangleDestructorEntity(dtor, /*deallocating*/ false);
return mangleEntity(fn, ResilienceExpansion::Minimal, /*uncurry*/ 0);
}
case DeclContextKind::Initializer:
switch (cast<Initializer>(ctx)->getInitializerKind()) {
case InitializerKind::DefaultArgument: {
auto argInit = cast<DefaultArgumentInitializer>(ctx);
mangleDefaultArgumentEntity(ctx->getParent(),
argInit->getIndex());
return;
}
case InitializerKind::PatternBinding: {
auto patternInit = cast<PatternBindingInitializer>(ctx);
auto var = findFirstVariable(patternInit->getBinding());
mangleInitializerEntity(var);
return;
}
}
llvm_unreachable("bad initializer kind");
case DeclContextKind::TopLevelCodeDecl:
// Mangle the containing module context.
return mangleContext(ctx->getParent(), shouldBind);
}
llvm_unreachable("bad decl context");
}
void Mangler::mangleModule(Module *module) {
assert(!module->getParent() && "cannot mangle nested modules!");
// Try the special 'swift' substitution.
// context ::= known-module
// known-module ::= 'Ss'
if (module->isStdlibModule()) {
Buffer << "Ss";
return;
}
// context ::= substitution
if (tryMangleSubstitution(module)) return;
// context ::= identifier
mangleIdentifier(module->Name);
addSubstitution(module);
}
/// Bind the generic parameters from the given list and its parents.
///
/// \param mangle if true, also emit the mangling for a 'generics'
void Mangler::bindGenericParameters(const GenericParamList *genericParams,
bool mangle = false) {
assert(genericParams);
SmallVector<const GenericParamList *, 2> paramLists;
// Determine the depth our parameter list is at. We don't actually need to
// emit the outer parameters because they should have been emitted as part of
// the outer context.
assert(ArchetypesDepth == genericParams->getDepth());
ArchetypesDepth++;
unsigned index = 0;
for (auto archetype : genericParams->getPrimaryArchetypes()) {
// Remember the current depth and level.
ArchetypeInfo info;
info.Depth = ArchetypesDepth;
info.Index = index++;
assert(!Archetypes.count(archetype) ||
(Archetypes[archetype].Depth == info.Depth &&
Archetypes[archetype].Index == info.Index));
Archetypes.insert(std::make_pair(archetype, info));
if (!mangle) continue;
// Mangle this type parameter.
// <generic-parameter> ::= <protocol-list> _
// FIXME: Only mangle the archetypes and protocol requirements
// that matter, rather than everything.
mangleProtocolList(archetype->getConformsTo());
Buffer << '_';
}
if (!mangle)
return;
auto assocTypes = genericParams->getAssociatedArchetypes();
if (!assocTypes.empty()) {
// Mangle the associated types.
Buffer << 'U';
for (auto *assocType : assocTypes) {
mangleProtocolList(assocType->getConformsTo());
Buffer << '_';
}
}
Buffer << '_';
}
void Mangler::manglePolymorphicType(const GenericParamList *genericParams,
CanType T, ResilienceExpansion explosion,
unsigned uncurryLevel,
bool mangleAsFunction) {
// FIXME: Prefix?
bindGenericParameters(genericParams, /*mangle*/ true);
if (mangleAsFunction)
mangleFunctionType(cast<AnyFunctionType>(T), explosion, uncurryLevel);
else
mangleType(T, explosion, uncurryLevel);
}
static OperatorFixity getDeclFixity(ValueDecl *decl) {
if (!decl->getName().isOperator())
return OperatorFixity::NotOperator;
if (decl->getAttrs().isPostfix())
return OperatorFixity::Postfix;
if (decl->getAttrs().isPrefix())
return OperatorFixity::Prefix;
return OperatorFixity::Infix;
}
void Mangler::mangleDeclName(ValueDecl *decl) {
// decl-name ::= 'L' index identifier
if (decl->getDeclContext()->isLocalContext()) {
Buffer << 'L' << Index(decl->getLocalDiscriminator());
// Fall through to mangle the <identiifier>.
}
// decl-name ::= identifier
mangleIdentifier(decl->getName(), getDeclFixity(decl));
}
static void bindAllGenericParameters(Mangler &mangler,
GenericParamList *generics) {
if (!generics) return;
bindAllGenericParameters(mangler, generics->getOuterParameters());
mangler.bindGenericParameters(generics, /*mangle*/ false);
}
void Mangler::mangleTypeForDebugger(Type Ty, DeclContext *DC) {
assert(DWARFMangling);
if (auto NameAliasTy = dyn_cast<NameAliasType>(Ty.getPointer())) {
TypeAliasDecl *decl = NameAliasTy->getDecl();
assert(decl);
if (decl->getModuleContext() == decl->getASTContext().TheBuiltinModule) {
// It's not possible to mangle the context of the builtin module.
Buffer << decl->getName().str();
} else {
// For the DWARF output we want to mangle the type alias + context,
// unless the type alias references a builtin type.
assert(decl->getModuleContext() !=
decl->getASTContext().TheBuiltinModule);
ContextStack context(*this);
Buffer << "_Tta";
mangleContextOf(decl, BindGenerics::None);
mangleIdentifier(decl->getName());
}
return;
}
Buffer << "_Tt";
// Move up to the innermost generic context.
while (DC && !DC->isInnermostContextGeneric()) DC = DC->getParent();
if (DC) bindAllGenericParameters(*this, DC->getGenericParamsOfContext());
DeclCtx = DC;
mangleType(Ty->getCanonicalType(), ResilienceExpansion::Minimal, /*uncurry*/ 0);
}
void Mangler::mangleDeclTypeForDebugger(ValueDecl *decl) {
assert(DWARFMangling);
Buffer << "_Tt";
typedef std::pair<bool, BindGenerics> result_t;
struct ClassifyDecl : swift::DeclVisitor<ClassifyDecl, result_t> {
/// TypeAliasDecls need to be mangled.
result_t visitTypeAliasDecl(TypeDecl *D) {
llvm_unreachable("filtered out above");
}
/// Other TypeDecls don't need their types mangled in.
result_t visitTypeDecl(TypeDecl *D) {
return { false, BindGenerics::None };
}
/// Function-like declarations do, but they should have
/// polymorphic type and therefore don't need specific binding.
result_t visitFuncDecl(FuncDecl *D) {
if (D->getDeclContext()->isTypeContext())
return { true, BindGenerics::Enclosing };
else
return { true, BindGenerics::All };
}
result_t visitConstructorDecl(ConstructorDecl *D) {
return { true, BindGenerics::Enclosing };
}
result_t visitDestructorDecl(DestructorDecl *D) {
return { true, BindGenerics::Enclosing };
}
result_t visitEnumElementDecl(EnumElementDecl *D) {
return { true, BindGenerics::Enclosing };
}
/// All other values need to have contextual archetypes bound.
result_t visitVarDecl(VarDecl *D) {
return { true, BindGenerics::All };
}
result_t visitSubscriptDecl(SubscriptDecl *D) {
return { true, BindGenerics::All };
}
/// Make sure we have a case for every ValueDecl.
result_t visitValueDecl(ValueDecl *D) = delete;
/// Everything else should be unreachable here.
result_t visitDecl(Decl *D) {
llvm_unreachable("not a ValueDecl");
}
};
auto result = ClassifyDecl().visit(decl);
if (!result.first) return;
// Find the innermost generic context and stash it in DeclCtx.
// Also track whether DC is just a type ancestor of the decl.
DeclContext *DC = decl->getDeclContext();
bool isNonTypeDC = false;
while (DC && !DC->isInnermostContextGeneric()) {
if (!isNonTypeDC) isNonTypeDC = !DC->isTypeContext();
DC = DC->getParent();
}
DeclCtx = DC;
// Bind the generic parameters from that.
if (DC) {
// But if the generics come from a type container, they may be
// accounted for in the decl's type; skip them if so.
if (result.second == BindGenerics::Enclosing && !isNonTypeDC) {
while (DC->isTypeContext())
DC = DC->getParent();
}
bindAllGenericParameters(*this, DC->getGenericParamsOfContext());
}
mangleDeclType(decl, ResilienceExpansion::Minimal, /*uncurry*/ 0);
}
void Mangler::mangleDeclType(ValueDecl *decl, ResilienceExpansion explosion,
unsigned uncurryLevel) {
auto type = decl->getType();
mangleType(type->getCanonicalType(), explosion, uncurryLevel);
}
void Mangler::mangleGenericSignature(GenericSignature *sig,
ResilienceExpansion expansion) {
// Mangle the number of parameters.
unsigned depth = 0;
unsigned count = 0;
for (auto param : sig->getGenericParams()) {
if (param->getDepth() != depth) {
assert(param->getDepth() > depth && "generic params not ordered");
while (depth++ < param->getDepth()) {
Buffer << Index(count);
count = 0;
}
}
assert(param->getIndex() == count && "generic params not ordered");
++count;
}
Buffer << Index(count);
Buffer << 'R';
// Mangle the requirements.
for (auto &reqt : sig->getRequirements()) {
switch (reqt.getKind()) {
case RequirementKind::WitnessMarker:
// TODO: Do we need to mangle this?
break;
case RequirementKind::Conformance:
Buffer << 'P';
mangleType(reqt.getFirstType()->getCanonicalType(), expansion, 0);
mangleType(reqt.getSecondType()->getCanonicalType(), expansion, 0);
break;
case RequirementKind::SameType:
Buffer << 'E';
mangleType(reqt.getFirstType()->getCanonicalType(), expansion, 0);
mangleType(reqt.getSecondType()->getCanonicalType(), expansion, 0);
break;
}
}
Buffer << '_';
}
/// Mangle a type into the buffer.
///
/// Type manglings should never start with [0-9d_] or end with [0-9].
///
/// <type> ::= A <natural> <type> # fixed-sized arrays
/// <type> ::= Bf <natural> _ # Builtin.Float
/// <type> ::= Bi <natural> _ # Builtin.Integer
/// <type> ::= BO # Builtin.ObjCPointer
/// <type> ::= Bo # Builtin.ObjectPointer
/// <type> ::= Bp # Builtin.RawPointer
/// <type> ::= Bv <natural> <type> # Builtin.Vector
/// <type> ::= C <decl> # class (substitutable)
/// <type> ::= D <type> # dynamic Self return
/// <type> ::= ERR # Error type
/// <type> ::= 'a' <context> <identifier> # Type alias (DWARF only)
/// <type> ::= F <type> <type> # function type
/// <type> ::= f <type> <type> # uncurried function type
/// <type> ::= G <type> <type>+ _ # bound generic type
/// <type> ::= O <decl> # enum (substitutable)
/// <type> ::= M <type> # metatype
/// <type> ::= P <protocol-list> _ # protocol composition
/// <type> ::= PM <type> # existential metatype
/// <type> ::= Q <index> # archetype with depth=0, index=N
/// <type> ::= Qd <index> <index> # archetype with depth=M+1, index=N
/// <type> ::= 'Qq' index context # archetype+context (DWARF only)
///
/// <type> ::= R <type> # inout
/// <type> ::= T <tuple-element>* _ # tuple
/// <type> ::= U <generic-parameter>+ _ <type>
/// <type> ::= V <decl> # struct (substitutable)
/// <type> ::= Xo <type> # unowned reference type
/// <type> ::= Xw <type> # weak reference type
/// <type> ::= XF <impl-function-type> # SIL function type
///
/// <index> ::= _ # 0
/// <index> ::= <natural> _ # N+1
///
/// <tuple-element> ::= <identifier>? <type>
void Mangler::mangleType(CanType type, ResilienceExpansion explosion,
unsigned uncurryLevel) {
switch (type->getKind()) {
case TypeKind::TypeVariable:
llvm_unreachable("mangling type variable");
case TypeKind::Module:
llvm_unreachable("Cannot mangle module type yet");
case TypeKind::Error:
Buffer << "ERR";
return;
// We don't care about these types being a bit verbose because we
// don't expect them to come up that often in API names.
case TypeKind::BuiltinFloat:
switch (cast<BuiltinFloatType>(type)->getFPKind()) {
case BuiltinFloatType::IEEE16: Buffer << "Bf16_"; return;
case BuiltinFloatType::IEEE32: Buffer << "Bf32_"; return;
case BuiltinFloatType::IEEE64: Buffer << "Bf64_"; return;
case BuiltinFloatType::IEEE80: Buffer << "Bf80_"; return;
case BuiltinFloatType::IEEE128: Buffer << "Bf128_"; return;
case BuiltinFloatType::PPC128: llvm_unreachable("ppc128 not supported");
}
llvm_unreachable("bad floating-point kind");
case TypeKind::BuiltinInteger: {
auto width = cast<BuiltinIntegerType>(type)->getWidth();
if (width.isFixedWidth())
Buffer << "Bi" << width.getFixedWidth() << '_';
else if (width.isPointerWidth())
Buffer << "Bw";
else
llvm_unreachable("impossible width value");
return;
}
case TypeKind::BuiltinRawPointer:
Buffer << "Bp";
return;
case TypeKind::BuiltinObjectPointer:
Buffer << "Bo";
return;
case TypeKind::BuiltinObjCPointer:
Buffer << "BO";
return;
case TypeKind::BuiltinVector:
Buffer << "Bv" << cast<BuiltinVectorType>(type)->getNumElements();
mangleType(cast<BuiltinVectorType>(type).getElementType(), explosion,
uncurryLevel);
return;
#define SUGARED_TYPE(id, parent) \
case TypeKind::id: \
llvm_unreachable("expect canonical type");
#define TYPE(id, parent)
#include "swift/AST/TypeNodes.def"
case TypeKind::ExistentialMetatype:
Buffer << 'P' << 'M';
return mangleType(cast<ExistentialMetatypeType>(type).getInstanceType(),
ResilienceExpansion::Minimal, 0);
case TypeKind::Metatype:
Buffer << 'M';
return mangleType(cast<MetatypeType>(type).getInstanceType(),
ResilienceExpansion::Minimal, 0);
case TypeKind::LValue:
assert(0 && "@lvalue types should not occur in function interfaces");
case TypeKind::InOut:
Buffer << 'R';
return mangleType(cast<InOutType>(type).getObjectType(),
ResilienceExpansion::Minimal, 0);
case TypeKind::UnownedStorage:
Buffer << "Xo";
return mangleType(cast<UnownedStorageType>(type).getReferentType(),
ResilienceExpansion::Minimal, 0);
case TypeKind::WeakStorage:
Buffer << "Xw";
return mangleType(cast<WeakStorageType>(type).getReferentType(),
ResilienceExpansion::Minimal, 0);
case TypeKind::Tuple: {
auto tuple = cast<TupleType>(type);
// type ::= 'T' tuple-field+ '_' // tuple
// type ::= 't' tuple-field+ '_' // variadic tuple
// tuple-field ::= identifier? type
if (tuple->getFields().size() > 0
&& tuple->getFields().back().isVararg())
Buffer << 't';
else
Buffer << 'T';
for (auto &field : tuple->getFields()) {
if (field.hasName())
mangleIdentifier(field.getName());
mangleType(CanType(field.getType()), explosion, 0);
}
Buffer << '_';
return;
}
case TypeKind::Protocol:
// Protocol type manglings have a variable number of protocol names
// follow the 'P' sigil, so a trailing underscore is needed after the
// type name, unlike protocols as contexts.
Buffer << 'P';
mangleProtocolList(type);
Buffer << '_';
return;
case TypeKind::UnboundGeneric: {
// We normally reject unbound types in IR-generation, but there
// are several occasions in which we'd like to mangle them in the
// abstract.
ContextStack context(*this);
mangleNominalType(cast<UnboundGenericType>(type)->getDecl(), explosion,
BindGenerics::None);
return;
}
case TypeKind::Class:
case TypeKind::Enum:
case TypeKind::Struct: {
ContextStack context(*this);
return mangleNominalType(cast<NominalType>(type)->getDecl(), explosion,
BindGenerics::None);
}
case TypeKind::BoundGenericClass:
case TypeKind::BoundGenericEnum:
case TypeKind::BoundGenericStruct: {
// type ::= 'G' <type> <type>+ '_'
auto boundType = cast<BoundGenericType>(type);
Buffer << 'G';
{
ContextStack context(*this);
mangleNominalType(boundType->getDecl(), explosion, BindGenerics::None);
}
for (auto arg : boundType.getGenericArgs()) {
mangleType(arg, ResilienceExpansion::Minimal, /*uncurry*/ 0);
}
Buffer << '_';
return;
}
case TypeKind::PolymorphicFunction: {
// <type> ::= U <generic-parameter>+ _ <type>
// 'U' is for "universal qualification".
// The nested type is always a function type.
auto fn = cast<PolymorphicFunctionType>(type);
Buffer << 'U';
manglePolymorphicType(&fn->getGenericParams(), fn, explosion, uncurryLevel,
/*mangleAsFunction=*/true);
return;
}
case TypeKind::SILFunction: {
// <type> ::= 'XF' <impl-function-type>
// <impl-function-type> ::= <impl-callee-convention>
// <impl-function-attribute>* <generics>? '_'
// <impl-parameter>* '_' <impl-result>* '_'
// <impl-callee-convention> ::= 't' // thin
// <impl-callee-convention> ::= <impl-convention> // thick
// <impl-convention> ::= 'a' // direct, autoreleased
// <impl-convention> ::= 'd' // direct, no ownership transfer
// <impl-convention> ::= 'g' // direct, guaranteed
// <impl-convention> ::= 'i' // indirect, ownership transfer
// <impl-convention> ::= 'l' // indirect, inout
// <impl-convention> ::= 'o' // direct, ownership transfer
// <impl-function-attribute> ::= 'Cb' // block invocation function
// <impl-function-attribute> ::= 'Cc' // C global function
// <impl-function-attribute> ::= 'Cm' // Swift method
// <impl-function-attribute> ::= 'CO' // ObjC method
// <impl-function-attribute> ::= 'N' // noreturn
// <impl-function-attribute> ::= 'G' // generic
// <impl-parameter> ::= <impl-convention> <type>
// <impl-result> ::= <impl-convention> <type>
auto fn = cast<SILFunctionType>(type);
Buffer << "XF";
auto mangleParameterConvention = [](ParameterConvention conv) {
// @in and @out are mangled the same because they're put in
// different places.
switch (conv) {
case ParameterConvention::Indirect_In: return 'i';
case ParameterConvention::Indirect_Out: return 'i';
case ParameterConvention::Indirect_Inout: return 'l';
case ParameterConvention::Direct_Owned: return 'o';
case ParameterConvention::Direct_Unowned: return 'd';
case ParameterConvention::Direct_Guaranteed: return 'g';
}
llvm_unreachable("bad parameter convention");
};
auto mangleResultConvention = [](ResultConvention conv) {
switch (conv) {
case ResultConvention::Owned: return 'o';
case ResultConvention::Unowned: return 'd';
case ResultConvention::Autoreleased: return 'a';
}
llvm_unreachable("bad result convention");
};
// <impl-callee-convention>
if (fn->getRepresentation() == AnyFunctionType::Representation::Thin) {
Buffer << 't';
} else {
Buffer << mangleParameterConvention(fn->getCalleeConvention());
}
// <impl-function-attribute>*
if (fn->getRepresentation() == AnyFunctionType::Representation::Block) {
Buffer << "Cb";
} else {
switch (fn->getAbstractCC()) {
case AbstractCC::Freestanding: break;
case AbstractCC::C: Buffer << "Cc"; break;
case AbstractCC::ObjCMethod: Buffer << "CO"; break;
case AbstractCC::Method: Buffer << "Cm"; break;
case AbstractCC::WitnessMethod: Buffer << "Cw"; break;
}
}
if (fn->isNoReturn()) Buffer << 'N';
if (fn->isPolymorphic()) {
Buffer << 'G';
mangleGenericSignature(fn->getGenericSignature(), explosion);
}
Buffer << '_';
auto mangleParameter = [&](SILParameterInfo param) {
Buffer << mangleParameterConvention(param.getConvention());
mangleType(param.getType(), ResilienceExpansion::Minimal, 0);
};
for (auto param : fn->getInterfaceParametersWithoutIndirectResult()) {
mangleParameter(param);
}
Buffer << '_';
if (fn->hasIndirectResult()) {
mangleParameter(fn->getIndirectInterfaceResult());
} else {
auto result = fn->getInterfaceResult();
Buffer << mangleResultConvention(result.getConvention());
mangleType(result.getType(), ResilienceExpansion::Minimal, 0);
}
Buffer << '_';
return;
}
// type ::= archetype
case TypeKind::Archetype: {
auto archetype = cast<ArchetypeType>(type);
// archetype ::= associated-type
// associated-type ::= substitution
if (tryMangleSubstitution(archetype.getPointer()))
return;
Buffer << 'Q';
// associated-type ::= 'Q' archetype identifier
// Mangle the associated type of a parent archetype.
if (auto parent = archetype->getParent()) {
assert(archetype->getAssocType()
&& "child archetype has no associated type?!");
mangleType(CanType(parent), explosion, 0);
mangleIdentifier(archetype->getName());
addSubstitution(archetype.getPointer());
return;
}
// associated-type ::= 'Q' protocol-context
// Mangle the Self archetype of a protocol.
if (auto proto = archetype->getSelfProtocol()) {
Buffer << 'P';
mangleProtocolName(proto);
addSubstitution(archetype.getPointer());
return;
}
// archetype ::= 'Q' <index> # archetype with depth=0, index=N
// archetype ::= 'Qd' <index> <index> # archetype with depth=M+1, index=N
// Mangle generic parameter archetypes.
// Find the archetype information.
DeclContext *DC = DeclCtx;
auto it = Archetypes.find(archetype);
while (it == Archetypes.end()) {
// This should be treated like an error, but we don't want
// clients like lldb to crash because of corrupted input.
assert(DC && "empty decl context");
if (!DC) return;
// This Archetype comes from an enclosing context -- proceed to
// bind the generic params form all parent contexts.
GenericParamList *GenericParams = nullptr;
do { // Skip over empty parent contexts.
DC = DC->getParent();
assert(DC && "no decl context for archetype found");
if (!DC) return;
GenericParams = DC->getGenericParamsOfContext();
} while (!GenericParams);
bindGenericParameters(GenericParams);
it = Archetypes.find(archetype);
}
auto &info = it->second;
assert(ArchetypesDepth >= info.Depth);
unsigned relativeDepth = ArchetypesDepth - info.Depth;
if (DWARFMangling) {
Buffer << 'q' << Index(info.Index);
// The DWARF output created by Swift is intentionally flat,
// therefore archetypes are emitted with their DeclContext if
// they appear at the top level of a type (_Tt).
// Clone a new, non-DWARF Mangler for the DeclContext.
Mangler ContextMangler(Buffer, /*DWARFMangling=*/false);
SmallVector<void *, 4> SortedSubsts(Substitutions.size());
for (auto S : Substitutions) SortedSubsts[S.second] = S.first;
for (auto S : SortedSubsts) ContextMangler.addSubstitution(S);
for (; relativeDepth > 0; --relativeDepth)
DC = DC->getParent();
ContextMangler.mangleContext(DC, BindGenerics::None);
} else {
if (relativeDepth != 0) {
Buffer << 'd' << Index(relativeDepth - 1);
}
Buffer << Index(info.Index);
}
return;
}
case TypeKind::DynamicSelf: {
auto dynamicSelf = cast<DynamicSelfType>(type);
if (dynamicSelf->getSelfType()->getAnyNominal()) {
Buffer << 'D';
mangleType(dynamicSelf.getSelfType(), explosion, uncurryLevel);
} else {
// Mangle DynamicSelf as Self within a protocol.
mangleType(dynamicSelf.getSelfType(), explosion, uncurryLevel);
}
return;
}
case TypeKind::GenericFunction: {
llvm_unreachable("cannot mangle generic function types yet");
}
case TypeKind::GenericTypeParam: {
Buffer << 'q';
// FIXME: Notion of depth is reversed from that for archetypes.
auto paramTy = cast<GenericTypeParamType>(type);
if (paramTy->getDepth() > 0) {
Buffer << 'd';
Buffer << Index(paramTy->getDepth() - 1);
}
Buffer << Index(paramTy->getIndex());
return;
}
case TypeKind::DependentMember: {
Buffer << 'q';
auto memTy = cast<DependentMemberType>(type);
mangleType(memTy.getBase(), explosion, 0);
mangleIdentifier(memTy->getName());
return;
}
case TypeKind::Function:
mangleFunctionType(cast<FunctionType>(type), explosion, uncurryLevel);
return;
case TypeKind::Array: {
// type ::= 'A' integer type
auto array = cast<ArrayType>(type);
Buffer << 'A';
Buffer << array->getSize();
mangleType(array.getBaseType(), ResilienceExpansion::Minimal, 0);
return;
};
case TypeKind::ProtocolComposition: {
// We mangle ProtocolType and ProtocolCompositionType using the
// same production:
// <type> ::= P <protocol-list> _
auto protocols = cast<ProtocolCompositionType>(type)->getProtocols();
Buffer << 'P';
mangleProtocolList(protocols);
Buffer << '_';
return;
}
}
llvm_unreachable("bad type kind");
}
/// Mangle a list of protocols. Each protocol is a substitution
/// candidate.
/// <protocol-list> ::= <protocol-name>+
void Mangler::mangleProtocolList(ArrayRef<Type> protocols) {
for (auto protoTy : protocols) {
mangleProtocolName(protoTy->castTo<ProtocolType>()->getDecl());
}
}
void Mangler::mangleProtocolList(ArrayRef<ProtocolDecl*> protocols) {
for (auto protocol : protocols) {
mangleProtocolName(protocol);
}
}
/// Mangle the name of a protocol as a substitution candidate.
void Mangler::mangleProtocolName(ProtocolDecl *protocol) {
// <protocol-name> ::= <decl> # substitutable
// The <decl> in a protocol-name is the same substitution
// candidate as a protocol <type>, but it is mangled without
// the surrounding 'P'...'_'.
ProtocolType *type = cast<ProtocolType>(protocol->getDeclaredType());
if (tryMangleSubstitution(type))
return;
ContextStack context(*this);
mangleContextOf(protocol, BindGenerics::None);
mangleDeclName(protocol);
addSubstitution(type);
}
static char getSpecifierForNominalType(NominalTypeDecl *decl) {
switch (decl->getKind()) {
#define NOMINAL_TYPE_DECL(id, parent)
#define DECL(id, parent) \
case DeclKind::id:
#include "swift/AST/DeclNodes.def"
llvm_unreachable("not a nominal type");
case DeclKind::Protocol: return 'P';
case DeclKind::Class: return 'C';
case DeclKind::Enum: return 'O';
case DeclKind::Struct: return 'V';
}
llvm_unreachable("bad decl kind");
}
void Mangler::mangleNominalType(NominalTypeDecl *decl,
ResilienceExpansion explosion,
BindGenerics shouldBind) {
auto bindGenericsIfDesired = [&] {
if (shouldBind == BindGenerics::All)
if (auto generics = decl->getGenericParams())
bindGenericParameters(generics, /*mangle*/ false);
};
// Check for certain standard types.
if (tryMangleStandardSubstitution(decl)) {
bindGenericsIfDesired();
return;
}
// For generic types, this uses the unbound type.
TypeBase *key = decl->getDeclaredType().getPointer();
// Try to mangle the entire name as a substitution.
// type ::= substitution
if (tryMangleSubstitution(key)) {
bindGenericsIfDesired();
return;
}
Buffer << getSpecifierForNominalType(decl);
mangleContextOf(decl, shouldBind);
bindGenericsIfDesired();
mangleDeclName(decl);
addSubstitution(key);
}
bool Mangler::tryMangleStandardSubstitution(NominalTypeDecl *decl) {
// Bail out if our parent isn't the swift standard library.
DeclContext *dc = decl->getDeclContext();
if (!dc->isModuleScopeContext() || !dc->getParentModule()->isStdlibModule())
return false;
// Standard substitutions shouldn't start with 's' (because that's
// reserved for the swift module itself) or a digit or '_'.
StringRef name = decl->getName().str();
if (name == "Int") {
Buffer << "Si";
return true;
} else if (name == "UInt") {
Buffer << "Su";
return true;
} else if (name == "Bool") {
Buffer << "Sb";
return true;
} else if (name == "UnicodeScalar") {
Buffer << "Sc";
return true;
} else if (name == "Float64") {
Buffer << "Sd";
return true;
} else if (name == "Float32") {
Buffer << "Sf";
return true;
} else if (name == "Optional") {
Buffer << "Sq";
return true;
} else if (name == "UncheckedOptional") {
Buffer << "SQ";
return true;
} else if (name == "Array") {
Buffer << "Sa";
return true;
} else if (name == "String") {
Buffer << "SS";
return true;
} else {
return false;
}
}
void Mangler::mangleFunctionType(CanAnyFunctionType fn,
ResilienceExpansion explosion,
unsigned uncurryLevel) {
// type ::= 'F' type type (curried)
// type ::= 'f' type type (uncurried)
// type ::= 'b' type type (objc block)
// type ::= 'K' type type (auto closure)
if (fn->getRepresentation() == AnyFunctionType::Representation::Block)
Buffer << 'b';
else if (fn->isAutoClosure())
Buffer << 'K';
else
Buffer << (uncurryLevel > 0 ? 'f' : 'F');
mangleType(fn.getInput(), explosion, 0);
mangleType(fn.getResult(), explosion,
(uncurryLevel > 0 ? uncurryLevel - 1 : 0));
}
void Mangler::mangleClosureEntity(AbstractClosureExpr *closure,
ResilienceExpansion explosion,
unsigned uncurryLevel) {
// entity-name ::= 'U' index type // explicit anonymous closure
// entity-name ::= 'u' index type // implicit anonymous closure
auto discriminator = closure->getDiscriminator();
assert(discriminator != AbstractClosureExpr::InvalidDiscriminator
&& "closure not marked correctly with discriminator?");
Buffer << 'F';
mangleContext(closure->getParent(), BindGenerics::All);
Buffer << (isa<ClosureExpr>(closure) ? 'U' : 'u') << Index(discriminator);
mangleType(closure->getType()->getCanonicalType(),
ResilienceExpansion::Minimal, /*uncurry*/ 0);
}
void Mangler::mangleConstructorEntity(ConstructorDecl *ctor,
bool isAllocating,
ResilienceExpansion explosion,
unsigned uncurryLevel) {
Buffer << 'F';
mangleContextOf(ctor, BindGenerics::Enclosing);
Buffer << (isAllocating ? 'C' : 'c');
mangleDeclType(ctor, explosion, uncurryLevel);
}
void Mangler::mangleDestructorEntity(DestructorDecl *dtor,
bool isDeallocating) {
Buffer << 'F';
mangleContextOf(dtor, BindGenerics::Enclosing);
Buffer << (isDeallocating ? 'D' : 'd');
}
void Mangler::mangleIVarInitDestroyEntity(ClassDecl *decl, bool isDestroyer) {
Buffer << 'F';
mangleContext(decl, BindGenerics::Enclosing);
Buffer << (isDestroyer ? 'E' : 'e');
}
static char getCodeForAccessorKind(AccessorKind kind) {
switch (kind) {
case AccessorKind::NotAccessor: llvm_unreachable("bad accessor kind!");
case AccessorKind::IsGetter: return 'g';
case AccessorKind::IsSetter: return 's';
case AccessorKind::IsWillSet: return 'w';
case AccessorKind::IsDidSet: return 'W';
}
llvm_unreachable("bad accessor kind");
}
void Mangler::mangleAccessorEntity(AccessorKind kind, AbstractStorageDecl *decl,
ResilienceExpansion explosion) {
assert(kind != AccessorKind::NotAccessor);
Buffer << 'F';
mangleContextOf(decl, BindGenerics::All);
Buffer << getCodeForAccessorKind(kind);
mangleDeclName(decl);
mangleDeclType(decl, explosion, 0);
}
void Mangler::mangleAddressorEntity(ValueDecl *decl) {
Buffer << 'F';
mangleContextOf(decl, BindGenerics::All);
Buffer << 'a';
mangleDeclName(decl);
mangleDeclType(decl, ResilienceExpansion::Minimal, 0);
}
void Mangler::mangleDefaultArgumentEntity(DeclContext *func, unsigned index) {
Buffer << 'I';
mangleContext(func, BindGenerics::All);
Buffer << 'A' << Index(index);
}
void Mangler::mangleInitializerEntity(VarDecl *var) {
// The initializer is its own entity whose context is the variable.
Buffer << 'I';
mangleEntity(var, ResilienceExpansion::Minimal, /*uncurry*/ 0);
Buffer << 'i';
}
void Mangler::mangleEntity(ValueDecl *decl, ResilienceExpansion explosion,
unsigned uncurryLevel) {
assert(!isa<ConstructorDecl>(decl));
assert(!isa<DestructorDecl>(decl));
// Handle accessors specially, they are mangled as modifiers on the accessed
// declaration.
if (auto func = dyn_cast<FuncDecl>(decl)) {
auto accessorKind = func->getAccessorKind();
if (accessorKind != AccessorKind::NotAccessor)
return mangleAccessorEntity(accessorKind, func->getAccessorStorageDecl(),
explosion);
}
BindGenerics shouldBindParent = BindGenerics::All;
// entity ::= entity-kind context entity-name
if (isa<VarDecl>(decl)) {
Buffer << 'v';
} else if (isa<SubscriptDecl>(decl)) {
Buffer << 's';
} else {
assert(isa<AbstractFunctionDecl>(decl) ||
isa<EnumElementDecl>(decl));
Buffer << 'F';
// If this is a method, then its formal type includes the
// archetypes of its parent.
if (decl->getDeclContext()->isTypeContext())
shouldBindParent = BindGenerics::Enclosing;
}
mangleContextOf(decl, shouldBindParent);
mangleDeclName(decl);
mangleDeclType(decl, explosion, uncurryLevel);
}
void Mangler::mangleDirectness(bool isIndirect) {
Buffer << (isIndirect ? 'i': 'd');
}
void Mangler::mangleProtocolConformance(ProtocolConformance *conformance) {
// protocol-conformance ::= ('U' generic-parameter+ '_')?
// type protocol module
// FIXME: explosion level?
CanType type = conformance->getType()->getCanonicalType();
// FIXME: Assume that all generic conformances add no additional constraints
// to the conforming type's generic parameters and swallow them. This makes
// it easier for our hacked-up implementation of swift_conformsToProtocol
// to find them.
if (conformance->getGenericParams())
type = UnboundGenericType::get(type->getNominalOrBoundGenericNominal(),
nullptr,
type->getASTContext())->getCanonicalType();
#if 0
ContextStack context(*this);
// If the conformance is generic, mangle its generic parameters.
if (auto gp = conformance->getGenericParams()) {
Buffer << 'U';
bindGenericParameters(gp, /*mangle*/ true);
}
#endif
mangleType(type, ResilienceExpansion::Minimal, 0);
mangleProtocolName(conformance->getProtocol());
mangleModule(conformance->getDeclContext()->getParentModule());
}