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 Andricbool 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 AndricPreservedAnalyses 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