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