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); 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