//===- CodegenNameGenerator.cpp - Codegen name generation -----------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Determines the name that the symbol will get for code generation. // //===----------------------------------------------------------------------===// #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().getDataLayoutString()) {} 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; } std::vector getAllManglings(const Decl *D) { if (!(isa(D) || isa(D))) return {}; const NamedDecl *ND = cast(D); ASTContext &Ctx = ND->getASTContext(); std::unique_ptr M(Ctx.createMangleContext()); std::unique_ptr DL( new llvm::DataLayout(Ctx.getTargetInfo().getDataLayoutString())); 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(); OS << D->getObjCRuntimeNameAsString(); } static StringRef getClassSymbolPrefix() { return "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)) { } CodegenNameGenerator::~CodegenNameGenerator() { } bool CodegenNameGenerator::writeName(const Decl *D, raw_ostream &OS) { return Impl->writeName(D, OS); } std::string CodegenNameGenerator::getName(const Decl *D) { return Impl->getName(D); } std::vector CodegenNameGenerator::getAllManglings(const Decl *D) { return Impl->getAllManglings(D); }