1a373d18eSDavid Blaikie //===- MetaRenamer.cpp - Rename everything with metasyntatic names --------===//
2a373d18eSDavid Blaikie //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6a373d18eSDavid Blaikie //
7a373d18eSDavid Blaikie //===----------------------------------------------------------------------===//
8a373d18eSDavid Blaikie //
9a373d18eSDavid Blaikie // This pass renames everything with metasyntatic names. The intent is to use
10a373d18eSDavid Blaikie // this pass after bugpoint reduction to conceal the nature of the original
11a373d18eSDavid Blaikie // program.
12a373d18eSDavid Blaikie //
13a373d18eSDavid Blaikie //===----------------------------------------------------------------------===//
14a373d18eSDavid Blaikie
15321986feSArthur Eubanks #include "llvm/Transforms/Utils/MetaRenamer.h"
16a373d18eSDavid Blaikie #include "llvm/ADT/STLExtras.h"
17a373d18eSDavid Blaikie #include "llvm/ADT/SmallString.h"
180b533c18SDmitry Makogon #include "llvm/ADT/SmallVector.h"
19a373d18eSDavid Blaikie #include "llvm/ADT/StringRef.h"
20a373d18eSDavid Blaikie #include "llvm/ADT/Twine.h"
21a373d18eSDavid Blaikie #include "llvm/Analysis/TargetLibraryInfo.h"
22a373d18eSDavid Blaikie #include "llvm/IR/Argument.h"
23a373d18eSDavid Blaikie #include "llvm/IR/BasicBlock.h"
24a373d18eSDavid Blaikie #include "llvm/IR/DerivedTypes.h"
25a373d18eSDavid Blaikie #include "llvm/IR/Function.h"
26a373d18eSDavid Blaikie #include "llvm/IR/GlobalAlias.h"
27a373d18eSDavid Blaikie #include "llvm/IR/GlobalVariable.h"
28a373d18eSDavid Blaikie #include "llvm/IR/Instruction.h"
29a373d18eSDavid Blaikie #include "llvm/IR/Module.h"
30321986feSArthur Eubanks #include "llvm/IR/PassManager.h"
31a373d18eSDavid Blaikie #include "llvm/IR/Type.h"
32a373d18eSDavid Blaikie #include "llvm/IR/TypeFinder.h"
3305da2fe5SReid Kleckner #include "llvm/InitializePasses.h"
34a373d18eSDavid Blaikie #include "llvm/Pass.h"
350b533c18SDmitry Makogon #include "llvm/Support/CommandLine.h"
36a373d18eSDavid Blaikie #include "llvm/Transforms/Utils.h"
37a373d18eSDavid Blaikie
38a373d18eSDavid Blaikie using namespace llvm;
39a373d18eSDavid Blaikie
400b533c18SDmitry Makogon static cl::opt<std::string> RenameExcludeFunctionPrefixes(
410b533c18SDmitry Makogon "rename-exclude-function-prefixes",
420b533c18SDmitry Makogon cl::desc("Prefixes for functions that don't need to be renamed, separated "
430b533c18SDmitry Makogon "by a comma"),
440b533c18SDmitry Makogon cl::Hidden);
450b533c18SDmitry Makogon
460b533c18SDmitry Makogon static cl::opt<std::string> RenameExcludeAliasPrefixes(
470b533c18SDmitry Makogon "rename-exclude-alias-prefixes",
480b533c18SDmitry Makogon cl::desc("Prefixes for aliases that don't need to be renamed, separated "
490b533c18SDmitry Makogon "by a comma"),
500b533c18SDmitry Makogon cl::Hidden);
510b533c18SDmitry Makogon
520b533c18SDmitry Makogon static cl::opt<std::string> RenameExcludeGlobalPrefixes(
530b533c18SDmitry Makogon "rename-exclude-global-prefixes",
540b533c18SDmitry Makogon cl::desc(
550b533c18SDmitry Makogon "Prefixes for global values that don't need to be renamed, separated "
560b533c18SDmitry Makogon "by a comma"),
570b533c18SDmitry Makogon cl::Hidden);
580b533c18SDmitry Makogon
590b533c18SDmitry Makogon static cl::opt<std::string> RenameExcludeStructPrefixes(
600b533c18SDmitry Makogon "rename-exclude-struct-prefixes",
610b533c18SDmitry Makogon cl::desc("Prefixes for structs that don't need to be renamed, separated "
620b533c18SDmitry Makogon "by a comma"),
630b533c18SDmitry Makogon cl::Hidden);
640b533c18SDmitry Makogon
65a373d18eSDavid Blaikie static const char *const metaNames[] = {
66a373d18eSDavid Blaikie // See http://en.wikipedia.org/wiki/Metasyntactic_variable
67a373d18eSDavid Blaikie "foo", "bar", "baz", "quux", "barney", "snork", "zot", "blam", "hoge",
68a373d18eSDavid Blaikie "wibble", "wobble", "widget", "wombat", "ham", "eggs", "pluto", "spam"
69a373d18eSDavid Blaikie };
70a373d18eSDavid Blaikie
71a373d18eSDavid Blaikie namespace {
72a373d18eSDavid Blaikie // This PRNG is from the ISO C spec. It is intentionally simple and
73a373d18eSDavid Blaikie // unsuitable for cryptographic use. We're just looking for enough
74a373d18eSDavid Blaikie // variety to surprise and delight users.
75a373d18eSDavid Blaikie struct PRNG {
76a373d18eSDavid Blaikie unsigned long next;
77a373d18eSDavid Blaikie
srand__anon91ab9caf0111::PRNG78321986feSArthur Eubanks void srand(unsigned int seed) { next = seed; }
79a373d18eSDavid Blaikie
rand__anon91ab9caf0111::PRNG80a373d18eSDavid Blaikie int rand() {
81a373d18eSDavid Blaikie next = next * 1103515245 + 12345;
82a373d18eSDavid Blaikie return (unsigned int)(next / 65536) % 32768;
83a373d18eSDavid Blaikie }
84a373d18eSDavid Blaikie };
85a373d18eSDavid Blaikie
86a373d18eSDavid Blaikie struct Renamer {
Renamer__anon91ab9caf0111::Renamer87321986feSArthur Eubanks Renamer(unsigned int seed) { prng.srand(seed); }
88a373d18eSDavid Blaikie
newName__anon91ab9caf0111::Renamer89a373d18eSDavid Blaikie const char *newName() {
90*f15014ffSBenjamin Kramer return metaNames[prng.rand() % array_lengthof(metaNames)];
91a373d18eSDavid Blaikie }
92a373d18eSDavid Blaikie
93a373d18eSDavid Blaikie PRNG prng;
94a373d18eSDavid Blaikie };
95a373d18eSDavid Blaikie
960b533c18SDmitry Makogon static void
parseExcludedPrefixes(StringRef PrefixesStr,SmallVectorImpl<StringRef> & ExcludedPrefixes)970b533c18SDmitry Makogon parseExcludedPrefixes(StringRef PrefixesStr,
980b533c18SDmitry Makogon SmallVectorImpl<StringRef> &ExcludedPrefixes) {
990b533c18SDmitry Makogon for (;;) {
1000b533c18SDmitry Makogon auto PrefixesSplit = PrefixesStr.split(',');
1010b533c18SDmitry Makogon if (PrefixesSplit.first.empty())
1020b533c18SDmitry Makogon break;
1030b533c18SDmitry Makogon ExcludedPrefixes.push_back(PrefixesSplit.first);
1040b533c18SDmitry Makogon PrefixesStr = PrefixesSplit.second;
1050b533c18SDmitry Makogon }
1060b533c18SDmitry Makogon }
1070b533c18SDmitry Makogon
MetaRename(Function & F)108321986feSArthur Eubanks void MetaRename(Function &F) {
109be23012dSKazu Hirata for (Argument &Arg : F.args())
110be23012dSKazu Hirata if (!Arg.getType()->isVoidTy())
111be23012dSKazu Hirata Arg.setName("arg");
112a373d18eSDavid Blaikie
113321986feSArthur Eubanks for (auto &BB : F) {
114321986feSArthur Eubanks BB.setName("bb");
115321986feSArthur Eubanks
116321986feSArthur Eubanks for (auto &I : BB)
117321986feSArthur Eubanks if (!I.getType()->isVoidTy())
118321986feSArthur Eubanks I.setName("tmp");
119321986feSArthur Eubanks }
120a373d18eSDavid Blaikie }
121a373d18eSDavid Blaikie
MetaRename(Module & M,function_ref<TargetLibraryInfo & (Function &)> GetTLI)122321986feSArthur Eubanks void MetaRename(Module &M,
123321986feSArthur Eubanks function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
124a373d18eSDavid Blaikie // Seed our PRNG with simple additive sum of ModuleID. We're looking to
125a373d18eSDavid Blaikie // simply avoid always having the same function names, and we need to
126a373d18eSDavid Blaikie // remain deterministic.
127a373d18eSDavid Blaikie unsigned int randSeed = 0;
128a373d18eSDavid Blaikie for (auto C : M.getModuleIdentifier())
129a373d18eSDavid Blaikie randSeed += C;
130a373d18eSDavid Blaikie
131a373d18eSDavid Blaikie Renamer renamer(randSeed);
132a373d18eSDavid Blaikie
1330b533c18SDmitry Makogon SmallVector<StringRef, 8> ExcludedAliasesPrefixes;
1340b533c18SDmitry Makogon SmallVector<StringRef, 8> ExcludedGlobalsPrefixes;
1350b533c18SDmitry Makogon SmallVector<StringRef, 8> ExcludedStructsPrefixes;
1360b533c18SDmitry Makogon SmallVector<StringRef, 8> ExcludedFuncPrefixes;
1370b533c18SDmitry Makogon parseExcludedPrefixes(RenameExcludeAliasPrefixes, ExcludedAliasesPrefixes);
1380b533c18SDmitry Makogon parseExcludedPrefixes(RenameExcludeGlobalPrefixes, ExcludedGlobalsPrefixes);
1390b533c18SDmitry Makogon parseExcludedPrefixes(RenameExcludeStructPrefixes, ExcludedStructsPrefixes);
1400b533c18SDmitry Makogon parseExcludedPrefixes(RenameExcludeFunctionPrefixes, ExcludedFuncPrefixes);
1410b533c18SDmitry Makogon
1420b533c18SDmitry Makogon auto IsNameExcluded = [](StringRef &Name,
1430b533c18SDmitry Makogon SmallVectorImpl<StringRef> &ExcludedPrefixes) {
1440b533c18SDmitry Makogon return any_of(ExcludedPrefixes,
1450b533c18SDmitry Makogon [&Name](auto &Prefix) { return Name.startswith(Prefix); });
1460b533c18SDmitry Makogon };
1470b533c18SDmitry Makogon
148a373d18eSDavid Blaikie // Rename all aliases
149d1abf481SKazu Hirata for (GlobalAlias &GA : M.aliases()) {
150d1abf481SKazu Hirata StringRef Name = GA.getName();
1510b533c18SDmitry Makogon if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
1520b533c18SDmitry Makogon IsNameExcluded(Name, ExcludedAliasesPrefixes))
153a373d18eSDavid Blaikie continue;
154a373d18eSDavid Blaikie
155d1abf481SKazu Hirata GA.setName("alias");
156a373d18eSDavid Blaikie }
157a373d18eSDavid Blaikie
158a373d18eSDavid Blaikie // Rename all global variables
159be23012dSKazu Hirata for (GlobalVariable &GV : M.globals()) {
160be23012dSKazu Hirata StringRef Name = GV.getName();
1610b533c18SDmitry Makogon if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
1620b533c18SDmitry Makogon IsNameExcluded(Name, ExcludedGlobalsPrefixes))
163a373d18eSDavid Blaikie continue;
164a373d18eSDavid Blaikie
165be23012dSKazu Hirata GV.setName("global");
166a373d18eSDavid Blaikie }
167a373d18eSDavid Blaikie
168a373d18eSDavid Blaikie // Rename all struct types
169a373d18eSDavid Blaikie TypeFinder StructTypes;
170a373d18eSDavid Blaikie StructTypes.run(M, true);
171a373d18eSDavid Blaikie for (StructType *STy : StructTypes) {
1720b533c18SDmitry Makogon StringRef Name = STy->getName();
1730b533c18SDmitry Makogon if (STy->isLiteral() || Name.empty() ||
1740b533c18SDmitry Makogon IsNameExcluded(Name, ExcludedStructsPrefixes))
175321986feSArthur Eubanks continue;
176a373d18eSDavid Blaikie
177a373d18eSDavid Blaikie SmallString<128> NameStorage;
178321986feSArthur Eubanks STy->setName(
179321986feSArthur Eubanks (Twine("struct.") + renamer.newName()).toStringRef(NameStorage));
180a373d18eSDavid Blaikie }
181a373d18eSDavid Blaikie
182a373d18eSDavid Blaikie // Rename all functions
183a373d18eSDavid Blaikie for (auto &F : M) {
184a373d18eSDavid Blaikie StringRef Name = F.getName();
185a373d18eSDavid Blaikie LibFunc Tmp;
186a373d18eSDavid Blaikie // Leave library functions alone because their presence or absence could
187a373d18eSDavid Blaikie // affect the behavior of other passes.
188a373d18eSDavid Blaikie if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
1890b533c18SDmitry Makogon GetTLI(F).getLibFunc(F, Tmp) ||
1900b533c18SDmitry Makogon IsNameExcluded(Name, ExcludedFuncPrefixes))
191a373d18eSDavid Blaikie continue;
192a373d18eSDavid Blaikie
193a373d18eSDavid Blaikie // Leave @main alone. The output of -metarenamer might be passed to
194a373d18eSDavid Blaikie // lli for execution and the latter needs a main entry point.
195a373d18eSDavid Blaikie if (Name != "main")
196a373d18eSDavid Blaikie F.setName(renamer.newName());
197a373d18eSDavid Blaikie
198321986feSArthur Eubanks MetaRename(F);
199a373d18eSDavid Blaikie }
200a373d18eSDavid Blaikie }
201a373d18eSDavid Blaikie
202321986feSArthur Eubanks struct MetaRenamer : public ModulePass {
203321986feSArthur Eubanks // Pass identification, replacement for typeid
204321986feSArthur Eubanks static char ID;
205a373d18eSDavid Blaikie
MetaRenamer__anon91ab9caf0111::MetaRenamer206321986feSArthur Eubanks MetaRenamer() : ModulePass(ID) {
207321986feSArthur Eubanks initializeMetaRenamerPass(*PassRegistry::getPassRegistry());
208a373d18eSDavid Blaikie }
209321986feSArthur Eubanks
getAnalysisUsage__anon91ab9caf0111::MetaRenamer210321986feSArthur Eubanks void getAnalysisUsage(AnalysisUsage &AU) const override {
211321986feSArthur Eubanks AU.addRequired<TargetLibraryInfoWrapperPass>();
212321986feSArthur Eubanks AU.setPreservesAll();
213321986feSArthur Eubanks }
214321986feSArthur Eubanks
runOnModule__anon91ab9caf0111::MetaRenamer215321986feSArthur Eubanks bool runOnModule(Module &M) override {
216321986feSArthur Eubanks auto GetTLI = [this](Function &F) -> TargetLibraryInfo & {
217321986feSArthur Eubanks return this->getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
218321986feSArthur Eubanks };
219321986feSArthur Eubanks MetaRename(M, GetTLI);
220a373d18eSDavid Blaikie return true;
221a373d18eSDavid Blaikie }
222a373d18eSDavid Blaikie };
223a373d18eSDavid Blaikie
224a373d18eSDavid Blaikie } // end anonymous namespace
225a373d18eSDavid Blaikie
226a373d18eSDavid Blaikie char MetaRenamer::ID = 0;
227a373d18eSDavid Blaikie
228a373d18eSDavid Blaikie INITIALIZE_PASS_BEGIN(MetaRenamer, "metarenamer",
229a373d18eSDavid Blaikie "Assign new names to everything", false, false)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)230a373d18eSDavid Blaikie INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
231a373d18eSDavid Blaikie INITIALIZE_PASS_END(MetaRenamer, "metarenamer",
232a373d18eSDavid Blaikie "Assign new names to everything", false, false)
233a373d18eSDavid Blaikie
234a373d18eSDavid Blaikie //===----------------------------------------------------------------------===//
235a373d18eSDavid Blaikie //
236a373d18eSDavid Blaikie // MetaRenamer - Rename everything with metasyntactic names.
237a373d18eSDavid Blaikie //
238a373d18eSDavid Blaikie ModulePass *llvm::createMetaRenamerPass() {
239a373d18eSDavid Blaikie return new MetaRenamer();
240a373d18eSDavid Blaikie }
241321986feSArthur Eubanks
run(Module & M,ModuleAnalysisManager & AM)242321986feSArthur Eubanks PreservedAnalyses MetaRenamerPass::run(Module &M, ModuleAnalysisManager &AM) {
243321986feSArthur Eubanks FunctionAnalysisManager &FAM =
244321986feSArthur Eubanks AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
245321986feSArthur Eubanks auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & {
246321986feSArthur Eubanks return FAM.getResult<TargetLibraryAnalysis>(F);
247321986feSArthur Eubanks };
248321986feSArthur Eubanks MetaRename(M, GetTLI);
249321986feSArthur Eubanks
250321986feSArthur Eubanks return PreservedAnalyses::all();
251321986feSArthur Eubanks }
252