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
20using namespace llvm;
21
22namespace {
23// Compute a "unique" hash for the module based on the name of the public
24// globals.
25class ModuleHasher {
26 Module &TheModule;
27 std::string TheHash;
28
29public:
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(Str: 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(Str: Name);
50 }
51
52 // Now return the result.
53 MD5::MD5Result Hash;
54 Hasher.final(Result&: Hash);
55 SmallString<32> Result;
56 MD5::stringifyResult(Result&: Hash, Str&: 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
64bool 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
82PreservedAnalyses NameAnonGlobalPass::run(Module &M,
83 ModuleAnalysisManager &AM) {
84 if (!nameUnamedGlobals(M))
85 return PreservedAnalyses::all();
86
87 return PreservedAnalyses::none();
88}
89