119 lines
3.8 KiB
C++
119 lines
3.8 KiB
C++
//===- 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
|