From 3ff8c3b73f6d9e1920aa4169f42aa7a0fd8cd5af Mon Sep 17 00:00:00 2001 From: Puyan Lotfi Date: Wed, 19 Jun 2019 20:51:35 +0000 Subject: [PATCH] [clang][AST] ASTNameGenerator: A refactoring of CodegenNameGeneratorImpl (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 --- clang/include/clang/AST/Mangle.h | 19 ++ .../clang/Index/CodegenNameGenerator.h | 3 +- clang/lib/AST/CMakeLists.txt | 1 + clang/lib/AST/Mangle.cpp | 183 +++++++++++++++++ clang/lib/Index/CodegenNameGenerator.cpp | 193 +----------------- 5 files changed, 206 insertions(+), 193 deletions(-) diff --git a/clang/include/clang/AST/Mangle.h b/clang/include/clang/AST/Mangle.h index fb53fbee8a06..a4714adfd745 100644 --- a/clang/include/clang/AST/Mangle.h +++ b/clang/include/clang/AST/Mangle.h @@ -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 { @@ -243,6 +244,24 @@ public: static MicrosoftMangleContext *create(ASTContext &Context, DiagnosticsEngine &Diags); }; + +class ASTNameGenerator { + std::unique_ptr 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 getAllManglings(const Decl *D); + +private: + std::vector 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 diff --git a/clang/include/clang/Index/CodegenNameGenerator.h b/clang/include/clang/Index/CodegenNameGenerator.h index d2528a10c973..98b3a5de817a 100644 --- a/clang/include/clang/Index/CodegenNameGenerator.h +++ b/clang/include/clang/Index/CodegenNameGenerator.h @@ -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 #include @@ -42,7 +43,7 @@ public: private: struct Implementation; - std::unique_ptr Impl; + std::unique_ptr Impl; }; } // namespace index diff --git a/clang/lib/AST/CMakeLists.txt b/clang/lib/AST/CMakeLists.txt index a7c50bec11a4..64ad029ccea4 100644 --- a/clang/lib/AST/CMakeLists.txt +++ b/clang/lib/AST/CMakeLists.txt @@ -1,5 +1,6 @@ set(LLVM_LINK_COMPONENTS BinaryFormat + Core Support ) diff --git a/clang/lib/AST/Mangle.cpp b/clang/lib/AST/Mangle.cpp index 03ebf98a7f16..ec3b6868a3f6 100644 --- a/clang/lib/AST/Mangle.cpp +++ b/clang/lib/AST/Mangle.cpp @@ -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" @@ -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(D)) { + if (FD->isDependentContext()) + return true; + if (writeFuncOrVarName(FD, FrontendBufOS)) + return true; + } else if (auto *VD = dyn_cast(D)) { + if (writeFuncOrVarName(VD, FrontendBufOS)) + return true; + } else if (auto *MD = dyn_cast(D)) { + MC->mangleObjCMethodNameWithoutSize(MD, OS); + return false; + } else if (auto *ID = dyn_cast(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 +ASTNameGenerator::getAllManglings(const ObjCContainerDecl *OCD) { + StringRef ClassName; + if (const auto *OID = dyn_cast(OCD)) + ClassName = OID->getObjCRuntimeNameAsString(); + else if (const auto *OID = dyn_cast(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 ASTNameGenerator::getAllManglings(const Decl *D) { + if (const auto *OCD = dyn_cast(D)) + return getAllManglings(OCD); + + if (!(isa(D) || isa(D))) + return {}; + + const NamedDecl *ND = cast(D); + + ASTContext &Ctx = ND->getASTContext(); + std::unique_ptr M(Ctx.createMangleContext()); + + std::vector Manglings; + + auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) { + auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false, + /*IsCSSMethod=*/true); + auto CC = MD->getType()->getAs()->getCallConv(); + return CC == DefaultCC; + }; + + if (const auto *CD = dyn_cast_or_null(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() && 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(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(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(D)) + MC->mangleCXXCtor(CtorD, Ctor_Complete, OS); + else if (const auto *DtorD = dyn_cast(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(ND)) + MC->mangleCXXCtor(CD, static_cast(StructorType), FOS); + else if (const auto *DD = dyn_cast_or_null(ND)) + MC->mangleCXXDtor(DD, static_cast(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(); +} diff --git a/clang/lib/Index/CodegenNameGenerator.cpp b/clang/lib/Index/CodegenNameGenerator.cpp index b56d769331a3..56d3d0603486 100644 --- a/clang/lib/Index/CodegenNameGenerator.cpp +++ b/clang/lib/Index/CodegenNameGenerator.cpp @@ -12,203 +12,12 @@ #include "clang/Index/CodegenNameGenerator.h" #include "clang/AST/ASTContext.h" -#include "clang/AST/DeclCXX.h" -#include "clang/AST/DeclObjC.h" -#include "clang/AST/Mangle.h" -#include "clang/AST/VTableBuilder.h" -#include "clang/Basic/TargetInfo.h" -#include "llvm/IR/DataLayout.h" -#include "llvm/IR/Mangler.h" -#include "llvm/Support/raw_ostream.h" using namespace clang; using namespace clang::index; -struct CodegenNameGenerator::Implementation { - std::unique_ptr MC; - llvm::DataLayout DL; - - Implementation(ASTContext &Ctx) - : MC(Ctx.createMangleContext()), - DL(Ctx.getTargetInfo().getDataLayout()) {} - - bool 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(D)) { - if (FD->isDependentContext()) - return true; - if (writeFuncOrVarName(FD, FrontendBufOS)) - return true; - } else if (auto *VD = dyn_cast(D)) { - if (writeFuncOrVarName(VD, FrontendBufOS)) - return true; - } else if (auto *MD = dyn_cast(D)) { - MC->mangleObjCMethodNameWithoutSize(MD, OS); - return false; - } else if (auto *ID = dyn_cast(D)) { - writeObjCClassName(ID, FrontendBufOS); - } else { - return true; - } - - // Now apply backend mangling. - llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL); - return false; - } - - std::string getName(const Decl *D) { - std::string Name; - { - llvm::raw_string_ostream OS(Name); - writeName(D, OS); - } - return Name; - } - - enum ObjCKind { - ObjCClass, - ObjCMetaclass, - }; - - std::vector getAllManglings(const ObjCContainerDecl *OCD) { - StringRef ClassName; - if (const auto *OID = dyn_cast(OCD)) - ClassName = OID->getObjCRuntimeNameAsString(); - else if (const auto *OID = dyn_cast(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 getAllManglings(const Decl *D) { - if (const auto *OCD = dyn_cast(D)) - return getAllManglings(OCD); - - if (!(isa(D) || isa(D))) - return {}; - - const NamedDecl *ND = cast(D); - - ASTContext &Ctx = ND->getASTContext(); - std::unique_ptr M(Ctx.createMangleContext()); - - std::vector Manglings; - - auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) { - auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false, - /*IsCSSMethod=*/true); - auto CC = MD->getType()->getAs()->getCallConv(); - return CC == DefaultCC; - }; - - if (const auto *CD = dyn_cast_or_null(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() && 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(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(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; - } - -private: - bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) { - if (MC->shouldMangleDeclName(D)) { - if (const auto *CtorD = dyn_cast(D)) - MC->mangleCXXCtor(CtorD, Ctor_Complete, OS); - else if (const auto *DtorD = dyn_cast(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 writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) { - OS << getClassSymbolPrefix(ObjCClass, D->getASTContext()); - OS << D->getObjCRuntimeNameAsString(); - } - - 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::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) { - std::string FrontendBuf; - llvm::raw_string_ostream FOS(FrontendBuf); - - if (const auto *CD = dyn_cast_or_null(ND)) - MC->mangleCXXCtor(CD, static_cast(StructorType), FOS); - else if (const auto *DD = dyn_cast_or_null(ND)) - MC->mangleCXXDtor(DD, static_cast(StructorType), FOS); - - std::string BackendBuf; - llvm::raw_string_ostream BOS(BackendBuf); - - llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL); - - return BOS.str(); - } - - std::string 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(); - } -}; - CodegenNameGenerator::CodegenNameGenerator(ASTContext &Ctx) - : Impl(new Implementation(Ctx)) { + : Impl(new ASTNameGenerator(Ctx)) { } CodegenNameGenerator::~CodegenNameGenerator() {