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