10b57cec5SDimitry Andric //===- NameAnonGlobals.cpp - ThinLTO Support: Name Unnamed Globals --------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements naming anonymous globals to make sure they can be
100b57cec5SDimitry Andric // referred to by ThinLTO.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/Transforms/Utils/NameAnonGlobals.h"
150b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
160b57cec5SDimitry Andric #include "llvm/IR/Module.h"
170b57cec5SDimitry Andric #include "llvm/Support/MD5.h"
180b57cec5SDimitry Andric #include "llvm/Transforms/Utils/ModuleUtils.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric using namespace llvm;
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric namespace {
230b57cec5SDimitry Andric // Compute a "unique" hash for the module based on the name of the public
240b57cec5SDimitry Andric // globals.
250b57cec5SDimitry Andric class ModuleHasher {
260b57cec5SDimitry Andric   Module &TheModule;
270b57cec5SDimitry Andric   std::string TheHash;
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric public:
ModuleHasher(Module & M)300b57cec5SDimitry Andric   ModuleHasher(Module &M) : TheModule(M) {}
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric   /// Return the lazily computed hash.
get()330b57cec5SDimitry Andric   std::string &get() {
340b57cec5SDimitry Andric     if (!TheHash.empty())
350b57cec5SDimitry Andric       // Cache hit :)
360b57cec5SDimitry Andric       return TheHash;
370b57cec5SDimitry Andric 
380b57cec5SDimitry Andric     MD5 Hasher;
390b57cec5SDimitry Andric     for (auto &F : TheModule) {
400b57cec5SDimitry Andric       if (F.isDeclaration() || F.hasLocalLinkage() || !F.hasName())
410b57cec5SDimitry Andric         continue;
420b57cec5SDimitry Andric       auto Name = F.getName();
430b57cec5SDimitry Andric       Hasher.update(Name);
440b57cec5SDimitry Andric     }
450b57cec5SDimitry Andric     for (auto &GV : TheModule.globals()) {
460b57cec5SDimitry Andric       if (GV.isDeclaration() || GV.hasLocalLinkage() || !GV.hasName())
470b57cec5SDimitry Andric         continue;
480b57cec5SDimitry Andric       auto Name = GV.getName();
490b57cec5SDimitry Andric       Hasher.update(Name);
500b57cec5SDimitry Andric     }
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric     // Now return the result.
530b57cec5SDimitry Andric     MD5::MD5Result Hash;
540b57cec5SDimitry Andric     Hasher.final(Hash);
550b57cec5SDimitry Andric     SmallString<32> Result;
560b57cec5SDimitry Andric     MD5::stringifyResult(Hash, Result);
577a6dacacSDimitry Andric     TheHash = std::string(Result);
580b57cec5SDimitry Andric     return TheHash;
590b57cec5SDimitry Andric   }
600b57cec5SDimitry Andric };
610b57cec5SDimitry Andric } // end anonymous namespace
620b57cec5SDimitry Andric 
630b57cec5SDimitry Andric // Rename all the anon globals in the module
nameUnamedGlobals(Module & M)640b57cec5SDimitry Andric bool llvm::nameUnamedGlobals(Module &M) {
650b57cec5SDimitry Andric   bool Changed = false;
660b57cec5SDimitry Andric   ModuleHasher ModuleHash(M);
670b57cec5SDimitry Andric   int count = 0;
680b57cec5SDimitry Andric   auto RenameIfNeed = [&](GlobalValue &GV) {
690b57cec5SDimitry Andric     if (GV.hasName())
700b57cec5SDimitry Andric       return;
710b57cec5SDimitry Andric     GV.setName(Twine("anon.") + ModuleHash.get() + "." + Twine(count++));
720b57cec5SDimitry Andric     Changed = true;
730b57cec5SDimitry Andric   };
740b57cec5SDimitry Andric   for (auto &GO : M.global_objects())
750b57cec5SDimitry Andric     RenameIfNeed(GO);
760b57cec5SDimitry Andric   for (auto &GA : M.aliases())
770b57cec5SDimitry Andric     RenameIfNeed(GA);
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   return Changed;
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric 
run(Module & M,ModuleAnalysisManager & AM)820b57cec5SDimitry Andric PreservedAnalyses NameAnonGlobalPass::run(Module &M,
830b57cec5SDimitry Andric                                           ModuleAnalysisManager &AM) {
840b57cec5SDimitry Andric   if (!nameUnamedGlobals(M))
850b57cec5SDimitry Andric     return PreservedAnalyses::all();
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   return PreservedAnalyses::none();
880b57cec5SDimitry Andric }
89