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