//===- UniqueInternalLinkageNames.cpp - Unique Internal Linkage Sym Names -===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // This file implements unique naming of internal linkage symbols with option // -funique-internal-linkage-symbols. // //===----------------------------------------------------------------------===// #include "llvm/Transforms/Utils/UniqueInternalLinkageNames.h" #include "llvm/ADT/SmallString.h" #include "llvm/IR/DebugInfoMetadata.h" #include "llvm/IR/MDBuilder.h" #include "llvm/IR/Module.h" #include "llvm/InitializePasses.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/MD5.h" #include "llvm/Transforms/Utils/ModuleUtils.h" using namespace llvm; static bool uniqueifyInternalLinkageNames(Module &M) { llvm::MD5 Md5; Md5.update(M.getSourceFileName()); llvm::MD5::MD5Result R; Md5.final(R); SmallString<32> Str; llvm::MD5::stringifyResult(R, Str); // Convert MD5hash to Decimal. Demangler suffixes can either contain numbers // or characters but not both. APInt IntHash = APInt(128, Str.str(), 16); // Prepend "__uniq" before the hash for tools like profilers to understand that // this symbol is of internal linkage type. std::string ModuleNameHash = (Twine(".__uniq.") + Twine(IntHash.toString(10, false))).str(); bool Changed = false; MDBuilder MDB(M.getContext()); // Append the module hash to all internal linkage functions. for (auto &F : M) { if (F.hasInternalLinkage()) { F.setName(F.getName() + ModuleNameHash); F.addFnAttr("sample-profile-suffix-elision-policy", "selected"); // Replace linkage names in the debug metadata. if (DISubprogram *SP = F.getSubprogram()) { if (SP->getRawLinkageName()) { auto *Name = MDB.createString(F.getName()); SP->replaceRawLinkageName(Name); if (DISubprogram *SPDecl = SP->getDeclaration()) { if (SPDecl->getRawLinkageName()) SPDecl->replaceRawLinkageName(Name); } } } Changed = true; } } // Append the module hash to all internal linkage globals. for (auto &GV : M.globals()) { if (GV.hasInternalLinkage()) { GV.setName(GV.getName() + ModuleNameHash); Changed = true; } } return Changed; } namespace { // Legacy pass that provides a name to every anon globals. class UniqueInternalLinkageNamesLegacyPass : public ModulePass { public: /// Pass identification, replacement for typeid static char ID; /// Specify pass name for debug output StringRef getPassName() const override { return "Unique Internal Linkage Names"; } explicit UniqueInternalLinkageNamesLegacyPass() : ModulePass(ID) { initializeUniqueInternalLinkageNamesLegacyPassPass( *PassRegistry::getPassRegistry()); } bool runOnModule(Module &M) override { return uniqueifyInternalLinkageNames(M); } }; char UniqueInternalLinkageNamesLegacyPass::ID = 0; } // anonymous namespace PreservedAnalyses UniqueInternalLinkageNamesPass::run(Module &M, ModuleAnalysisManager &AM) { if (!uniqueifyInternalLinkageNames(M)) return PreservedAnalyses::all(); return PreservedAnalyses::none(); } INITIALIZE_PASS_BEGIN(UniqueInternalLinkageNamesLegacyPass, "unique-internal-linkage-names", "Uniqueify internal linkage names", false, false) INITIALIZE_PASS_END(UniqueInternalLinkageNamesLegacyPass, "unique-internal-linkage-names", "Uniqueify Internal linkage names", false, false) namespace llvm { ModulePass *createUniqueInternalLinkageNamesPass() { return new UniqueInternalLinkageNamesLegacyPass(); } } // namespace llvm