diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -304,6 +304,7 @@ void initializeMustExecutePrinterPass(PassRegistry&); void initializeMustBeExecutedContextPrinterPass(PassRegistry&); void initializeNameAnonGlobalLegacyPassPass(PassRegistry&); +void initializeUniqueInternalLinkageNamesLegacyPassPass(PassRegistry &); void initializeNaryReassociateLegacyPassPass(PassRegistry&); void initializeNewGVNLegacyPassPass(PassRegistry&); void initializeObjCARCAAWrapperPassPass(PassRegistry&); diff --git a/llvm/include/llvm/Transforms/Utils.h b/llvm/include/llvm/Transforms/Utils.h --- a/llvm/include/llvm/Transforms/Utils.h +++ b/llvm/include/llvm/Transforms/Utils.h @@ -26,6 +26,12 @@ ModulePass *createMetaRenamerPass(); //===----------------------------------------------------------------------===// +// createUniqueInternalLinkageNamesPass - Make internal linkage symbol names +// unique. +// +ModulePass *createUniqueInternalLinkageNamesPass(); + +//===----------------------------------------------------------------------===// // // LowerInvoke - This pass removes invoke instructions, converting them to call // instructions. diff --git a/llvm/include/llvm/Transforms/Utils/UniqueInternalLinkageNames.h b/llvm/include/llvm/Transforms/Utils/UniqueInternalLinkageNames.h new file mode 100644 --- /dev/null +++ b/llvm/include/llvm/Transforms/Utils/UniqueInternalLinkageNames.h @@ -0,0 +1,31 @@ +//===-- UniqueInternalLinkageNames.h - Uniq. Int. Linkage Names -*- C++ -*-===// +// +// 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. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_TRANSFORMS_UTILS_UNIQUEINTERNALLINKAGENAMES_H +#define LLVM_TRANSFORMS_UTILS_UNIQUEINTERNALLINKAGENAMES_H + +#include "llvm/IR/Module.h" +#include "llvm/IR/PassManager.h" + +namespace llvm { + +/// Simple pass that provides a name to every anonymous globals. +class UniqueInternalLinkageNamesPass + : public PassInfoMixin { +public: + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + +} // end namespace llvm + +#endif // LLVM_TRANSFORMS_UTILS_UNIQUEINTERNALLINKAGENAMES_H diff --git a/llvm/lib/Transforms/Utils/CMakeLists.txt b/llvm/lib/Transforms/Utils/CMakeLists.txt --- a/llvm/lib/Transforms/Utils/CMakeLists.txt +++ b/llvm/lib/Transforms/Utils/CMakeLists.txt @@ -65,6 +65,7 @@ SymbolRewriter.cpp UnifyFunctionExitNodes.cpp UnifyLoopExits.cpp + UniqueInternalLinkageNames.cpp Utils.cpp ValueMapper.cpp VNCoercion.cpp diff --git a/llvm/lib/Transforms/Utils/UniqueInternalLinkageNames.cpp b/llvm/lib/Transforms/Utils/UniqueInternalLinkageNames.cpp new file mode 100644 --- /dev/null +++ b/llvm/lib/Transforms/Utils/UniqueInternalLinkageNames.cpp @@ -0,0 +1,97 @@ +//===- 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/Module.h" +#include "llvm/InitializePasses.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); + std::string ModuleNameHash = (Twine(".") + Twine(Str)).str(); + bool Changed = false; + + // Append the module hash to all internal linkage functions. + for (auto &F : M) { + if (F.hasInternalLinkage()) { + F.setName(F.getName() + ModuleNameHash); + 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 diff --git a/llvm/lib/Transforms/Utils/Utils.cpp b/llvm/lib/Transforms/Utils/Utils.cpp --- a/llvm/lib/Transforms/Utils/Utils.cpp +++ b/llvm/lib/Transforms/Utils/Utils.cpp @@ -42,6 +42,7 @@ initializeInjectTLIMappingsLegacyPass(Registry); initializeFixIrreduciblePass(Registry); initializeUnifyLoopExitsPass(Registry); + initializeUniqueInternalLinkageNamesLegacyPassPass(Registry); } /// LLVMInitializeTransformUtils - C binding for initializeTransformUtilsPasses. diff --git a/llvm/test/Transforms/UniqueInternalLinkageNames/unique_symbol_names.ll b/llvm/test/Transforms/UniqueInternalLinkageNames/unique_symbol_names.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/UniqueInternalLinkageNames/unique_symbol_names.ll @@ -0,0 +1,13 @@ +; RUN: opt -S -unique-internal-linkage-names < %s | FileCheck %s + +source_filename = "foo.c" + +@glob = internal global i32 0 + +define internal i32 @foo() { +entry: + ret i32 0 +} + +; CHECK: @glob.6ae72bb15a7d1834b42ae042a58f7a4d = internal global +; CHECK: define internal i32 @foo.6ae72bb15a7d1834b42ae042a58f7a4d() diff --git a/llvm/utils/gn/secondary/llvm/lib/Transforms/Utils/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Transforms/Utils/BUILD.gn --- a/llvm/utils/gn/secondary/llvm/lib/Transforms/Utils/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Transforms/Utils/BUILD.gn @@ -72,6 +72,7 @@ "SymbolRewriter.cpp", "UnifyFunctionExitNodes.cpp", "UnifyLoopExits.cpp", + "UniqueInternalLinkageNames.cpp", "Utils.cpp", "VNCoercion.cpp", "ValueMapper.cpp",