blob: 0fdcbfcb8c84a45d1809b73d244a2a9992e361ee [file] [log] [blame]
//===--- Linking.cpp - Name mangling for IRGen entities -------------------===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file implements name mangling for IRGen entities with linkage.
//
//===----------------------------------------------------------------------===//
#include "Linking.h"
#include "IRGenMangler.h"
#include "llvm/Support/raw_ostream.h"
#include "swift/ClangImporter/ClangImporter.h"
#include "swift/SIL/SILGlobalVariable.h"
#include "swift/AST/Mangle.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclObjC.h"
#include "llvm/Support/Compiler.h"
using namespace swift;
using namespace irgen;
using namespace Mangle;
static StringRef mangleValueWitness(ValueWitness witness) {
// The ones with at least one capital are the composite ops, and the
// capitals correspond roughly to the positions of buffers (as
// opposed to objects) in the arguments. That doesn't serve any
// direct purpose, but it's neat.
switch (witness) {
#define VALUE_WITNESS(MANGLING, NAME) \
case ValueWitness::NAME: return #MANGLING;
#include "swift/Basic/ValueWitnessMangling.def"
case ValueWitness::Size:
case ValueWitness::Flags:
case ValueWitness::Stride:
case ValueWitness::ExtraInhabitantFlags:
llvm_unreachable("not a function witness");
}
llvm_unreachable("bad witness kind");
}
/// Mangle this entity as a std::string.
std::string LinkEntity::mangleAsString() const {
std::string result; {
llvm::raw_string_ostream stream(result);
mangle(stream);
}
return result;
}
/// Mangle this entity into the given buffer.
void LinkEntity::mangle(SmallVectorImpl<char> &buffer) const {
llvm::raw_svector_ostream stream(buffer);
mangle(stream);
}
/// Use the Clang importer to mangle a Clang declaration.
static void mangleClangDecl(raw_ostream &buffer,
const clang::NamedDecl *clangDecl,
ASTContext &ctx) {
auto *importer = static_cast<ClangImporter *>(ctx.getClangModuleLoader());
importer->getMangledName(buffer, clangDecl);
}
/// Mangle this entity into the given stream.
void LinkEntity::mangle(raw_ostream &buffer) const {
std::string Old = mangleOld();
std::string New = mangleNew();
std::string Result = NewMangling::selectMangling(Old, New);
buffer.write(Result.data(), Result.size());
}
/// Mangle this entity into the given stream.
std::string LinkEntity::mangleOld() const {
// Almost everything below gets the common prefix:
// mangled-name ::= '_T' global
Mangler mangler;
switch (getKind()) {
// global ::= 'w' value-witness-kind type // value witness
case Kind::ValueWitness:
mangler.append("_Tw");
mangler.append(mangleValueWitness(getValueWitness()));
mangler.mangleType(getType(), 0);
return mangler.finalize();
// global ::= 'WV' type // value witness
case Kind::ValueWitnessTable:
mangler.append("_TWV");
mangler.mangleType(getType(), 0);
return mangler.finalize();
// global ::= 'Ma' type // type metadata access function
case Kind::TypeMetadataAccessFunction:
mangler.append("_TMa");
mangler.mangleType(getType(), 0);
return mangler.finalize();
// global ::= 'ML' type // type metadata lazy cache variable
case Kind::TypeMetadataLazyCacheVariable:
mangler.append("_TML");
mangler.mangleType(getType(), 0);
return mangler.finalize();
// global ::= 'Mf' type // 'full' type metadata
// global ::= 'M' directness type // type metadata
// global ::= 'MP' directness type // type metadata pattern
case Kind::TypeMetadata:
switch (getMetadataAddress()) {
case TypeMetadataAddress::FullMetadata:
mangler.mangleTypeFullMetadataFull(getType());
break;
case TypeMetadataAddress::AddressPoint:
mangler.mangleTypeMetadataFull(getType(), isMetadataPattern());
break;
}
return mangler.finalize();
// global ::= 'M' directness type // type metadata
case Kind::ForeignTypeMetadataCandidate:
mangler.mangleTypeMetadataFull(getType(), /*isPattern=*/false);
return mangler.finalize();
// global ::= 'Mm' type // class metaclass
case Kind::SwiftMetaclassStub:
mangler.append("_TMm");
mangler.mangleNominalType(cast<ClassDecl>(getDecl()));
return mangler.finalize();
// global ::= 'Mn' type // nominal type descriptor
case Kind::NominalTypeDescriptor:
mangler.append("_TMn");
mangler.mangleNominalType(cast<NominalTypeDecl>(getDecl()));
return mangler.finalize();
// global ::= 'Mp' type // protocol descriptor
case Kind::ProtocolDescriptor:
mangler.append("_TMp");
mangler.mangleProtocolName(cast<ProtocolDecl>(getDecl()));
return mangler.finalize();
// global ::= 'Wo' entity
case Kind::WitnessTableOffset:
mangler.append("_TWo");
// Witness table entries for constructors always refer to the allocating
// constructor.
if (auto ctor = dyn_cast<ConstructorDecl>(getDecl()))
mangler.mangleConstructorEntity(ctor, /*isAllocating=*/true,
getUncurryLevel());
else
mangler.mangleEntity(getDecl(), getUncurryLevel());
return mangler.finalize();
// global ::= 'Wv' directness entity
case Kind::FieldOffset:
mangler.mangleFieldOffsetFull(getDecl(), isOffsetIndirect());
return mangler.finalize();
// global ::= 'WP' protocol-conformance
case Kind::DirectProtocolWitnessTable:
mangler.append("_TWP");
mangler.mangleProtocolConformance(getProtocolConformance());
return mangler.finalize();
// global ::= 'WG' protocol-conformance
case Kind::GenericProtocolWitnessTableCache:
mangler.mangleProtocolConformance(getProtocolConformance());
return std::string("_TWG") + mangler.finalize();
// global ::= 'WI' protocol-conformance
case Kind::GenericProtocolWitnessTableInstantiationFunction:
mangler.mangleProtocolConformance(getProtocolConformance());
return std::string("_TWI") + mangler.finalize();
// global ::= 'Wa' protocol-conformance
case Kind::ProtocolWitnessTableAccessFunction:
mangler.append("_TWa");
mangler.mangleProtocolConformance(getProtocolConformance());
return mangler.finalize();
// global ::= 'Wl' type protocol-conformance
case Kind::ProtocolWitnessTableLazyAccessFunction:
mangler.append("_TWl");
mangler.mangleType(getType(), 0);
mangler.mangleProtocolConformance(getProtocolConformance());
return mangler.finalize();
// global ::= 'WL' type protocol-conformance
case Kind::ProtocolWitnessTableLazyCacheVariable:
mangler.append("_TWL");
mangler.mangleType(getType(), 0);
mangler.mangleProtocolConformance(getProtocolConformance());
return mangler.finalize();
// global ::= 'Wt' protocol-conformance identifier
case Kind::AssociatedTypeMetadataAccessFunction:
mangler.append("_TWt");
mangler.mangleProtocolConformance(getProtocolConformance());
mangler.mangleIdentifier(getAssociatedType()->getNameStr());
return mangler.finalize();
// global ::= 'WT' protocol-conformance identifier nominal-type
case Kind::AssociatedTypeWitnessTableAccessFunction:
mangler.append("_TWT");
mangler.mangleProtocolConformance(getProtocolConformance());
mangler.mangleIdentifier(getAssociatedType()->getNameStr());
mangler.mangleProtocolDecl(getAssociatedProtocol());
return mangler.finalize();
// For all the following, this rule was imposed above:
// global ::= local-marker? entity // some identifiable thing
// entity ::= declaration // other declaration
case Kind::Function:
// As a special case, functions can have manually mangled names.
if (auto AsmA = getDecl()->getAttrs().getAttribute<SILGenNameAttr>()) {
mangler.append(AsmA->Name);
return mangler.finalize();
}
// Otherwise, fall through into the 'other decl' case.
LLVM_FALLTHROUGH;
case Kind::Other:
// As a special case, Clang functions and globals don't get mangled at all.
if (auto clangDecl = getDecl()->getClangDecl()) {
if (auto namedClangDecl = dyn_cast<clang::DeclaratorDecl>(clangDecl)) {
if (auto asmLabel = namedClangDecl->getAttr<clang::AsmLabelAttr>()) {
mangler.append('\01');
mangler.append(asmLabel->getLabel());
} else if (namedClangDecl->hasAttr<clang::OverloadableAttr>()) {
// FIXME: When we can import C++, use Clang's mangler all the time.
std::string storage;
llvm::raw_string_ostream SS(storage);
mangleClangDecl(SS, namedClangDecl, getDecl()->getASTContext());
mangler.append(SS.str());
} else {
mangler.append(namedClangDecl->getName());
}
return mangler.finalize();
}
}
mangler.append("_T");
if (auto type = dyn_cast<NominalTypeDecl>(getDecl())) {
mangler.mangleNominalType(type);
} else if (auto ctor = dyn_cast<ConstructorDecl>(getDecl())) {
// FIXME: Hack. LinkInfo should be able to refer to the allocating
// constructor rather than inferring it here.
mangler.mangleConstructorEntity(ctor, /*isAllocating=*/true,
getUncurryLevel());
} else {
mangler.mangleEntity(getDecl(), getUncurryLevel());
}
return mangler.finalize();
// An Objective-C class reference reference. The symbol is private, so
// the mangling is unimportant; it should just be readable in LLVM IR.
case Kind::ObjCClassRef: {
mangler.append("OBJC_CLASS_REF_$_");
llvm::SmallString<64> tempBuffer;
StringRef name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(tempBuffer);
mangler.append(name);
return mangler.finalize();
}
// An Objective-C class reference; not a swift mangling.
case Kind::ObjCClass: {
llvm::SmallString<64> TempBuffer;
mangler.append("OBJC_CLASS_$_");
StringRef Name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(TempBuffer);
mangler.append(Name);
return mangler.finalize();
}
// An Objective-C metaclass reference; not a swift mangling.
case Kind::ObjCMetaclass: {
llvm::SmallString<64> TempBuffer;
mangler.append("OBJC_METACLASS_$_");
StringRef Name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(TempBuffer);
mangler.append(Name);
return mangler.finalize();
}
case Kind::SILFunction:
mangler.appendSymbol(getSILFunction()->getName());
return mangler.finalize();
case Kind::SILGlobalVariable:
mangler.appendSymbol(getSILGlobalVariable()->getName());
return mangler.finalize();
case Kind::ReflectionBuiltinDescriptor:
mangler.append("_TMRb");
mangler.mangleType(getType(), getUncurryLevel());
return mangler.finalize();
case Kind::ReflectionFieldDescriptor:
mangler.append("_TMRf");
mangler.mangleType(getType(), getUncurryLevel());
return mangler.finalize();
case Kind::ReflectionAssociatedTypeDescriptor:
mangler.append("_TMRa");
mangler.mangleProtocolConformance(getProtocolConformance());
return mangler.finalize();
case Kind::ReflectionSuperclassDescriptor:
mangler.append("_TMRs");
mangler.mangleNominalType(cast<ClassDecl>(getDecl()));
return mangler.finalize();
}
llvm_unreachable("bad entity kind!");
}
/// Mangle this entity into the given stream.
std::string LinkEntity::mangleNew() const {
// Almost everything below gets the common prefix:
// mangled-name ::= '_T' global
IRGenMangler mangler;
switch (getKind()) {
// global ::= 'w' value-witness-kind // value witness
case Kind::ValueWitness:
return mangler.mangleValueWitness(getType(), getValueWitness());
// global ::= 'WV' type // value witness
case Kind::ValueWitnessTable:
return mangler.mangleValueWitnessTable(getType());
// global ::= 'Ma' type // type metadata access function
case Kind::TypeMetadataAccessFunction:
return mangler.mangleTypeMetadataAccessFunction(getType());
// global ::= 'ML' type // type metadata lazy cache variable
case Kind::TypeMetadataLazyCacheVariable:
return mangler.mangleTypeMetadataLazyCacheVariable(getType());
// global ::= 'Mf' type // 'full' type metadata
// global ::= 'M' directness type // type metadata
// global ::= 'MP' directness type // type metadata pattern
case Kind::TypeMetadata:
switch (getMetadataAddress()) {
case TypeMetadataAddress::FullMetadata:
return mangler.mangleTypeFullMetadataFull(getType());
case TypeMetadataAddress::AddressPoint:
return mangler.mangleTypeMetadataFull(getType(), isMetadataPattern());
}
llvm_unreachable("invalid metadata address");
// global ::= 'M' directness type // type metadata
case Kind::ForeignTypeMetadataCandidate:
return mangler.mangleTypeMetadataFull(getType(), /*isPattern=*/false);
// global ::= 'Mm' type // class metaclass
case Kind::SwiftMetaclassStub:
return mangler.mangleClassMetaClass(cast<ClassDecl>(getDecl()));
// global ::= 'Mn' type // nominal type descriptor
case Kind::NominalTypeDescriptor:
return mangler.mangleNominalTypeDescriptor(
cast<NominalTypeDecl>(getDecl()));
// global ::= 'Mp' type // protocol descriptor
case Kind::ProtocolDescriptor:
return mangler.mangleProtocolDescriptor(cast<ProtocolDecl>(getDecl()));
// global ::= 'Wo' entity
case Kind::WitnessTableOffset:
return mangler.mangleWitnessTableOffset(getDecl());
// global ::= 'Wv' directness entity
case Kind::FieldOffset:
return mangler.mangleFieldOffsetFull(getDecl(), isOffsetIndirect());
// global ::= 'WP' protocol-conformance
case Kind::DirectProtocolWitnessTable:
return mangler.mangleDirectProtocolWitnessTable(getProtocolConformance());
// global ::= 'WG' protocol-conformance
case Kind::GenericProtocolWitnessTableCache:
return mangler.mangleGenericProtocolWitnessTableCache(
getProtocolConformance());
// global ::= 'WI' protocol-conformance
case Kind::GenericProtocolWitnessTableInstantiationFunction:
return mangler.mangleGenericProtocolWitnessTableInstantiationFunction(
getProtocolConformance());
// global ::= 'Wa' protocol-conformance
case Kind::ProtocolWitnessTableAccessFunction:
return mangler.mangleProtocolWitnessTableAccessFunction(
getProtocolConformance());
// global ::= 'Wl' type protocol-conformance
case Kind::ProtocolWitnessTableLazyAccessFunction:
return mangler.mangleProtocolWitnessTableLazyAccessFunction(getType(),
getProtocolConformance());
// global ::= 'WL' type protocol-conformance
case Kind::ProtocolWitnessTableLazyCacheVariable:
return mangler.mangleProtocolWitnessTableLazyCacheVariable(getType(),
getProtocolConformance());
// global ::= 'Wt' protocol-conformance identifier
case Kind::AssociatedTypeMetadataAccessFunction:
return mangler.mangleAssociatedTypeMetadataAccessFunction(
getProtocolConformance(), getAssociatedType()->getNameStr());
// global ::= 'WT' protocol-conformance identifier nominal-type
case Kind::AssociatedTypeWitnessTableAccessFunction:
return mangler.mangleAssociatedTypeWitnessTableAccessFunction(
getProtocolConformance(), getAssociatedType()->getNameStr(),
getAssociatedProtocol());
// For all the following, this rule was imposed above:
// global ::= local-marker? entity // some identifiable thing
// entity ::= declaration // other declaration
case Kind::Function:
// As a special case, functions can have manually mangled names.
if (auto AsmA = getDecl()->getAttrs().getAttribute<SILGenNameAttr>()) {
return AsmA->Name;
}
// Otherwise, fall through into the 'other decl' case.
LLVM_FALLTHROUGH;
case Kind::Other:
// As a special case, Clang functions and globals don't get mangled at all.
if (auto clangDecl = getDecl()->getClangDecl()) {
if (auto namedClangDecl = dyn_cast<clang::DeclaratorDecl>(clangDecl)) {
if (auto asmLabel = namedClangDecl->getAttr<clang::AsmLabelAttr>()) {
std::string Name(1, '\01');
Name.append(asmLabel->getLabel());
return Name;
}
if (namedClangDecl->hasAttr<clang::OverloadableAttr>()) {
// FIXME: When we can import C++, use Clang's mangler all the time.
std::string storage;
llvm::raw_string_ostream SS(storage);
mangleClangDecl(SS, namedClangDecl, getDecl()->getASTContext());
return SS.str();
}
return namedClangDecl->getName();
}
}
if (auto type = dyn_cast<NominalTypeDecl>(getDecl())) {
return mangler.mangleNominalType(type);
}
if (auto ctor = dyn_cast<ConstructorDecl>(getDecl())) {
// FIXME: Hack. LinkInfo should be able to refer to the allocating
// constructor rather than inferring it here.
return mangler.mangleConstructorEntity(ctor, /*isAllocating=*/true,
/*isCurried=*/false);
}
return mangler.mangleEntity(getDecl(), /*isCurried=*/false);
// An Objective-C class reference reference. The symbol is private, so
// the mangling is unimportant; it should just be readable in LLVM IR.
case Kind::ObjCClassRef: {
llvm::SmallString<64> tempBuffer;
StringRef name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(tempBuffer);
std::string Result("OBJC_CLASS_REF_$_");
Result.append(name.data(), name.size());
return Result;
}
// An Objective-C class reference; not a swift mangling.
case Kind::ObjCClass: {
llvm::SmallString<64> TempBuffer;
StringRef Name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(TempBuffer);
std::string Result("OBJC_CLASS_$_");
Result.append(Name.data(), Name.size());
return Result;
}
// An Objective-C metaclass reference; not a swift mangling.
case Kind::ObjCMetaclass: {
llvm::SmallString<64> TempBuffer;
StringRef Name = cast<ClassDecl>(getDecl())->getObjCRuntimeName(TempBuffer);
std::string Result("OBJC_METACLASS_$_");
Result.append(Name.data(), Name.size());
return Result;
}
case Kind::SILFunction:
return getSILFunction()->getName();
case Kind::SILGlobalVariable:
return getSILGlobalVariable()->getName();
case Kind::ReflectionBuiltinDescriptor:
return mangler.mangleReflectionBuiltinDescriptor(getType());
case Kind::ReflectionFieldDescriptor:
return mangler.mangleReflectionFieldDescriptor(getType());
case Kind::ReflectionAssociatedTypeDescriptor:
return mangler.mangleReflectionAssociatedTypeDescriptor(
getProtocolConformance());
case Kind::ReflectionSuperclassDescriptor:
return mangler.mangleReflectionSuperclassDescriptor(
cast<ClassDecl>(getDecl()));
}
llvm_unreachable("bad entity kind!");
}