1*e7145dcbSDimitry Andric //===- CodegenNameGenerator.cpp - Codegen name generation -----------------===// 2*e7145dcbSDimitry Andric // 3*e7145dcbSDimitry Andric // The LLVM Compiler Infrastructure 4*e7145dcbSDimitry Andric // 5*e7145dcbSDimitry Andric // This file is distributed under the University of Illinois Open Source 6*e7145dcbSDimitry Andric // License. See LICENSE.TXT for details. 7*e7145dcbSDimitry Andric // 8*e7145dcbSDimitry Andric //===----------------------------------------------------------------------===// 9*e7145dcbSDimitry Andric // 10*e7145dcbSDimitry Andric // Determines the name that the symbol will get for code generation. 11*e7145dcbSDimitry Andric // 12*e7145dcbSDimitry Andric //===----------------------------------------------------------------------===// 13*e7145dcbSDimitry Andric 14*e7145dcbSDimitry Andric #include "clang/Index/CodegenNameGenerator.h" 15*e7145dcbSDimitry Andric #include "clang/AST/ASTContext.h" 16*e7145dcbSDimitry Andric #include "clang/AST/DeclCXX.h" 17*e7145dcbSDimitry Andric #include "clang/AST/DeclObjC.h" 18*e7145dcbSDimitry Andric #include "clang/AST/Mangle.h" 19*e7145dcbSDimitry Andric #include "clang/AST/VTableBuilder.h" 20*e7145dcbSDimitry Andric #include "clang/Basic/TargetInfo.h" 21*e7145dcbSDimitry Andric #include "llvm/IR/DataLayout.h" 22*e7145dcbSDimitry Andric #include "llvm/IR/Mangler.h" 23*e7145dcbSDimitry Andric #include "llvm/Support/raw_ostream.h" 24*e7145dcbSDimitry Andric 25*e7145dcbSDimitry Andric using namespace clang; 26*e7145dcbSDimitry Andric using namespace clang::index; 27*e7145dcbSDimitry Andric 28*e7145dcbSDimitry Andric struct CodegenNameGenerator::Implementation { 29*e7145dcbSDimitry Andric std::unique_ptr<MangleContext> MC; 30*e7145dcbSDimitry Andric llvm::DataLayout DL; 31*e7145dcbSDimitry Andric 32*e7145dcbSDimitry Andric Implementation(ASTContext &Ctx) 33*e7145dcbSDimitry Andric : MC(Ctx.createMangleContext()), 34*e7145dcbSDimitry Andric DL(Ctx.getTargetInfo().getDataLayout()) {} 35*e7145dcbSDimitry Andric 36*e7145dcbSDimitry Andric bool writeName(const Decl *D, raw_ostream &OS) { 37*e7145dcbSDimitry Andric // First apply frontend mangling. 38*e7145dcbSDimitry Andric SmallString<128> FrontendBuf; 39*e7145dcbSDimitry Andric llvm::raw_svector_ostream FrontendBufOS(FrontendBuf); 40*e7145dcbSDimitry Andric if (auto *FD = dyn_cast<FunctionDecl>(D)) { 41*e7145dcbSDimitry Andric if (FD->isDependentContext()) 42*e7145dcbSDimitry Andric return true; 43*e7145dcbSDimitry Andric if (writeFuncOrVarName(FD, FrontendBufOS)) 44*e7145dcbSDimitry Andric return true; 45*e7145dcbSDimitry Andric } else if (auto *VD = dyn_cast<VarDecl>(D)) { 46*e7145dcbSDimitry Andric if (writeFuncOrVarName(VD, FrontendBufOS)) 47*e7145dcbSDimitry Andric return true; 48*e7145dcbSDimitry Andric } else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) { 49*e7145dcbSDimitry Andric MC->mangleObjCMethodNameWithoutSize(MD, OS); 50*e7145dcbSDimitry Andric return false; 51*e7145dcbSDimitry Andric } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) { 52*e7145dcbSDimitry Andric writeObjCClassName(ID, FrontendBufOS); 53*e7145dcbSDimitry Andric } else { 54*e7145dcbSDimitry Andric return true; 55*e7145dcbSDimitry Andric } 56*e7145dcbSDimitry Andric 57*e7145dcbSDimitry Andric // Now apply backend mangling. 58*e7145dcbSDimitry Andric llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL); 59*e7145dcbSDimitry Andric return false; 60*e7145dcbSDimitry Andric } 61*e7145dcbSDimitry Andric 62*e7145dcbSDimitry Andric std::string getName(const Decl *D) { 63*e7145dcbSDimitry Andric std::string Name; 64*e7145dcbSDimitry Andric { 65*e7145dcbSDimitry Andric llvm::raw_string_ostream OS(Name); 66*e7145dcbSDimitry Andric writeName(D, OS); 67*e7145dcbSDimitry Andric } 68*e7145dcbSDimitry Andric return Name; 69*e7145dcbSDimitry Andric } 70*e7145dcbSDimitry Andric 71*e7145dcbSDimitry Andric std::vector<std::string> getAllManglings(const Decl *D) { 72*e7145dcbSDimitry Andric if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D))) 73*e7145dcbSDimitry Andric return {}; 74*e7145dcbSDimitry Andric 75*e7145dcbSDimitry Andric const NamedDecl *ND = cast<NamedDecl>(D); 76*e7145dcbSDimitry Andric 77*e7145dcbSDimitry Andric ASTContext &Ctx = ND->getASTContext(); 78*e7145dcbSDimitry Andric std::unique_ptr<MangleContext> M(Ctx.createMangleContext()); 79*e7145dcbSDimitry Andric 80*e7145dcbSDimitry Andric std::vector<std::string> Manglings; 81*e7145dcbSDimitry Andric 82*e7145dcbSDimitry Andric auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) { 83*e7145dcbSDimitry Andric auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false, 84*e7145dcbSDimitry Andric /*IsCSSMethod=*/true); 85*e7145dcbSDimitry Andric auto CC = MD->getType()->getAs<FunctionProtoType>()->getCallConv(); 86*e7145dcbSDimitry Andric return CC == DefaultCC; 87*e7145dcbSDimitry Andric }; 88*e7145dcbSDimitry Andric 89*e7145dcbSDimitry Andric if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) { 90*e7145dcbSDimitry Andric Manglings.emplace_back(getMangledStructor(CD, Ctor_Base)); 91*e7145dcbSDimitry Andric 92*e7145dcbSDimitry Andric if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) 93*e7145dcbSDimitry Andric if (!CD->getParent()->isAbstract()) 94*e7145dcbSDimitry Andric Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete)); 95*e7145dcbSDimitry Andric 96*e7145dcbSDimitry Andric if (Ctx.getTargetInfo().getCXXABI().isMicrosoft()) 97*e7145dcbSDimitry Andric if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor()) 98*e7145dcbSDimitry Andric if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0)) 99*e7145dcbSDimitry Andric Manglings.emplace_back(getMangledStructor(CD, Ctor_DefaultClosure)); 100*e7145dcbSDimitry Andric } else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) { 101*e7145dcbSDimitry Andric Manglings.emplace_back(getMangledStructor(DD, Dtor_Base)); 102*e7145dcbSDimitry Andric if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) { 103*e7145dcbSDimitry Andric Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete)); 104*e7145dcbSDimitry Andric if (DD->isVirtual()) 105*e7145dcbSDimitry Andric Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting)); 106*e7145dcbSDimitry Andric } 107*e7145dcbSDimitry Andric } else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) { 108*e7145dcbSDimitry Andric Manglings.emplace_back(getName(ND)); 109*e7145dcbSDimitry Andric if (MD->isVirtual()) 110*e7145dcbSDimitry Andric if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD)) 111*e7145dcbSDimitry Andric for (const auto &T : *TIV) 112*e7145dcbSDimitry Andric Manglings.emplace_back(getMangledThunk(MD, T)); 113*e7145dcbSDimitry Andric } 114*e7145dcbSDimitry Andric 115*e7145dcbSDimitry Andric return Manglings; 116*e7145dcbSDimitry Andric } 117*e7145dcbSDimitry Andric 118*e7145dcbSDimitry Andric private: 119*e7145dcbSDimitry Andric bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) { 120*e7145dcbSDimitry Andric if (MC->shouldMangleDeclName(D)) { 121*e7145dcbSDimitry Andric if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D)) 122*e7145dcbSDimitry Andric MC->mangleCXXCtor(CtorD, Ctor_Complete, OS); 123*e7145dcbSDimitry Andric else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(D)) 124*e7145dcbSDimitry Andric MC->mangleCXXDtor(DtorD, Dtor_Complete, OS); 125*e7145dcbSDimitry Andric else 126*e7145dcbSDimitry Andric MC->mangleName(D, OS); 127*e7145dcbSDimitry Andric return false; 128*e7145dcbSDimitry Andric } else { 129*e7145dcbSDimitry Andric IdentifierInfo *II = D->getIdentifier(); 130*e7145dcbSDimitry Andric if (!II) 131*e7145dcbSDimitry Andric return true; 132*e7145dcbSDimitry Andric OS << II->getName(); 133*e7145dcbSDimitry Andric return false; 134*e7145dcbSDimitry Andric } 135*e7145dcbSDimitry Andric } 136*e7145dcbSDimitry Andric 137*e7145dcbSDimitry Andric void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) { 138*e7145dcbSDimitry Andric OS << getClassSymbolPrefix(); 139*e7145dcbSDimitry Andric OS << D->getObjCRuntimeNameAsString(); 140*e7145dcbSDimitry Andric } 141*e7145dcbSDimitry Andric 142*e7145dcbSDimitry Andric static StringRef getClassSymbolPrefix() { 143*e7145dcbSDimitry Andric return "OBJC_CLASS_$_"; 144*e7145dcbSDimitry Andric } 145*e7145dcbSDimitry Andric 146*e7145dcbSDimitry Andric std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) { 147*e7145dcbSDimitry Andric std::string FrontendBuf; 148*e7145dcbSDimitry Andric llvm::raw_string_ostream FOS(FrontendBuf); 149*e7145dcbSDimitry Andric 150*e7145dcbSDimitry Andric if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) 151*e7145dcbSDimitry Andric MC->mangleCXXCtor(CD, static_cast<CXXCtorType>(StructorType), FOS); 152*e7145dcbSDimitry Andric else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) 153*e7145dcbSDimitry Andric MC->mangleCXXDtor(DD, static_cast<CXXDtorType>(StructorType), FOS); 154*e7145dcbSDimitry Andric 155*e7145dcbSDimitry Andric std::string BackendBuf; 156*e7145dcbSDimitry Andric llvm::raw_string_ostream BOS(BackendBuf); 157*e7145dcbSDimitry Andric 158*e7145dcbSDimitry Andric llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL); 159*e7145dcbSDimitry Andric 160*e7145dcbSDimitry Andric return BOS.str(); 161*e7145dcbSDimitry Andric } 162*e7145dcbSDimitry Andric 163*e7145dcbSDimitry Andric std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T) { 164*e7145dcbSDimitry Andric std::string FrontendBuf; 165*e7145dcbSDimitry Andric llvm::raw_string_ostream FOS(FrontendBuf); 166*e7145dcbSDimitry Andric 167*e7145dcbSDimitry Andric MC->mangleThunk(MD, T, FOS); 168*e7145dcbSDimitry Andric 169*e7145dcbSDimitry Andric std::string BackendBuf; 170*e7145dcbSDimitry Andric llvm::raw_string_ostream BOS(BackendBuf); 171*e7145dcbSDimitry Andric 172*e7145dcbSDimitry Andric llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL); 173*e7145dcbSDimitry Andric 174*e7145dcbSDimitry Andric return BOS.str(); 175*e7145dcbSDimitry Andric } 176*e7145dcbSDimitry Andric }; 177*e7145dcbSDimitry Andric 178*e7145dcbSDimitry Andric CodegenNameGenerator::CodegenNameGenerator(ASTContext &Ctx) 179*e7145dcbSDimitry Andric : Impl(new Implementation(Ctx)) { 180*e7145dcbSDimitry Andric } 181*e7145dcbSDimitry Andric 182*e7145dcbSDimitry Andric CodegenNameGenerator::~CodegenNameGenerator() { 183*e7145dcbSDimitry Andric } 184*e7145dcbSDimitry Andric 185*e7145dcbSDimitry Andric bool CodegenNameGenerator::writeName(const Decl *D, raw_ostream &OS) { 186*e7145dcbSDimitry Andric return Impl->writeName(D, OS); 187*e7145dcbSDimitry Andric } 188*e7145dcbSDimitry Andric 189*e7145dcbSDimitry Andric std::string CodegenNameGenerator::getName(const Decl *D) { 190*e7145dcbSDimitry Andric return Impl->getName(D); 191*e7145dcbSDimitry Andric } 192*e7145dcbSDimitry Andric 193*e7145dcbSDimitry Andric std::vector<std::string> CodegenNameGenerator::getAllManglings(const Decl *D) { 194*e7145dcbSDimitry Andric return Impl->getAllManglings(D); 195*e7145dcbSDimitry Andric } 196