Skip to content

Commit

Permalink
[clang][AST] ASTNameGenerator: A refactoring of CodegenNameGeneratorI…
Browse files Browse the repository at this point in the history
…mpl (NFC).

This is a NFC refactor move of CodegenNameGeneratorImpl from clang::Index to
clang:AST (and rename to ASTNameGenerator). The purpose is to make the
highlevel mangling code more reusable inside of clang (say in places like clang
FrontendAction). This does not affect anything in CodegenNameGenerator, except
that CodegenNameGenerator will now use ASTNameGenerator (in AST).

Differential Revision: https://reviews.llvm.org/D63535

llvm-svn: 363878
  • Loading branch information
plotfi committed Jun 19, 2019
1 parent ce53e22 commit 3ff8c3b
Show file tree
Hide file tree
Showing 5 changed files with 206 additions and 193 deletions.
19 changes: 19 additions & 0 deletions clang/include/clang/AST/Mangle.h
Expand Up @@ -17,6 +17,7 @@
#include "clang/AST/Type.h"
#include "clang/Basic/ABI.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/Support/Casting.h"

namespace llvm {
Expand Down Expand Up @@ -243,6 +244,24 @@ class MicrosoftMangleContext : public MangleContext {
static MicrosoftMangleContext *create(ASTContext &Context,
DiagnosticsEngine &Diags);
};

class ASTNameGenerator {
std::unique_ptr<MangleContext> MC;
llvm::DataLayout DL;

public:
explicit ASTNameGenerator(ASTContext &Ctx);
bool writeName(const Decl *D, raw_ostream &OS);
std::string getName(const Decl *D);
std::vector<std::string> getAllManglings(const Decl *D);

private:
std::vector<std::string> getAllManglings(const ObjCContainerDecl *OCD);
bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS);
void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS);
std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType);
std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T);
};
}

#endif
3 changes: 2 additions & 1 deletion clang/include/clang/Index/CodegenNameGenerator.h
Expand Up @@ -13,6 +13,7 @@
#ifndef LLVM_CLANG_INDEX_CODEGENNAMEGENERATOR_H
#define LLVM_CLANG_INDEX_CODEGENNAMEGENERATOR_H

#include "clang/AST/Mangle.h"
#include "clang/Basic/LLVM.h"
#include <memory>
#include <string>
Expand Down Expand Up @@ -42,7 +43,7 @@ class CodegenNameGenerator {

private:
struct Implementation;
std::unique_ptr<Implementation> Impl;
std::unique_ptr<ASTNameGenerator> Impl;
};

} // namespace index
Expand Down
1 change: 1 addition & 0 deletions clang/lib/AST/CMakeLists.txt
@@ -1,5 +1,6 @@
set(LLVM_LINK_COMPONENTS
BinaryFormat
Core
Support
)

Expand Down
183 changes: 183 additions & 0 deletions clang/lib/AST/Mangle.cpp
Expand Up @@ -17,10 +17,12 @@
#include "clang/AST/DeclTemplate.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/Mangle.h"
#include "clang/AST/VTableBuilder.h"
#include "clang/Basic/ABI.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/TargetInfo.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/IR/Mangler.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"

Expand Down Expand Up @@ -280,3 +282,184 @@ void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD,
mangleObjCMethodNameWithoutSize(MD, OS);
Out << OS.str().size() << OS.str();
}

ASTNameGenerator::ASTNameGenerator(ASTContext &Ctx)
: MC(Ctx.createMangleContext()), DL(Ctx.getTargetInfo().getDataLayout()) {}

bool ASTNameGenerator::writeName(const Decl *D, raw_ostream &OS) {
// First apply frontend mangling.
SmallString<128> FrontendBuf;
llvm::raw_svector_ostream FrontendBufOS(FrontendBuf);
if (auto *FD = dyn_cast<FunctionDecl>(D)) {
if (FD->isDependentContext())
return true;
if (writeFuncOrVarName(FD, FrontendBufOS))
return true;
} else if (auto *VD = dyn_cast<VarDecl>(D)) {
if (writeFuncOrVarName(VD, FrontendBufOS))
return true;
} else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
MC->mangleObjCMethodNameWithoutSize(MD, OS);
return false;
} else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) {
writeObjCClassName(ID, FrontendBufOS);
} else {
return true;
}

// Now apply backend mangling.
llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL);
return false;
}

std::string ASTNameGenerator::getName(const Decl *D) {
std::string Name;
{
llvm::raw_string_ostream OS(Name);
writeName(D, OS);
}
return Name;
}

