blob: ac8991e9d475a241f157f19e2cc3cfaf26d19247 [file] [log] [blame]
Mehdi Amini27d23792016-09-16 16:56:30 +00001//===- NameAnonGlobals.cpp - ThinLTO Support: Name Unnamed Globals --------===//
Mehdi Aminid5faa262016-04-12 21:35:28 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Mehdi Aminid5faa262016-04-12 21:35:28 +00006//
7//===----------------------------------------------------------------------===//
8//
Mehdi Amini27d23792016-09-16 16:56:30 +00009// This file implements naming anonymous globals to make sure they can be
10// referred to by ThinLTO.
Mehdi Aminid5faa262016-04-12 21:35:28 +000011//
12//===----------------------------------------------------------------------===//
13
Mehdi Amini27d23792016-09-16 16:56:30 +000014#include "llvm/Transforms/Utils/NameAnonGlobals.h"
Teresa Johnson4223dd82016-08-12 14:03:36 +000015
Mehdi Aminid5faa262016-04-12 21:35:28 +000016#include "llvm/ADT/SmallString.h"
17#include "llvm/IR/Module.h"
18#include "llvm/Support/MD5.h"
19#include "llvm/Transforms/Utils/ModuleUtils.h"
20
21using namespace llvm;
22
Benjamin Kramerb7d33112016-08-06 11:13:10 +000023namespace {
Mehdi Aminid5faa262016-04-12 21:35:28 +000024// Compute a "unique" hash for the module based on the name of the public
Mehdi Amini27d23792016-09-16 16:56:30 +000025// globals.
Mehdi Aminid5faa262016-04-12 21:35:28 +000026class ModuleHasher {
27 Module &TheModule;
28 std::string TheHash;
29
30public:
31 ModuleHasher(Module &M) : TheModule(M) {}
32
33 /// Return the lazily computed hash.
34 std::string &get() {
35 if (!TheHash.empty())
36 // Cache hit :)
37 return TheHash;
38
39 MD5 Hasher;
40 for (auto &F : TheModule) {
41 if (F.isDeclaration() || F.hasLocalLinkage() || !F.hasName())
42 continue;
43 auto Name = F.getName();
44 Hasher.update(Name);
45 }
46 for (auto &GV : TheModule.globals()) {
47 if (GV.isDeclaration() || GV.hasLocalLinkage() || !GV.hasName())
48 continue;
49 auto Name = GV.getName();
50 Hasher.update(Name);
51 }
52
53 // Now return the result.
54 MD5::MD5Result Hash;
55 Hasher.final(Hash);
56 SmallString<32> Result;
57 MD5::stringifyResult(Hash, Result);
58 TheHash = Result.str();
59 return TheHash;
60 }
61};
Benjamin Kramerb7d33112016-08-06 11:13:10 +000062} // end anonymous namespace
Mehdi Aminid5faa262016-04-12 21:35:28 +000063
Mehdi Amini27d23792016-09-16 16:56:30 +000064// Rename all the anon globals in the module
65bool llvm::nameUnamedGlobals(Module &M) {
Mehdi Aminid5faa262016-04-12 21:35:28 +000066 bool Changed = false;
67 ModuleHasher ModuleHash(M);
68 int count = 0;
Mehdi Amini27d23792016-09-16 16:56:30 +000069 auto RenameIfNeed = [&](GlobalValue &GV) {
Mehdi Amini2cac7872016-09-16 16:56:25 +000070 if (GV.hasName())
71 return;
72 GV.setName(Twine("anon.") + ModuleHash.get() + "." + Twine(count++));
Mehdi Aminid5faa262016-04-12 21:35:28 +000073 Changed = true;
Mehdi Amini2cac7872016-09-16 16:56:25 +000074 };
75 for (auto &GO : M.global_objects())
76 RenameIfNeed(GO);
77 for (auto &GA : M.aliases())
78 RenameIfNeed(GA);
79
Mehdi Aminid5faa262016-04-12 21:35:28 +000080 return Changed;
81}
82
83namespace {
84
Mehdi Amini27d23792016-09-16 16:56:30 +000085// Legacy pass that provides a name to every anon globals.
86class NameAnonGlobalLegacyPass : public ModulePass {
Mehdi Aminid5faa262016-04-12 21:35:28 +000087
88public:
89 /// Pass identification, replacement for typeid
90 static char ID;
91
92 /// Specify pass name for debug output
Mehdi Amini117296c2016-10-01 02:56:57 +000093 StringRef getPassName() const override { return "Name Anon Globals"; }
Mehdi Aminid5faa262016-04-12 21:35:28 +000094
Mehdi Amini27d23792016-09-16 16:56:30 +000095 explicit NameAnonGlobalLegacyPass() : ModulePass(ID) {}
Mehdi Aminid5faa262016-04-12 21:35:28 +000096
Mehdi Amini27d23792016-09-16 16:56:30 +000097 bool runOnModule(Module &M) override { return nameUnamedGlobals(M); }
Mehdi Aminid5faa262016-04-12 21:35:28 +000098};
Mehdi Amini27d23792016-09-16 16:56:30 +000099char NameAnonGlobalLegacyPass::ID = 0;
Mehdi Aminid5faa262016-04-12 21:35:28 +0000100
101} // anonymous namespace
102
Mehdi Amini27d23792016-09-16 16:56:30 +0000103PreservedAnalyses NameAnonGlobalPass::run(Module &M,
104 ModuleAnalysisManager &AM) {
105 if (!nameUnamedGlobals(M))
Teresa Johnson4223dd82016-08-12 14:03:36 +0000106 return PreservedAnalyses::all();
107
108 return PreservedAnalyses::none();
109}
110
Mehdi Amini27d23792016-09-16 16:56:30 +0000111INITIALIZE_PASS_BEGIN(NameAnonGlobalLegacyPass, "name-anon-globals",
112 "Provide a name to nameless globals", false, false)
113INITIALIZE_PASS_END(NameAnonGlobalLegacyPass, "name-anon-globals",
114 "Provide a name to nameless globals", false, false)
Mehdi Aminid5faa262016-04-12 21:35:28 +0000115
116namespace llvm {
Mehdi Amini27d23792016-09-16 16:56:30 +0000117ModulePass *createNameAnonGlobalPass() {
118 return new NameAnonGlobalLegacyPass();
Teresa Johnson4223dd82016-08-12 14:03:36 +0000119}
Mehdi Aminid5faa262016-04-12 21:35:28 +0000120}