blob: c57cec6be676e075aaefb11b175176a6fa191517 [file] [log] [blame]
//===- 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