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