xref: /freebsd-src/contrib/llvm-project/llvm/lib/Transforms/Utils/MetaRenamer.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
10b57cec5SDimitry Andric //===- MetaRenamer.cpp - Rename everything with metasyntatic names --------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This pass renames everything with metasyntatic names. The intent is to use
100b57cec5SDimitry Andric // this pass after bugpoint reduction to conceal the nature of the original
110b57cec5SDimitry Andric // program.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
15e8d8bef9SDimitry Andric #include "llvm/Transforms/Utils/MetaRenamer.h"
160b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
170b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
180eae32dcSDimitry Andric #include "llvm/ADT/SmallVector.h"
190b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
200b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
210b57cec5SDimitry Andric #include "llvm/Analysis/TargetLibraryInfo.h"
220b57cec5SDimitry Andric #include "llvm/IR/Argument.h"
230b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
240b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
250b57cec5SDimitry Andric #include "llvm/IR/Function.h"
260b57cec5SDimitry Andric #include "llvm/IR/GlobalAlias.h"
270b57cec5SDimitry Andric #include "llvm/IR/GlobalVariable.h"
280b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
2906c3fb27SDimitry Andric #include "llvm/IR/InstIterator.h"
300b57cec5SDimitry Andric #include "llvm/IR/Module.h"
31e8d8bef9SDimitry Andric #include "llvm/IR/PassManager.h"
320b57cec5SDimitry Andric #include "llvm/IR/Type.h"
330b57cec5SDimitry Andric #include "llvm/IR/TypeFinder.h"
340eae32dcSDimitry Andric #include "llvm/Support/CommandLine.h"
350b57cec5SDimitry Andric 
360b57cec5SDimitry Andric using namespace llvm;
370b57cec5SDimitry Andric 
380eae32dcSDimitry Andric static cl::opt<std::string> RenameExcludeFunctionPrefixes(
390eae32dcSDimitry Andric     "rename-exclude-function-prefixes",
400eae32dcSDimitry Andric     cl::desc("Prefixes for functions that don't need to be renamed, separated "
410eae32dcSDimitry Andric              "by a comma"),
420eae32dcSDimitry Andric     cl::Hidden);
430eae32dcSDimitry Andric 
440eae32dcSDimitry Andric static cl::opt<std::string> RenameExcludeAliasPrefixes(
450eae32dcSDimitry Andric     "rename-exclude-alias-prefixes",
460eae32dcSDimitry Andric     cl::desc("Prefixes for aliases that don't need to be renamed, separated "
470eae32dcSDimitry Andric              "by a comma"),
480eae32dcSDimitry Andric     cl::Hidden);
490eae32dcSDimitry Andric 
500eae32dcSDimitry Andric static cl::opt<std::string> RenameExcludeGlobalPrefixes(
510eae32dcSDimitry Andric     "rename-exclude-global-prefixes",
520eae32dcSDimitry Andric     cl::desc(
530eae32dcSDimitry Andric         "Prefixes for global values that don't need to be renamed, separated "
540eae32dcSDimitry Andric         "by a comma"),
550eae32dcSDimitry Andric     cl::Hidden);
560eae32dcSDimitry Andric 
570eae32dcSDimitry Andric static cl::opt<std::string> RenameExcludeStructPrefixes(
580eae32dcSDimitry Andric     "rename-exclude-struct-prefixes",
590eae32dcSDimitry Andric     cl::desc("Prefixes for structs that don't need to be renamed, separated "
600eae32dcSDimitry Andric              "by a comma"),
610eae32dcSDimitry Andric     cl::Hidden);
620eae32dcSDimitry Andric 
6306c3fb27SDimitry Andric static cl::opt<bool>
6406c3fb27SDimitry Andric     RenameOnlyInst("rename-only-inst", cl::init(false),
6506c3fb27SDimitry Andric                    cl::desc("only rename the instructions in the function"),
6606c3fb27SDimitry Andric                    cl::Hidden);
6706c3fb27SDimitry Andric 
680b57cec5SDimitry Andric static const char *const metaNames[] = {
690b57cec5SDimitry Andric   // See http://en.wikipedia.org/wiki/Metasyntactic_variable
700b57cec5SDimitry Andric   "foo", "bar", "baz", "quux", "barney", "snork", "zot", "blam", "hoge",
710b57cec5SDimitry Andric   "wibble", "wobble", "widget", "wombat", "ham", "eggs", "pluto", "spam"
720b57cec5SDimitry Andric };
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric namespace {
750b57cec5SDimitry Andric // This PRNG is from the ISO C spec. It is intentionally simple and
760b57cec5SDimitry Andric // unsuitable for cryptographic use. We're just looking for enough
770b57cec5SDimitry Andric // variety to surprise and delight users.
780b57cec5SDimitry Andric struct PRNG {
790b57cec5SDimitry Andric   unsigned long next;
800b57cec5SDimitry Andric 
srand__anonbc5a2a510111::PRNG81e8d8bef9SDimitry Andric   void srand(unsigned int seed) { next = seed; }
820b57cec5SDimitry Andric 
rand__anonbc5a2a510111::PRNG830b57cec5SDimitry Andric   int rand() {
840b57cec5SDimitry Andric     next = next * 1103515245 + 12345;
850b57cec5SDimitry Andric     return (unsigned int)(next / 65536) % 32768;
860b57cec5SDimitry Andric   }
870b57cec5SDimitry Andric };
880b57cec5SDimitry Andric 
890b57cec5SDimitry Andric struct Renamer {
Renamer__anonbc5a2a510111::Renamer90e8d8bef9SDimitry Andric   Renamer(unsigned int seed) { prng.srand(seed); }
910b57cec5SDimitry Andric 
newName__anonbc5a2a510111::Renamer920b57cec5SDimitry Andric   const char *newName() {
93bdd1243dSDimitry Andric     return metaNames[prng.rand() % std::size(metaNames)];
940b57cec5SDimitry Andric   }
950b57cec5SDimitry Andric 
960b57cec5SDimitry Andric   PRNG prng;
970b57cec5SDimitry Andric };
980b57cec5SDimitry Andric 
990eae32dcSDimitry Andric static void
parseExcludedPrefixes(StringRef PrefixesStr,SmallVectorImpl<StringRef> & ExcludedPrefixes)1000eae32dcSDimitry Andric parseExcludedPrefixes(StringRef PrefixesStr,
1010eae32dcSDimitry Andric                       SmallVectorImpl<StringRef> &ExcludedPrefixes) {
1020eae32dcSDimitry Andric   for (;;) {
1030eae32dcSDimitry Andric     auto PrefixesSplit = PrefixesStr.split(',');
1040eae32dcSDimitry Andric     if (PrefixesSplit.first.empty())
1050eae32dcSDimitry Andric       break;
1060eae32dcSDimitry Andric     ExcludedPrefixes.push_back(PrefixesSplit.first);
1070eae32dcSDimitry Andric     PrefixesStr = PrefixesSplit.second;
1080eae32dcSDimitry Andric   }
1090eae32dcSDimitry Andric }
1100eae32dcSDimitry Andric 
MetaRenameOnlyInstructions(Function & F)11106c3fb27SDimitry Andric void MetaRenameOnlyInstructions(Function &F) {
11206c3fb27SDimitry Andric   for (auto &I : instructions(F))
11306c3fb27SDimitry Andric     if (!I.getType()->isVoidTy() && I.getName().empty())
11406c3fb27SDimitry Andric       I.setName(I.getOpcodeName());
11506c3fb27SDimitry Andric }
11606c3fb27SDimitry Andric 
MetaRename(Function & F)117e8d8bef9SDimitry Andric void MetaRename(Function &F) {
118fe6060f1SDimitry Andric   for (Argument &Arg : F.args())
119fe6060f1SDimitry Andric     if (!Arg.getType()->isVoidTy())
120fe6060f1SDimitry Andric       Arg.setName("arg");
1210b57cec5SDimitry Andric 
122e8d8bef9SDimitry Andric   for (auto &BB : F) {
123e8d8bef9SDimitry Andric     BB.setName("bb");
124e8d8bef9SDimitry Andric 
125e8d8bef9SDimitry Andric     for (auto &I : BB)
126e8d8bef9SDimitry Andric       if (!I.getType()->isVoidTy())
12706c3fb27SDimitry Andric         I.setName(I.getOpcodeName());
128e8d8bef9SDimitry Andric   }
1290b57cec5SDimitry Andric }
1300b57cec5SDimitry Andric 
MetaRename(Module & M,function_ref<TargetLibraryInfo & (Function &)> GetTLI)131e8d8bef9SDimitry Andric void MetaRename(Module &M,
132e8d8bef9SDimitry Andric                 function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
1330b57cec5SDimitry Andric   // Seed our PRNG with simple additive sum of ModuleID. We're looking to
1340b57cec5SDimitry Andric   // simply avoid always having the same function names, and we need to
1350b57cec5SDimitry Andric   // remain deterministic.
1360b57cec5SDimitry Andric   unsigned int randSeed = 0;
1370b57cec5SDimitry Andric   for (auto C : M.getModuleIdentifier())
1380b57cec5SDimitry Andric     randSeed += C;
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   Renamer renamer(randSeed);
1410b57cec5SDimitry Andric 
1420eae32dcSDimitry Andric   SmallVector<StringRef, 8> ExcludedAliasesPrefixes;
1430eae32dcSDimitry Andric   SmallVector<StringRef, 8> ExcludedGlobalsPrefixes;
1440eae32dcSDimitry Andric   SmallVector<StringRef, 8> ExcludedStructsPrefixes;
1450eae32dcSDimitry Andric   SmallVector<StringRef, 8> ExcludedFuncPrefixes;
1460eae32dcSDimitry Andric   parseExcludedPrefixes(RenameExcludeAliasPrefixes, ExcludedAliasesPrefixes);
1470eae32dcSDimitry Andric   parseExcludedPrefixes(RenameExcludeGlobalPrefixes, ExcludedGlobalsPrefixes);
1480eae32dcSDimitry Andric   parseExcludedPrefixes(RenameExcludeStructPrefixes, ExcludedStructsPrefixes);
1490eae32dcSDimitry Andric   parseExcludedPrefixes(RenameExcludeFunctionPrefixes, ExcludedFuncPrefixes);
1500eae32dcSDimitry Andric 
1510eae32dcSDimitry Andric   auto IsNameExcluded = [](StringRef &Name,
1520eae32dcSDimitry Andric                            SmallVectorImpl<StringRef> &ExcludedPrefixes) {
1530eae32dcSDimitry Andric     return any_of(ExcludedPrefixes,
154*5f757f3fSDimitry Andric                   [&Name](auto &Prefix) { return Name.starts_with(Prefix); });
1550eae32dcSDimitry Andric   };
1560eae32dcSDimitry Andric 
15706c3fb27SDimitry Andric   // Leave library functions alone because their presence or absence could
15806c3fb27SDimitry Andric   // affect the behavior of other passes.
15906c3fb27SDimitry Andric   auto ExcludeLibFuncs = [&](Function &F) {
16006c3fb27SDimitry Andric     LibFunc Tmp;
16106c3fb27SDimitry Andric     StringRef Name = F.getName();
162*5f757f3fSDimitry Andric     return Name.starts_with("llvm.") || (!Name.empty() && Name[0] == 1) ||
16306c3fb27SDimitry Andric            GetTLI(F).getLibFunc(F, Tmp) ||
16406c3fb27SDimitry Andric            IsNameExcluded(Name, ExcludedFuncPrefixes);
16506c3fb27SDimitry Andric   };
16606c3fb27SDimitry Andric 
16706c3fb27SDimitry Andric   if (RenameOnlyInst) {
16806c3fb27SDimitry Andric     // Rename all functions
16906c3fb27SDimitry Andric     for (auto &F : M) {
17006c3fb27SDimitry Andric       if (ExcludeLibFuncs(F))
17106c3fb27SDimitry Andric         continue;
17206c3fb27SDimitry Andric       MetaRenameOnlyInstructions(F);
17306c3fb27SDimitry Andric     }
17406c3fb27SDimitry Andric     return;
17506c3fb27SDimitry Andric   }
17606c3fb27SDimitry Andric 
1770b57cec5SDimitry Andric   // Rename all aliases
1785e801ac6SDimitry Andric   for (GlobalAlias &GA : M.aliases()) {
1795e801ac6SDimitry Andric     StringRef Name = GA.getName();
180*5f757f3fSDimitry Andric     if (Name.starts_with("llvm.") || (!Name.empty() && Name[0] == 1) ||
1810eae32dcSDimitry Andric         IsNameExcluded(Name, ExcludedAliasesPrefixes))
1820b57cec5SDimitry Andric       continue;
1830b57cec5SDimitry Andric 
1845e801ac6SDimitry Andric     GA.setName("alias");
1850b57cec5SDimitry Andric   }
1860b57cec5SDimitry Andric 
1870b57cec5SDimitry Andric   // Rename all global variables
188fe6060f1SDimitry Andric   for (GlobalVariable &GV : M.globals()) {
189fe6060f1SDimitry Andric     StringRef Name = GV.getName();
190*5f757f3fSDimitry Andric     if (Name.starts_with("llvm.") || (!Name.empty() && Name[0] == 1) ||
1910eae32dcSDimitry Andric         IsNameExcluded(Name, ExcludedGlobalsPrefixes))
1920b57cec5SDimitry Andric       continue;
1930b57cec5SDimitry Andric 
194fe6060f1SDimitry Andric     GV.setName("global");
1950b57cec5SDimitry Andric   }
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   // Rename all struct types
1980b57cec5SDimitry Andric   TypeFinder StructTypes;
1990b57cec5SDimitry Andric   StructTypes.run(M, true);
2000b57cec5SDimitry Andric   for (StructType *STy : StructTypes) {
2010eae32dcSDimitry Andric     StringRef Name = STy->getName();
2020eae32dcSDimitry Andric     if (STy->isLiteral() || Name.empty() ||
2030eae32dcSDimitry Andric         IsNameExcluded(Name, ExcludedStructsPrefixes))
204e8d8bef9SDimitry Andric       continue;
2050b57cec5SDimitry Andric 
2060b57cec5SDimitry Andric     SmallString<128> NameStorage;
207e8d8bef9SDimitry Andric     STy->setName(
208e8d8bef9SDimitry Andric         (Twine("struct.") + renamer.newName()).toStringRef(NameStorage));
2090b57cec5SDimitry Andric   }
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   // Rename all functions
2120b57cec5SDimitry Andric   for (auto &F : M) {
21306c3fb27SDimitry Andric     if (ExcludeLibFuncs(F))
2140b57cec5SDimitry Andric       continue;
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric     // Leave @main alone. The output of -metarenamer might be passed to
2170b57cec5SDimitry Andric     // lli for execution and the latter needs a main entry point.
21806c3fb27SDimitry Andric     if (F.getName() != "main")
2190b57cec5SDimitry Andric       F.setName(renamer.newName());
2200b57cec5SDimitry Andric 
221e8d8bef9SDimitry Andric     MetaRename(F);
2220b57cec5SDimitry Andric   }
2230b57cec5SDimitry Andric }
2240b57cec5SDimitry Andric 
2250b57cec5SDimitry Andric } // end anonymous namespace
2260b57cec5SDimitry Andric 
run(Module & M,ModuleAnalysisManager & AM)227e8d8bef9SDimitry Andric PreservedAnalyses MetaRenamerPass::run(Module &M, ModuleAnalysisManager &AM) {
228e8d8bef9SDimitry Andric   FunctionAnalysisManager &FAM =
229e8d8bef9SDimitry Andric       AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
230e8d8bef9SDimitry Andric   auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & {
231e8d8bef9SDimitry Andric     return FAM.getResult<TargetLibraryAnalysis>(F);
232e8d8bef9SDimitry Andric   };
233e8d8bef9SDimitry Andric   MetaRename(M, GetTLI);
234e8d8bef9SDimitry Andric 
235e8d8bef9SDimitry Andric   return PreservedAnalyses::all();
236e8d8bef9SDimitry Andric }
237