NameAnonGlobals.cpp 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. //===- NameAnonGlobals.cpp - ThinLTO Support: Name Unnamed Globals --------===//
  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. // This file implements naming anonymous globals to make sure they can be
  10. // referred to by ThinLTO.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "llvm/Transforms/Utils/NameAnonGlobals.h"
  14. #include "llvm/ADT/SmallString.h"
  15. #include "llvm/IR/Module.h"
  16. #include "llvm/InitializePasses.h"
  17. #include "llvm/Pass.h"
  18. #include "llvm/Support/MD5.h"
  19. #include "llvm/Transforms/Utils/ModuleUtils.h"
  20. using namespace llvm;
  21. namespace {
  22. // Compute a "unique" hash for the module based on the name of the public
  23. // globals.
  24. class ModuleHasher {
  25. Module &TheModule;
  26. std::string TheHash;
  27. public:
  28. ModuleHasher(Module &M) : TheModule(M) {}
  29. /// Return the lazily computed hash.
  30. std::string &get() {
  31. if (!TheHash.empty())
  32. // Cache hit :)
  33. return TheHash;
  34. MD5 Hasher;
  35. for (auto &F : TheModule) {
  36. if (F.isDeclaration() || F.hasLocalLinkage() || !F.hasName())
  37. continue;
  38. auto Name = F.getName();
  39. Hasher.update(Name);
  40. }
  41. for (auto &GV : TheModule.globals()) {
  42. if (GV.isDeclaration() || GV.hasLocalLinkage() || !GV.hasName())
  43. continue;
  44. auto Name = GV.getName();
  45. Hasher.update(Name);
  46. }
  47. // Now return the result.
  48. MD5::MD5Result Hash;
  49. Hasher.final(Hash);
  50. SmallString<32> Result;
  51. MD5::stringifyResult(Hash, Result);
  52. TheHash = std::string(Result.str());
  53. return TheHash;
  54. }
  55. };
  56. } // end anonymous namespace
  57. // Rename all the anon globals in the module
  58. bool llvm::nameUnamedGlobals(Module &M) {
  59. bool Changed = false;
  60. ModuleHasher ModuleHash(M);
  61. int count = 0;
  62. auto RenameIfNeed = [&](GlobalValue &GV) {
  63. if (GV.hasName())
  64. return;
  65. GV.setName(Twine("anon.") + ModuleHash.get() + "." + Twine(count++));
  66. Changed = true;
  67. };
  68. for (auto &GO : M.global_objects())
  69. RenameIfNeed(GO);
  70. for (auto &GA : M.aliases())
  71. RenameIfNeed(GA);
  72. return Changed;
  73. }
  74. namespace {
  75. // Legacy pass that provides a name to every anon globals.
  76. class NameAnonGlobalLegacyPass : public ModulePass {
  77. public:
  78. /// Pass identification, replacement for typeid
  79. static char ID;
  80. /// Specify pass name for debug output
  81. StringRef getPassName() const override { return "Name Anon Globals"; }
  82. explicit NameAnonGlobalLegacyPass() : ModulePass(ID) {}
  83. bool runOnModule(Module &M) override { return nameUnamedGlobals(M); }
  84. };
  85. char NameAnonGlobalLegacyPass::ID = 0;
  86. } // anonymous namespace
  87. PreservedAnalyses NameAnonGlobalPass::run(Module &M,
  88. ModuleAnalysisManager &AM) {
  89. if (!nameUnamedGlobals(M))
  90. return PreservedAnalyses::all();
  91. return PreservedAnalyses::none();
  92. }
  93. INITIALIZE_PASS_BEGIN(NameAnonGlobalLegacyPass, "name-anon-globals",
  94. "Provide a name to nameless globals", false, false)
  95. INITIALIZE_PASS_END(NameAnonGlobalLegacyPass, "name-anon-globals",
  96. "Provide a name to nameless globals", false, false)
  97. namespace llvm {
  98. ModulePass *createNameAnonGlobalPass() {
  99. return new NameAnonGlobalLegacyPass();
  100. }
  101. }