1 1.1 joerg //===--- Mangle.cpp - Mangle C++ Names --------------------------*- C++ -*-===// 2 1.1 joerg // 3 1.1 joerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 1.1 joerg // See https://llvm.org/LICENSE.txt for license information. 5 1.1 joerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 1.1 joerg // 7 1.1 joerg //===----------------------------------------------------------------------===// 8 1.1 joerg // 9 1.1 joerg // Implements generic name mangling support for blocks and Objective-C. 10 1.1 joerg // 11 1.1 joerg //===----------------------------------------------------------------------===// 12 1.1 joerg #include "clang/AST/Attr.h" 13 1.1 joerg #include "clang/AST/ASTContext.h" 14 1.1 joerg #include "clang/AST/Decl.h" 15 1.1 joerg #include "clang/AST/DeclCXX.h" 16 1.1 joerg #include "clang/AST/DeclObjC.h" 17 1.1 joerg #include "clang/AST/DeclTemplate.h" 18 1.1 joerg #include "clang/AST/ExprCXX.h" 19 1.1 joerg #include "clang/AST/Mangle.h" 20 1.1 joerg #include "clang/AST/VTableBuilder.h" 21 1.1 joerg #include "clang/Basic/ABI.h" 22 1.1 joerg #include "clang/Basic/SourceManager.h" 23 1.1 joerg #include "clang/Basic/TargetInfo.h" 24 1.1 joerg #include "llvm/ADT/StringExtras.h" 25 1.1 joerg #include "llvm/IR/DataLayout.h" 26 1.1 joerg #include "llvm/IR/Mangler.h" 27 1.1 joerg #include "llvm/Support/ErrorHandling.h" 28 1.1.1.2 joerg #include "llvm/Support/Format.h" 29 1.1 joerg #include "llvm/Support/raw_ostream.h" 30 1.1 joerg 31 1.1 joerg using namespace clang; 32 1.1 joerg 33 1.1 joerg // FIXME: For blocks we currently mimic GCC's mangling scheme, which leaves 34 1.1 joerg // much to be desired. Come up with a better mangling scheme. 35 1.1 joerg 36 1.1 joerg static void mangleFunctionBlock(MangleContext &Context, 37 1.1 joerg StringRef Outer, 38 1.1 joerg const BlockDecl *BD, 39 1.1 joerg raw_ostream &Out) { 40 1.1 joerg unsigned discriminator = Context.getBlockId(BD, true); 41 1.1 joerg if (discriminator == 0) 42 1.1 joerg Out << "__" << Outer << "_block_invoke"; 43 1.1 joerg else 44 1.1 joerg Out << "__" << Outer << "_block_invoke_" << discriminator+1; 45 1.1 joerg } 46 1.1 joerg 47 1.1 joerg void MangleContext::anchor() { } 48 1.1 joerg 49 1.1 joerg enum CCMangling { 50 1.1 joerg CCM_Other, 51 1.1 joerg CCM_Fast, 52 1.1 joerg CCM_RegCall, 53 1.1 joerg CCM_Vector, 54 1.1.1.2 joerg CCM_Std, 55 1.1.1.2 joerg CCM_WasmMainArgcArgv 56 1.1 joerg }; 57 1.1 joerg 58 1.1 joerg static bool isExternC(const NamedDecl *ND) { 59 1.1 joerg if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) 60 1.1 joerg return FD->isExternC(); 61 1.1.1.2 joerg if (const VarDecl *VD = dyn_cast<VarDecl>(ND)) 62 1.1.1.2 joerg return VD->isExternC(); 63 1.1.1.2 joerg return false; 64 1.1 joerg } 65 1.1 joerg 66 1.1 joerg static CCMangling getCallingConvMangling(const ASTContext &Context, 67 1.1 joerg const NamedDecl *ND) { 68 1.1 joerg const TargetInfo &TI = Context.getTargetInfo(); 69 1.1 joerg const llvm::Triple &Triple = TI.getTriple(); 70 1.1.1.2 joerg 71 1.1.1.2 joerg // On wasm, the argc/argv form of "main" is renamed so that the startup code 72 1.1.1.2 joerg // can call it with the correct function signature. 73 1.1.1.2 joerg // On Emscripten, users may be exporting "main" and expecting to call it 74 1.1.1.2 joerg // themselves, so we can't mangle it. 75 1.1.1.2 joerg if (Triple.isWasm() && !Triple.isOSEmscripten()) 76 1.1.1.2 joerg if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND)) 77 1.1.1.2 joerg if (FD->isMain() && FD->hasPrototype() && FD->param_size() == 2) 78 1.1.1.2 joerg return CCM_WasmMainArgcArgv; 79 1.1.1.2 joerg 80 1.1.1.2 joerg if (!Triple.isOSWindows() || !Triple.isX86()) 81 1.1 joerg return CCM_Other; 82 1.1 joerg 83 1.1 joerg if (Context.getLangOpts().CPlusPlus && !isExternC(ND) && 84 1.1 joerg TI.getCXXABI() == TargetCXXABI::Microsoft) 85 1.1 joerg return CCM_Other; 86 1.1 joerg 87 1.1 joerg const FunctionDecl *FD = dyn_cast<FunctionDecl>(ND); 88 1.1 joerg if (!FD) 89 1.1 joerg return CCM_Other; 90 1.1 joerg QualType T = FD->getType(); 91 1.1 joerg 92 1.1 joerg const FunctionType *FT = T->castAs<FunctionType>(); 93 1.1 joerg 94 1.1 joerg CallingConv CC = FT->getCallConv(); 95 1.1 joerg switch (CC) { 96 1.1 joerg default: 97 1.1 joerg return CCM_Other; 98 1.1 joerg case CC_X86FastCall: 99 1.1 joerg return CCM_Fast; 100 1.1 joerg case CC_X86StdCall: 101 1.1 joerg return CCM_Std; 102 1.1 joerg case CC_X86VectorCall: 103 1.1 joerg return CCM_Vector; 104 1.1 joerg } 105 1.1 joerg } 106 1.1 joerg 107 1.1 joerg bool MangleContext::shouldMangleDeclName(const NamedDecl *D) { 108 1.1 joerg const ASTContext &ASTContext = getASTContext(); 109 1.1 joerg 110 1.1 joerg CCMangling CC = getCallingConvMangling(ASTContext, D); 111 1.1 joerg if (CC != CCM_Other) 112 1.1 joerg return true; 113 1.1 joerg 114 1.1 joerg // If the declaration has an owning module for linkage purposes that needs to 115 1.1 joerg // be mangled, we must mangle its name. 116 1.1 joerg if (!D->hasExternalFormalLinkage() && D->getOwningModuleForLinkage()) 117 1.1 joerg return true; 118 1.1 joerg 119 1.1.1.2 joerg // C functions with internal linkage have to be mangled with option 120 1.1.1.2 joerg // -funique-internal-linkage-names. 121 1.1.1.2 joerg if (!getASTContext().getLangOpts().CPlusPlus && 122 1.1.1.2 joerg isUniqueInternalLinkageDecl(D)) 123 1.1.1.2 joerg return true; 124 1.1.1.2 joerg 125 1.1 joerg // In C, functions with no attributes never need to be mangled. Fastpath them. 126 1.1 joerg if (!getASTContext().getLangOpts().CPlusPlus && !D->hasAttrs()) 127 1.1 joerg return false; 128 1.1 joerg 129 1.1 joerg // Any decl can be declared with __asm("foo") on it, and this takes precedence 130 1.1 joerg // over all other naming in the .o file. 131 1.1 joerg if (D->hasAttr<AsmLabelAttr>()) 132 1.1 joerg return true; 133 1.1 joerg 134 1.1.1.2 joerg // Declarations that don't have identifier names always need to be mangled. 135 1.1.1.2 joerg if (isa<MSGuidDecl>(D)) 136 1.1.1.2 joerg return true; 137 1.1.1.2 joerg 138 1.1 joerg return shouldMangleCXXName(D); 139 1.1 joerg } 140 1.1 joerg 141 1.1.1.2 joerg void MangleContext::mangleName(GlobalDecl GD, raw_ostream &Out) { 142 1.1.1.2 joerg const ASTContext &ASTContext = getASTContext(); 143 1.1.1.2 joerg const NamedDecl *D = cast<NamedDecl>(GD.getDecl()); 144 1.1.1.2 joerg 145 1.1 joerg // Any decl can be declared with __asm("foo") on it, and this takes precedence 146 1.1 joerg // over all other naming in the .o file. 147 1.1 joerg if (const AsmLabelAttr *ALA = D->getAttr<AsmLabelAttr>()) { 148 1.1 joerg // If we have an asm name, then we use it as the mangling. 149 1.1 joerg 150 1.1 joerg // If the label isn't literal, or if this is an alias for an LLVM intrinsic, 151 1.1 joerg // do not add a "\01" prefix. 152 1.1 joerg if (!ALA->getIsLiteralLabel() || ALA->getLabel().startswith("llvm.")) { 153 1.1 joerg Out << ALA->getLabel(); 154 1.1 joerg return; 155 1.1 joerg } 156 1.1 joerg 157 1.1 joerg // Adding the prefix can cause problems when one file has a "foo" and 158 1.1 joerg // another has a "\01foo". That is known to happen on ELF with the 159 1.1 joerg // tricks normally used for producing aliases (PR9177). Fortunately the 160 1.1 joerg // llvm mangler on ELF is a nop, so we can just avoid adding the \01 161 1.1 joerg // marker. 162 1.1.1.2 joerg StringRef UserLabelPrefix = 163 1.1.1.2 joerg getASTContext().getTargetInfo().getUserLabelPrefix(); 164 1.1.1.2 joerg #ifndef NDEBUG 165 1.1 joerg char GlobalPrefix = 166 1.1.1.2 joerg llvm::DataLayout(getASTContext().getTargetInfo().getDataLayoutString()) 167 1.1.1.2 joerg .getGlobalPrefix(); 168 1.1.1.2 joerg assert((UserLabelPrefix.empty() && !GlobalPrefix) || 169 1.1.1.2 joerg (UserLabelPrefix.size() == 1 && UserLabelPrefix[0] == GlobalPrefix)); 170 1.1.1.2 joerg #endif 171 1.1.1.2 joerg if (!UserLabelPrefix.empty()) 172 1.1 joerg Out << '\01'; // LLVM IR Marker for __asm("foo") 173 1.1 joerg 174 1.1 joerg Out << ALA->getLabel(); 175 1.1 joerg return; 176 1.1 joerg } 177 1.1 joerg 178 1.1.1.2 joerg if (auto *GD = dyn_cast<MSGuidDecl>(D)) 179 1.1.1.2 joerg return mangleMSGuidDecl(GD, Out); 180 1.1.1.2 joerg 181 1.1 joerg CCMangling CC = getCallingConvMangling(ASTContext, D); 182 1.1.1.2 joerg 183 1.1.1.2 joerg if (CC == CCM_WasmMainArgcArgv) { 184 1.1.1.2 joerg Out << "__main_argc_argv"; 185 1.1.1.2 joerg return; 186 1.1.1.2 joerg } 187 1.1.1.2 joerg 188 1.1 joerg bool MCXX = shouldMangleCXXName(D); 189 1.1 joerg const TargetInfo &TI = Context.getTargetInfo(); 190 1.1 joerg if (CC == CCM_Other || (MCXX && TI.getCXXABI() == TargetCXXABI::Microsoft)) { 191 1.1 joerg if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) 192 1.1.1.2 joerg mangleObjCMethodNameAsSourceName(OMD, Out); 193 1.1 joerg else 194 1.1.1.2 joerg mangleCXXName(GD, Out); 195 1.1 joerg return; 196 1.1 joerg } 197 1.1 joerg 198 1.1 joerg Out << '\01'; 199 1.1 joerg if (CC == CCM_Std) 200 1.1 joerg Out << '_'; 201 1.1 joerg else if (CC == CCM_Fast) 202 1.1 joerg Out << '@'; 203 1.1 joerg else if (CC == CCM_RegCall) 204 1.1 joerg Out << "__regcall3__"; 205 1.1 joerg 206 1.1 joerg if (!MCXX) 207 1.1 joerg Out << D->getIdentifier()->getName(); 208 1.1 joerg else if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) 209 1.1.1.2 joerg mangleObjCMethodNameAsSourceName(OMD, Out); 210 1.1 joerg else 211 1.1.1.2 joerg mangleCXXName(GD, Out); 212 1.1 joerg 213 1.1 joerg const FunctionDecl *FD = cast<FunctionDecl>(D); 214 1.1 joerg const FunctionType *FT = FD->getType()->castAs<FunctionType>(); 215 1.1 joerg const FunctionProtoType *Proto = dyn_cast<FunctionProtoType>(FT); 216 1.1 joerg if (CC == CCM_Vector) 217 1.1 joerg Out << '@'; 218 1.1 joerg Out << '@'; 219 1.1 joerg if (!Proto) { 220 1.1 joerg Out << '0'; 221 1.1 joerg return; 222 1.1 joerg } 223 1.1 joerg assert(!Proto->isVariadic()); 224 1.1 joerg unsigned ArgWords = 0; 225 1.1 joerg if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(FD)) 226 1.1 joerg if (!MD->isStatic()) 227 1.1 joerg ++ArgWords; 228 1.1 joerg for (const auto &AT : Proto->param_types()) 229 1.1 joerg // Size should be aligned to pointer size. 230 1.1 joerg ArgWords += 231 1.1 joerg llvm::alignTo(ASTContext.getTypeSize(AT), TI.getPointerWidth(0)) / 232 1.1 joerg TI.getPointerWidth(0); 233 1.1 joerg Out << ((TI.getPointerWidth(0) / 8) * ArgWords); 234 1.1 joerg } 235 1.1 joerg 236 1.1.1.2 joerg void MangleContext::mangleMSGuidDecl(const MSGuidDecl *GD, raw_ostream &Out) { 237 1.1.1.2 joerg // For now, follow the MSVC naming convention for GUID objects on all 238 1.1.1.2 joerg // targets. 239 1.1.1.2 joerg MSGuidDecl::Parts P = GD->getParts(); 240 1.1.1.2 joerg Out << llvm::format("_GUID_%08" PRIx32 "_%04" PRIx32 "_%04" PRIx32 "_", 241 1.1.1.2 joerg P.Part1, P.Part2, P.Part3); 242 1.1.1.2 joerg unsigned I = 0; 243 1.1.1.2 joerg for (uint8_t C : P.Part4And5) { 244 1.1.1.2 joerg Out << llvm::format("%02" PRIx8, C); 245 1.1.1.2 joerg if (++I == 2) 246 1.1.1.2 joerg Out << "_"; 247 1.1.1.2 joerg } 248 1.1.1.2 joerg } 249 1.1.1.2 joerg 250 1.1 joerg void MangleContext::mangleGlobalBlock(const BlockDecl *BD, 251 1.1 joerg const NamedDecl *ID, 252 1.1 joerg raw_ostream &Out) { 253 1.1 joerg unsigned discriminator = getBlockId(BD, false); 254 1.1 joerg if (ID) { 255 1.1 joerg if (shouldMangleDeclName(ID)) 256 1.1 joerg mangleName(ID, Out); 257 1.1 joerg else { 258 1.1 joerg Out << ID->getIdentifier()->getName(); 259 1.1 joerg } 260 1.1 joerg } 261 1.1 joerg if (discriminator == 0) 262 1.1 joerg Out << "_block_invoke"; 263 1.1 joerg else 264 1.1 joerg Out << "_block_invoke_" << discriminator+1; 265 1.1 joerg } 266 1.1 joerg 267 1.1 joerg void MangleContext::mangleCtorBlock(const CXXConstructorDecl *CD, 268 1.1 joerg CXXCtorType CT, const BlockDecl *BD, 269 1.1 joerg raw_ostream &ResStream) { 270 1.1 joerg SmallString<64> Buffer; 271 1.1 joerg llvm::raw_svector_ostream Out(Buffer); 272 1.1.1.2 joerg mangleName(GlobalDecl(CD, CT), Out); 273 1.1 joerg mangleFunctionBlock(*this, Buffer, BD, ResStream); 274 1.1 joerg } 275 1.1 joerg 276 1.1 joerg void MangleContext::mangleDtorBlock(const CXXDestructorDecl *DD, 277 1.1 joerg CXXDtorType DT, const BlockDecl *BD, 278 1.1 joerg raw_ostream &ResStream) { 279 1.1 joerg SmallString<64> Buffer; 280 1.1 joerg llvm::raw_svector_ostream Out(Buffer); 281 1.1.1.2 joerg mangleName(GlobalDecl(DD, DT), Out); 282 1.1 joerg mangleFunctionBlock(*this, Buffer, BD, ResStream); 283 1.1 joerg } 284 1.1 joerg 285 1.1 joerg void MangleContext::mangleBlock(const DeclContext *DC, const BlockDecl *BD, 286 1.1 joerg raw_ostream &Out) { 287 1.1 joerg assert(!isa<CXXConstructorDecl>(DC) && !isa<CXXDestructorDecl>(DC)); 288 1.1 joerg 289 1.1 joerg SmallString<64> Buffer; 290 1.1 joerg llvm::raw_svector_ostream Stream(Buffer); 291 1.1 joerg if (const ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(DC)) { 292 1.1.1.2 joerg mangleObjCMethodNameAsSourceName(Method, Stream); 293 1.1 joerg } else { 294 1.1 joerg assert((isa<NamedDecl>(DC) || isa<BlockDecl>(DC)) && 295 1.1 joerg "expected a NamedDecl or BlockDecl"); 296 1.1 joerg if (isa<BlockDecl>(DC)) 297 1.1 joerg for (; DC && isa<BlockDecl>(DC); DC = DC->getParent()) 298 1.1 joerg (void) getBlockId(cast<BlockDecl>(DC), true); 299 1.1 joerg assert((isa<TranslationUnitDecl>(DC) || isa<NamedDecl>(DC)) && 300 1.1 joerg "expected a TranslationUnitDecl or a NamedDecl"); 301 1.1 joerg if (const auto *CD = dyn_cast<CXXConstructorDecl>(DC)) 302 1.1 joerg mangleCtorBlock(CD, /*CT*/ Ctor_Complete, BD, Out); 303 1.1 joerg else if (const auto *DD = dyn_cast<CXXDestructorDecl>(DC)) 304 1.1 joerg mangleDtorBlock(DD, /*DT*/ Dtor_Complete, BD, Out); 305 1.1 joerg else if (auto ND = dyn_cast<NamedDecl>(DC)) { 306 1.1 joerg if (!shouldMangleDeclName(ND) && ND->getIdentifier()) 307 1.1 joerg Stream << ND->getIdentifier()->getName(); 308 1.1 joerg else { 309 1.1 joerg // FIXME: We were doing a mangleUnqualifiedName() before, but that's 310 1.1 joerg // a private member of a class that will soon itself be private to the 311 1.1 joerg // Itanium C++ ABI object. What should we do now? Right now, I'm just 312 1.1 joerg // calling the mangleName() method on the MangleContext; is there a 313 1.1 joerg // better way? 314 1.1 joerg mangleName(ND, Stream); 315 1.1 joerg } 316 1.1 joerg } 317 1.1 joerg } 318 1.1 joerg mangleFunctionBlock(*this, Buffer, BD, Out); 319 1.1 joerg } 320 1.1 joerg 321 1.1.1.2 joerg void MangleContext::mangleObjCMethodName(const ObjCMethodDecl *MD, 322 1.1.1.2 joerg raw_ostream &OS, 323 1.1.1.2 joerg bool includePrefixByte, 324 1.1.1.2 joerg bool includeCategoryNamespace) { 325 1.1.1.2 joerg if (getASTContext().getLangOpts().ObjCRuntime.isGNUFamily()) { 326 1.1.1.2 joerg // This is the mangling we've always used on the GNU runtimes, but it 327 1.1.1.2 joerg // has obvious collisions in the face of underscores within class 328 1.1.1.2 joerg // names, category names, and selectors; maybe we should improve it. 329 1.1.1.2 joerg 330 1.1.1.2 joerg OS << (MD->isClassMethod() ? "_c_" : "_i_") 331 1.1.1.2 joerg << MD->getClassInterface()->getName() << '_'; 332 1.1.1.2 joerg 333 1.1.1.2 joerg if (includeCategoryNamespace) { 334 1.1.1.2 joerg if (auto category = MD->getCategory()) 335 1.1.1.2 joerg OS << category->getName(); 336 1.1.1.2 joerg } 337 1.1.1.2 joerg OS << '_'; 338 1.1.1.2 joerg 339 1.1.1.2 joerg auto selector = MD->getSelector(); 340 1.1.1.2 joerg for (unsigned slotIndex = 0, 341 1.1.1.2 joerg numArgs = selector.getNumArgs(), 342 1.1.1.2 joerg slotEnd = std::max(numArgs, 1U); 343 1.1.1.2 joerg slotIndex != slotEnd; ++slotIndex) { 344 1.1.1.2 joerg if (auto name = selector.getIdentifierInfoForSlot(slotIndex)) 345 1.1.1.2 joerg OS << name->getName(); 346 1.1.1.2 joerg 347 1.1.1.2 joerg // Replace all the positions that would've been ':' with '_'. 348 1.1.1.2 joerg // That's after each slot except that a unary selector doesn't 349 1.1.1.2 joerg // end in ':'. 350 1.1.1.2 joerg if (numArgs) 351 1.1.1.2 joerg OS << '_'; 352 1.1.1.2 joerg } 353 1.1.1.2 joerg 354 1.1.1.2 joerg return; 355 1.1.1.2 joerg } 356 1.1.1.2 joerg 357 1.1.1.2 joerg // \01+[ContainerName(CategoryName) SelectorName] 358 1.1.1.2 joerg if (includePrefixByte) { 359 1.1.1.2 joerg OS << '\01'; 360 1.1.1.2 joerg } 361 1.1 joerg OS << (MD->isInstanceMethod() ? '-' : '+') << '['; 362 1.1.1.2 joerg if (const auto *CID = MD->getCategory()) { 363 1.1 joerg OS << CID->getClassInterface()->getName(); 364 1.1.1.2 joerg if (includeCategoryNamespace) { 365 1.1.1.2 joerg OS << '(' << *CID << ')'; 366 1.1.1.2 joerg } 367 1.1.1.2 joerg } else if (const auto *CD = 368 1.1.1.2 joerg dyn_cast<ObjCContainerDecl>(MD->getDeclContext())) { 369 1.1 joerg OS << CD->getName(); 370 1.1.1.2 joerg } else { 371 1.1.1.2 joerg llvm_unreachable("Unexpected ObjC method decl context"); 372 1.1 joerg } 373 1.1 joerg OS << ' '; 374 1.1 joerg MD->getSelector().print(OS); 375 1.1 joerg OS << ']'; 376 1.1 joerg } 377 1.1 joerg 378 1.1.1.2 joerg void MangleContext::mangleObjCMethodNameAsSourceName(const ObjCMethodDecl *MD, 379 1.1.1.2 joerg raw_ostream &Out) { 380 1.1 joerg SmallString<64> Name; 381 1.1 joerg llvm::raw_svector_ostream OS(Name); 382 1.1 joerg 383 1.1.1.2 joerg mangleObjCMethodName(MD, OS, /*includePrefixByte=*/false, 384 1.1.1.2 joerg /*includeCategoryNamespace=*/true); 385 1.1 joerg Out << OS.str().size() << OS.str(); 386 1.1 joerg } 387 1.1 joerg 388 1.1 joerg class ASTNameGenerator::Implementation { 389 1.1 joerg std::unique_ptr<MangleContext> MC; 390 1.1 joerg llvm::DataLayout DL; 391 1.1 joerg 392 1.1 joerg public: 393 1.1 joerg explicit Implementation(ASTContext &Ctx) 394 1.1.1.2 joerg : MC(Ctx.createMangleContext()), 395 1.1.1.2 joerg DL(Ctx.getTargetInfo().getDataLayoutString()) {} 396 1.1 joerg 397 1.1 joerg bool writeName(const Decl *D, raw_ostream &OS) { 398 1.1 joerg // First apply frontend mangling. 399 1.1 joerg SmallString<128> FrontendBuf; 400 1.1 joerg llvm::raw_svector_ostream FrontendBufOS(FrontendBuf); 401 1.1 joerg if (auto *FD = dyn_cast<FunctionDecl>(D)) { 402 1.1 joerg if (FD->isDependentContext()) 403 1.1 joerg return true; 404 1.1 joerg if (writeFuncOrVarName(FD, FrontendBufOS)) 405 1.1 joerg return true; 406 1.1 joerg } else if (auto *VD = dyn_cast<VarDecl>(D)) { 407 1.1 joerg if (writeFuncOrVarName(VD, FrontendBufOS)) 408 1.1 joerg return true; 409 1.1 joerg } else if (auto *MD = dyn_cast<ObjCMethodDecl>(D)) { 410 1.1.1.2 joerg MC->mangleObjCMethodName(MD, OS, /*includePrefixByte=*/false, 411 1.1.1.2 joerg /*includeCategoryNamespace=*/true); 412 1.1 joerg return false; 413 1.1 joerg } else if (auto *ID = dyn_cast<ObjCInterfaceDecl>(D)) { 414 1.1 joerg writeObjCClassName(ID, FrontendBufOS); 415 1.1 joerg } else { 416 1.1 joerg return true; 417 1.1 joerg } 418 1.1 joerg 419 1.1 joerg // Now apply backend mangling. 420 1.1 joerg llvm::Mangler::getNameWithPrefix(OS, FrontendBufOS.str(), DL); 421 1.1 joerg return false; 422 1.1 joerg } 423 1.1 joerg 424 1.1 joerg std::string getName(const Decl *D) { 425 1.1 joerg std::string Name; 426 1.1 joerg { 427 1.1 joerg llvm::raw_string_ostream OS(Name); 428 1.1 joerg writeName(D, OS); 429 1.1 joerg } 430 1.1 joerg return Name; 431 1.1 joerg } 432 1.1 joerg 433 1.1 joerg enum ObjCKind { 434 1.1 joerg ObjCClass, 435 1.1 joerg ObjCMetaclass, 436 1.1 joerg }; 437 1.1 joerg 438 1.1 joerg static StringRef getClassSymbolPrefix(ObjCKind Kind, 439 1.1 joerg const ASTContext &Context) { 440 1.1 joerg if (Context.getLangOpts().ObjCRuntime.isGNUFamily()) 441 1.1 joerg return Kind == ObjCMetaclass ? "_OBJC_METACLASS_" : "_OBJC_CLASS_"; 442 1.1 joerg return Kind == ObjCMetaclass ? "OBJC_METACLASS_$_" : "OBJC_CLASS_$_"; 443 1.1 joerg } 444 1.1 joerg 445 1.1 joerg std::vector<std::string> getAllManglings(const ObjCContainerDecl *OCD) { 446 1.1 joerg StringRef ClassName; 447 1.1 joerg if (const auto *OID = dyn_cast<ObjCInterfaceDecl>(OCD)) 448 1.1 joerg ClassName = OID->getObjCRuntimeNameAsString(); 449 1.1 joerg else if (const auto *OID = dyn_cast<ObjCImplementationDecl>(OCD)) 450 1.1 joerg ClassName = OID->getObjCRuntimeNameAsString(); 451 1.1 joerg 452 1.1 joerg if (ClassName.empty()) 453 1.1 joerg return {}; 454 1.1 joerg 455 1.1 joerg auto Mangle = [&](ObjCKind Kind, StringRef ClassName) -> std::string { 456 1.1 joerg SmallString<40> Mangled; 457 1.1 joerg auto Prefix = getClassSymbolPrefix(Kind, OCD->getASTContext()); 458 1.1 joerg llvm::Mangler::getNameWithPrefix(Mangled, Prefix + ClassName, DL); 459 1.1.1.2 joerg return std::string(Mangled.str()); 460 1.1 joerg }; 461 1.1 joerg 462 1.1 joerg return { 463 1.1 joerg Mangle(ObjCClass, ClassName), 464 1.1 joerg Mangle(ObjCMetaclass, ClassName), 465 1.1 joerg }; 466 1.1 joerg } 467 1.1 joerg 468 1.1 joerg std::vector<std::string> getAllManglings(const Decl *D) { 469 1.1 joerg if (const auto *OCD = dyn_cast<ObjCContainerDecl>(D)) 470 1.1 joerg return getAllManglings(OCD); 471 1.1 joerg 472 1.1 joerg if (!(isa<CXXRecordDecl>(D) || isa<CXXMethodDecl>(D))) 473 1.1 joerg return {}; 474 1.1 joerg 475 1.1 joerg const NamedDecl *ND = cast<NamedDecl>(D); 476 1.1 joerg 477 1.1 joerg ASTContext &Ctx = ND->getASTContext(); 478 1.1 joerg std::unique_ptr<MangleContext> M(Ctx.createMangleContext()); 479 1.1 joerg 480 1.1 joerg std::vector<std::string> Manglings; 481 1.1 joerg 482 1.1 joerg auto hasDefaultCXXMethodCC = [](ASTContext &C, const CXXMethodDecl *MD) { 483 1.1 joerg auto DefaultCC = C.getDefaultCallingConvention(/*IsVariadic=*/false, 484 1.1 joerg /*IsCXXMethod=*/true); 485 1.1 joerg auto CC = MD->getType()->castAs<FunctionProtoType>()->getCallConv(); 486 1.1 joerg return CC == DefaultCC; 487 1.1 joerg }; 488 1.1 joerg 489 1.1 joerg if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) { 490 1.1 joerg Manglings.emplace_back(getMangledStructor(CD, Ctor_Base)); 491 1.1 joerg 492 1.1 joerg if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) 493 1.1 joerg if (!CD->getParent()->isAbstract()) 494 1.1 joerg Manglings.emplace_back(getMangledStructor(CD, Ctor_Complete)); 495 1.1 joerg 496 1.1 joerg if (Ctx.getTargetInfo().getCXXABI().isMicrosoft()) 497 1.1 joerg if (CD->hasAttr<DLLExportAttr>() && CD->isDefaultConstructor()) 498 1.1 joerg if (!(hasDefaultCXXMethodCC(Ctx, CD) && CD->getNumParams() == 0)) 499 1.1 joerg Manglings.emplace_back(getMangledStructor(CD, Ctor_DefaultClosure)); 500 1.1 joerg } else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) { 501 1.1 joerg Manglings.emplace_back(getMangledStructor(DD, Dtor_Base)); 502 1.1 joerg if (Ctx.getTargetInfo().getCXXABI().isItaniumFamily()) { 503 1.1 joerg Manglings.emplace_back(getMangledStructor(DD, Dtor_Complete)); 504 1.1 joerg if (DD->isVirtual()) 505 1.1 joerg Manglings.emplace_back(getMangledStructor(DD, Dtor_Deleting)); 506 1.1 joerg } 507 1.1 joerg } else if (const auto *MD = dyn_cast_or_null<CXXMethodDecl>(ND)) { 508 1.1 joerg Manglings.emplace_back(getName(ND)); 509 1.1 joerg if (MD->isVirtual()) 510 1.1 joerg if (const auto *TIV = Ctx.getVTableContext()->getThunkInfo(MD)) 511 1.1 joerg for (const auto &T : *TIV) 512 1.1 joerg Manglings.emplace_back(getMangledThunk(MD, T)); 513 1.1 joerg } 514 1.1 joerg 515 1.1 joerg return Manglings; 516 1.1 joerg } 517 1.1 joerg 518 1.1 joerg private: 519 1.1 joerg bool writeFuncOrVarName(const NamedDecl *D, raw_ostream &OS) { 520 1.1 joerg if (MC->shouldMangleDeclName(D)) { 521 1.1.1.2 joerg GlobalDecl GD; 522 1.1 joerg if (const auto *CtorD = dyn_cast<CXXConstructorDecl>(D)) 523 1.1.1.2 joerg GD = GlobalDecl(CtorD, Ctor_Complete); 524 1.1 joerg else if (const auto *DtorD = dyn_cast<CXXDestructorDecl>(D)) 525 1.1.1.2 joerg GD = GlobalDecl(DtorD, Dtor_Complete); 526 1.1.1.2 joerg else if (D->hasAttr<CUDAGlobalAttr>()) 527 1.1.1.2 joerg GD = GlobalDecl(cast<FunctionDecl>(D)); 528 1.1 joerg else 529 1.1.1.2 joerg GD = GlobalDecl(D); 530 1.1.1.2 joerg MC->mangleName(GD, OS); 531 1.1 joerg return false; 532 1.1 joerg } else { 533 1.1 joerg IdentifierInfo *II = D->getIdentifier(); 534 1.1 joerg if (!II) 535 1.1 joerg return true; 536 1.1 joerg OS << II->getName(); 537 1.1 joerg return false; 538 1.1 joerg } 539 1.1 joerg } 540 1.1 joerg 541 1.1 joerg void writeObjCClassName(const ObjCInterfaceDecl *D, raw_ostream &OS) { 542 1.1 joerg OS << getClassSymbolPrefix(ObjCClass, D->getASTContext()); 543 1.1 joerg OS << D->getObjCRuntimeNameAsString(); 544 1.1 joerg } 545 1.1 joerg 546 1.1 joerg std::string getMangledStructor(const NamedDecl *ND, unsigned StructorType) { 547 1.1 joerg std::string FrontendBuf; 548 1.1 joerg llvm::raw_string_ostream FOS(FrontendBuf); 549 1.1 joerg 550 1.1.1.2 joerg GlobalDecl GD; 551 1.1 joerg if (const auto *CD = dyn_cast_or_null<CXXConstructorDecl>(ND)) 552 1.1.1.2 joerg GD = GlobalDecl(CD, static_cast<CXXCtorType>(StructorType)); 553 1.1 joerg else if (const auto *DD = dyn_cast_or_null<CXXDestructorDecl>(ND)) 554 1.1.1.2 joerg GD = GlobalDecl(DD, static_cast<CXXDtorType>(StructorType)); 555 1.1.1.2 joerg MC->mangleName(GD, FOS); 556 1.1 joerg 557 1.1 joerg std::string BackendBuf; 558 1.1 joerg llvm::raw_string_ostream BOS(BackendBuf); 559 1.1 joerg 560 1.1 joerg llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL); 561 1.1 joerg 562 1.1 joerg return BOS.str(); 563 1.1 joerg } 564 1.1 joerg 565 1.1 joerg std::string getMangledThunk(const CXXMethodDecl *MD, const ThunkInfo &T) { 566 1.1 joerg std::string FrontendBuf; 567 1.1 joerg llvm::raw_string_ostream FOS(FrontendBuf); 568 1.1 joerg 569 1.1 joerg MC->mangleThunk(MD, T, FOS); 570 1.1 joerg 571 1.1 joerg std::string BackendBuf; 572 1.1 joerg llvm::raw_string_ostream BOS(BackendBuf); 573 1.1 joerg 574 1.1 joerg llvm::Mangler::getNameWithPrefix(BOS, FOS.str(), DL); 575 1.1 joerg 576 1.1 joerg return BOS.str(); 577 1.1 joerg } 578 1.1 joerg }; 579 1.1 joerg 580 1.1 joerg ASTNameGenerator::ASTNameGenerator(ASTContext &Ctx) 581 1.1 joerg : Impl(std::make_unique<Implementation>(Ctx)) {} 582 1.1 joerg 583 1.1 joerg ASTNameGenerator::~ASTNameGenerator() {} 584 1.1 joerg 585 1.1 joerg bool ASTNameGenerator::writeName(const Decl *D, raw_ostream &OS) { 586 1.1 joerg return Impl->writeName(D, OS); 587 1.1 joerg } 588 1.1 joerg 589 1.1 joerg std::string ASTNameGenerator::getName(const Decl *D) { 590 1.1 joerg return Impl->getName(D); 591 1.1 joerg } 592 1.1 joerg 593 1.1 joerg std::vector<std::string> ASTNameGenerator::getAllManglings(const Decl *D) { 594 1.1 joerg return Impl->getAllManglings(D); 595 1.1 joerg } 596