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 
14 #include "llvm/Transforms/Utils/NameAnonGlobals.h"
15 #include "llvm/ADT/SmallString.h"
16 #include "llvm/IR/Module.h"
17 #include "llvm/Support/MD5.h"
18 #include "llvm/Transforms/Utils/ModuleUtils.h"
19 
20 using namespace llvm;
21 
22 namespace {
23 // Compute a "unique" hash for the module based on the name of the public
24 // globals.
25 class ModuleHasher {
26   Module &TheModule;
27   std::string TheHash;
28 
29 public:
30   ModuleHasher(Module &M) : TheModule(M) {}
31 
32   /// Return the lazily computed hash.
33   std::string &get() {
34     if (!TheHash.empty())
35       // Cache hit :)
36       return TheHash;
37 
38     MD5 Hasher;
39     for (auto &F : TheModule) {
40       if (F.isDeclaration() || F.hasLocalLinkage() || !F.hasName())
41         continue;
42       auto Name = F.getName();
43       Hasher.update(Name);
44     }
45     for (auto &GV : TheModule.globals()) {
46       if (GV.isDeclaration() || GV.hasLocalLinkage() || !GV.hasName())
47         continue;
48       auto Name = GV.getName();
49       Hasher.update(Name);
50     }
51 
52     // Now return the result.
53     MD5::MD5Result Hash;
54     Hasher.final(Hash);
55     SmallString<32> Result;
56     MD5::stringifyResult(Hash, Result);
57     TheHash = std::string(Result.str());
58     return TheHash;
59   }
60 };
61 } // end anonymous namespace
62 
63 // Rename all the anon globals in the module
64 bool llvm::nameUnamedGlobals(Module &M) {
65   bool Changed = false;
66   ModuleHasher ModuleHash(M);
67   int count = 0;
68   auto RenameIfNeed = [&](GlobalValue &GV) {
69     if (GV.hasName())
70       return;
71     GV.setName(Twine("anon.") + ModuleHash.get() + "." + Twine(count++));
72     Changed = true;
73   };
74   for (auto &GO : M.global_objects())
75     RenameIfNeed(GO);
76   for (auto &GA : M.aliases())
77     RenameIfNeed(GA);
78 
79   return Changed;
80 }
81 
82 PreservedAnalyses NameAnonGlobalPass::run(Module &M,
83                                           ModuleAnalysisManager &AM) {
84   if (!nameUnamedGlobals(M))
85     return PreservedAnalyses::all();
86 
87   return PreservedAnalyses::none();
88 }
89