enum ObjCKind {
ObjCClass,
ObjCMetaclass,
};

static StringRef getClassSymbolPrefix(ObjCKind Kind,
const ASTContext &Context) {
if (Context.getLangOpts().ObjCRuntime.isGNUFamily())
return Kind == ObjCMetaclass ? "_OBJC_METACLASS_" : "_OBJC_CLASS_";
return Kind == ObjCMetaclass ? "OBJC_METACLASS_$_" : "OBJC_CLASS_$_";
}

std::vector<std::string>
ASTNameGenerator::getAllManglings(const ObjCContainerDecl *OCD) {
StringRef ClassName;
if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(OCD))
ClassName = OID->getObjCRuntimeNameAsString();
else if (const auto *OID = dyn_cast<ObjCImplementationDecl>(OCD))
ClassName = OID->getObjCRuntimeNameAsString();

if (ClassName.empty())
return {};

auto Mangle = [&](ObjCKind Kind, StringRef ClassName) -> std::string {
SmallString<40> Mangled;
auto Prefix = getClassSymbolPrefix(Kind, OCD->getASTContext());
llvm::Mangler::getNameWithPrefix(Mangled, Prefix + ClassName, DL);
return Mangled.str();
};

return {
Mangle(ObjCClass, ClassName),
Mangle(ObjCMetaclass, ClassName),
};
}

std::vector<std::string> ASTNameGenerator::getAllManglings(const Decl *D) {
if (const auto *OCD = dyn_cast<ObjCContainerDecl>(D))
return getAllManglings(OCD);

if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D)))
return {};

const NamedDecl *ND = cast<NamedDecl>(D);

ASTContext &Ctx = ND->getASTContext();
std::unique_ptr<MangleContext> M(Ctx.createMangleContext());

std::vector<std::string> Manglings;

auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) {
auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false,
/*IsCSSMethod=*/true);
auto CC = MD->getType()->getAs<FunctionProtoType>()->getCallConv();
return CC == DefaultCC;
};

if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) {
Manglings.emplace_back(getMangledStructor(CD, Ctor_Base));

if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily())
if (!CD->getParent()->isAbstract())
Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete));

if (Ctx.getTargetInfo().getCXXABI().isMicrosoft())
if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor())
if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0))
Manglings.emplace_back(getMangledStructor(CD, Ctor_DefaultClosure));
} else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) {
Manglings.emplace_back(getMangledStructor(DD, Dtor_Base));
if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) {
Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete));
if (DD->isVirtual())
Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting));
}
} else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) {
Manglings.emplace_back(getName(ND));
if (MD->isVirtual())
if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD))
for (const auto &T : *TIV)
Manglings.emplace_back(getMangledThunk(MD, T));
}

return Manglings;
}

bool ASTNameGenerator::writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) {
if (MC->shouldMangleDeclName(D)) {
if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D))
MC->mangleCXXCtor(CtorD, Ctor_Complete, OS);
else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(D))
MC->mangleCXXDtor(DtorD, Dtor_Complete, OS);
else
MC->mangleName(D, OS);
return false;
} else {
IdentifierInfo *II = D->getIdentifier();
if (!II)
return true;
OS << II->getName();
return false;
}
}

void ASTNameGenerator::writeObjCClassName(const ObjCInterfaceDecl *D,
raw_ostream &OS) {
OS << getClassSymbolPrefix(ObjCClass, D->getASTContext());
OS << D->getObjCRuntimeNameAsString();
}

std::string ASTNameGenerator::getMangledStructor(const NamedDecl *ND,
unsigned StructorType) {
std::string FrontendBuf;
llvm::raw_string_ostream FOS(FrontendBuf);

if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND))
MC->mangleCXXCtor(CD, static_cast<CXXCtorType>(StructorType), FOS);
else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND))
MC->mangleCXXDtor(DD, static_cast<CXXDtorType>(StructorType), FOS);

std::string BackendBuf;
llvm::raw_string_ostream BOS(BackendBuf);

llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);

return BOS.str();
}

std::string ASTNameGenerator::getMangledThunk(const CXXMethodDecl *MD,
const ThunkInfo &T) {
std::string FrontendBuf;
llvm::raw_string_ostream FOS(FrontendBuf);

MC->mangleThunk(MD, T, FOS);

std::string BackendBuf;
llvm::raw_string_ostream BOS(BackendBuf);

llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL);

return BOS.str();
}

0 comments on commit 3ff8c3b

Please sign in to comment.