blob: 6629ab85510be78174a702a1e0aeb9f50a1fc575 [file] [log] [blame]
Mehdi Aminid5faa262016-04-12 21:35:28 +00001//===- NameAnonFunctions.cpp - ThinLTO Summary-based Function Import ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements naming anonymous function to make sure they can be
11// refered to by ThinLTO.
12//
13//===----------------------------------------------------------------------===//
14
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
Benjamin Kramerb7d33112016-08-06 11:13:10 +000022namespace {
Mehdi Aminid5faa262016-04-12 21:35:28 +000023// Compute a "unique" hash for the module based on the name of the public
24// functions.
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(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 = Result.str();
58 return TheHash;
59 }
60};
Benjamin Kramerb7d33112016-08-06 11:13:10 +000061} // end anonymous namespace
Mehdi Aminid5faa262016-04-12 21:35:28 +000062
63// Rename all the anon functions in the module
64bool llvm::nameUnamedFunctions(Module &M) {
65 bool Changed = false;
66 ModuleHasher ModuleHash(M);
67 int count = 0;
68 for (auto &F : M) {
69 if (F.hasName())
70 continue;
71 F.setName(Twine("anon.") + ModuleHash.get() + "." + Twine(count++));
72 Changed = true;
73 }
74 return Changed;
75}
76
77namespace {
78
79// Simple pass that provides a name to every anon function.
80class NameAnonFunction : public ModulePass {
81
82public:
83 /// Pass identification, replacement for typeid
84 static char ID;
85
86 /// Specify pass name for debug output
87 const char *getPassName() const override { return "Name Anon Functions"; }
88
89 explicit NameAnonFunction() : ModulePass(ID) {}
90
91 bool runOnModule(Module &M) override { return nameUnamedFunctions(M); }
92};
93char NameAnonFunction::ID = 0;
94
95} // anonymous namespace
96
97INITIALIZE_PASS_BEGIN(NameAnonFunction, "name-anon-functions",
98 "Provide a name to nameless functions", false, false)
99INITIALIZE_PASS_END(NameAnonFunction, "name-anon-functions",
100 "Provide a name to nameless functions", false, false)
101
102namespace llvm {
Mehdi Amini818f67a2016-04-12 23:25:11 +0000103ModulePass *createNameAnonFunctionPass() { return new NameAnonFunction(); }
Mehdi Aminid5faa262016-04-12 21:35:28 +0000104}