NameAnonGlobals.cpp revision 341825
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 22using namespace llvm; 23 24namespace { 25// Compute a "unique" hash for the module based on the name of the public 26// globals. 27class ModuleHasher { 28 Module &TheModule; 29 std::string TheHash; 30 31public: 32 ModuleHasher(Module &M) : TheModule(M) {} 33 34 /// Return the lazily computed hash. 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 66bool 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 84namespace { 85 86// Legacy pass that provides a name to every anon globals. 87class NameAnonGlobalLegacyPass : public ModulePass { 88 89public: 90 /// Pass identification, replacement for typeid 91 static char ID; 92 93 /// Specify pass name for debug output 94 StringRef getPassName() const override { return "Name Anon Globals"; } 95 96 explicit NameAnonGlobalLegacyPass() : ModulePass(ID) {} 97 98 bool runOnModule(Module &M) override { return nameUnamedGlobals(M); } 99}; 100char NameAnonGlobalLegacyPass::ID = 0; 101 102} // anonymous namespace 103 104PreservedAnalyses NameAnonGlobalPass::run(Module &M, 105 ModuleAnalysisManager &AM) { 106 if (!nameUnamedGlobals(M)) 107 return PreservedAnalyses::all(); 108 109 return PreservedAnalyses::none(); 110} 111 112INITIALIZE_PASS_BEGIN(NameAnonGlobalLegacyPass, "name-anon-globals", 113 "Provide a name to nameless globals", false, false) 114INITIALIZE_PASS_END(NameAnonGlobalLegacyPass, "name-anon-globals", 115 "Provide a name to nameless globals", false, false) 116 117namespace llvm { 118ModulePass *createNameAnonGlobalPass() { 119 return new NameAnonGlobalLegacyPass(); 120} 121} 122