xref: /openbsd-src/gnu/llvm/llvm/lib/Transforms/Utils/MetaRenamer.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
109467b48Spatrick //===- MetaRenamer.cpp - Rename everything with metasyntatic names --------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick //
909467b48Spatrick // This pass renames everything with metasyntatic names. The intent is to use
1009467b48Spatrick // this pass after bugpoint reduction to conceal the nature of the original
1109467b48Spatrick // program.
1209467b48Spatrick //
1309467b48Spatrick //===----------------------------------------------------------------------===//
1409467b48Spatrick 
1573471bf0Spatrick #include "llvm/Transforms/Utils/MetaRenamer.h"
1609467b48Spatrick #include "llvm/ADT/STLExtras.h"
1709467b48Spatrick #include "llvm/ADT/SmallString.h"
18*d415bd75Srobert #include "llvm/ADT/SmallVector.h"
1909467b48Spatrick #include "llvm/ADT/StringRef.h"
2009467b48Spatrick #include "llvm/ADT/Twine.h"
2109467b48Spatrick #include "llvm/Analysis/TargetLibraryInfo.h"
2209467b48Spatrick #include "llvm/IR/Argument.h"
2309467b48Spatrick #include "llvm/IR/BasicBlock.h"
2409467b48Spatrick #include "llvm/IR/DerivedTypes.h"
2509467b48Spatrick #include "llvm/IR/Function.h"
2609467b48Spatrick #include "llvm/IR/GlobalAlias.h"
2709467b48Spatrick #include "llvm/IR/GlobalVariable.h"
2809467b48Spatrick #include "llvm/IR/Instruction.h"
2909467b48Spatrick #include "llvm/IR/Module.h"
3073471bf0Spatrick #include "llvm/IR/PassManager.h"
3109467b48Spatrick #include "llvm/IR/Type.h"
3209467b48Spatrick #include "llvm/IR/TypeFinder.h"
3309467b48Spatrick #include "llvm/InitializePasses.h"
3409467b48Spatrick #include "llvm/Pass.h"
35*d415bd75Srobert #include "llvm/Support/CommandLine.h"
3609467b48Spatrick #include "llvm/Transforms/Utils.h"
3709467b48Spatrick 
3809467b48Spatrick using namespace llvm;
3909467b48Spatrick 
40*d415bd75Srobert static cl::opt<std::string> RenameExcludeFunctionPrefixes(
41*d415bd75Srobert     "rename-exclude-function-prefixes",
42*d415bd75Srobert     cl::desc("Prefixes for functions that don't need to be renamed, separated "
43*d415bd75Srobert              "by a comma"),
44*d415bd75Srobert     cl::Hidden);
45*d415bd75Srobert 
46*d415bd75Srobert static cl::opt<std::string> RenameExcludeAliasPrefixes(
47*d415bd75Srobert     "rename-exclude-alias-prefixes",
48*d415bd75Srobert     cl::desc("Prefixes for aliases that don't need to be renamed, separated "
49*d415bd75Srobert              "by a comma"),
50*d415bd75Srobert     cl::Hidden);
51*d415bd75Srobert 
52*d415bd75Srobert static cl::opt<std::string> RenameExcludeGlobalPrefixes(
53*d415bd75Srobert     "rename-exclude-global-prefixes",
54*d415bd75Srobert     cl::desc(
55*d415bd75Srobert         "Prefixes for global values that don't need to be renamed, separated "
56*d415bd75Srobert         "by a comma"),
57*d415bd75Srobert     cl::Hidden);
58*d415bd75Srobert 
59*d415bd75Srobert static cl::opt<std::string> RenameExcludeStructPrefixes(
60*d415bd75Srobert     "rename-exclude-struct-prefixes",
61*d415bd75Srobert     cl::desc("Prefixes for structs that don't need to be renamed, separated "
62*d415bd75Srobert              "by a comma"),
63*d415bd75Srobert     cl::Hidden);
64*d415bd75Srobert 
6509467b48Spatrick static const char *const metaNames[] = {
6609467b48Spatrick   // See http://en.wikipedia.org/wiki/Metasyntactic_variable
6709467b48Spatrick   "foo", "bar", "baz", "quux", "barney", "snork", "zot", "blam", "hoge",
6809467b48Spatrick   "wibble", "wobble", "widget", "wombat", "ham", "eggs", "pluto", "spam"
6909467b48Spatrick };
7009467b48Spatrick 
7109467b48Spatrick namespace {
7209467b48Spatrick // This PRNG is from the ISO C spec. It is intentionally simple and
7309467b48Spatrick // unsuitable for cryptographic use. We're just looking for enough
7409467b48Spatrick // variety to surprise and delight users.
7509467b48Spatrick struct PRNG {
7609467b48Spatrick   unsigned long next;
7709467b48Spatrick 
srand__anon4d72f7160111::PRNG7873471bf0Spatrick   void srand(unsigned int seed) { next = seed; }
7909467b48Spatrick 
rand__anon4d72f7160111::PRNG8009467b48Spatrick   int rand() {
8109467b48Spatrick     next = next * 1103515245 + 12345;
8209467b48Spatrick     return (unsigned int)(next / 65536) % 32768;
8309467b48Spatrick   }
8409467b48Spatrick };
8509467b48Spatrick 
8609467b48Spatrick struct Renamer {
Renamer__anon4d72f7160111::Renamer8773471bf0Spatrick   Renamer(unsigned int seed) { prng.srand(seed); }
8809467b48Spatrick 
newName__anon4d72f7160111::Renamer8909467b48Spatrick   const char *newName() {
90*d415bd75Srobert     return metaNames[prng.rand() % std::size(metaNames)];
9109467b48Spatrick   }
9209467b48Spatrick 
9309467b48Spatrick   PRNG prng;
9409467b48Spatrick };
9509467b48Spatrick 
96*d415bd75Srobert static void
parseExcludedPrefixes(StringRef PrefixesStr,SmallVectorImpl<StringRef> & ExcludedPrefixes)97*d415bd75Srobert parseExcludedPrefixes(StringRef PrefixesStr,
98*d415bd75Srobert                       SmallVectorImpl<StringRef> &ExcludedPrefixes) {
99*d415bd75Srobert   for (;;) {
100*d415bd75Srobert     auto PrefixesSplit = PrefixesStr.split(',');
101*d415bd75Srobert     if (PrefixesSplit.first.empty())
102*d415bd75Srobert       break;
103*d415bd75Srobert     ExcludedPrefixes.push_back(PrefixesSplit.first);
104*d415bd75Srobert     PrefixesStr = PrefixesSplit.second;
105*d415bd75Srobert   }
106*d415bd75Srobert }
107*d415bd75Srobert 
MetaRename(Function & F)10873471bf0Spatrick void MetaRename(Function &F) {
10973471bf0Spatrick   for (Argument &Arg : F.args())
11073471bf0Spatrick     if (!Arg.getType()->isVoidTy())
11173471bf0Spatrick       Arg.setName("arg");
11209467b48Spatrick 
11373471bf0Spatrick   for (auto &BB : F) {
11473471bf0Spatrick     BB.setName("bb");
11573471bf0Spatrick 
11673471bf0Spatrick     for (auto &I : BB)
11773471bf0Spatrick       if (!I.getType()->isVoidTy())
11873471bf0Spatrick         I.setName("tmp");
11973471bf0Spatrick   }
12009467b48Spatrick }
12109467b48Spatrick 
MetaRename(Module & M,function_ref<TargetLibraryInfo & (Function &)> GetTLI)12273471bf0Spatrick void MetaRename(Module &M,
12373471bf0Spatrick                 function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
12409467b48Spatrick   // Seed our PRNG with simple additive sum of ModuleID. We're looking to
12509467b48Spatrick   // simply avoid always having the same function names, and we need to
12609467b48Spatrick   // remain deterministic.
12709467b48Spatrick   unsigned int randSeed = 0;
12809467b48Spatrick   for (auto C : M.getModuleIdentifier())
12909467b48Spatrick     randSeed += C;
13009467b48Spatrick 
13109467b48Spatrick   Renamer renamer(randSeed);
13209467b48Spatrick 
133*d415bd75Srobert   SmallVector<StringRef, 8> ExcludedAliasesPrefixes;
134*d415bd75Srobert   SmallVector<StringRef, 8> ExcludedGlobalsPrefixes;
135*d415bd75Srobert   SmallVector<StringRef, 8> ExcludedStructsPrefixes;
136*d415bd75Srobert   SmallVector<StringRef, 8> ExcludedFuncPrefixes;
137*d415bd75Srobert   parseExcludedPrefixes(RenameExcludeAliasPrefixes, ExcludedAliasesPrefixes);
138*d415bd75Srobert   parseExcludedPrefixes(RenameExcludeGlobalPrefixes, ExcludedGlobalsPrefixes);
139*d415bd75Srobert   parseExcludedPrefixes(RenameExcludeStructPrefixes, ExcludedStructsPrefixes);
140*d415bd75Srobert   parseExcludedPrefixes(RenameExcludeFunctionPrefixes, ExcludedFuncPrefixes);
141*d415bd75Srobert 
142*d415bd75Srobert   auto IsNameExcluded = [](StringRef &Name,
143*d415bd75Srobert                            SmallVectorImpl<StringRef> &ExcludedPrefixes) {
144*d415bd75Srobert     return any_of(ExcludedPrefixes,
145*d415bd75Srobert                   [&Name](auto &Prefix) { return Name.startswith(Prefix); });
146*d415bd75Srobert   };
147*d415bd75Srobert 
14809467b48Spatrick   // Rename all aliases
149*d415bd75Srobert   for (GlobalAlias &GA : M.aliases()) {
150*d415bd75Srobert     StringRef Name = GA.getName();
151*d415bd75Srobert     if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
152*d415bd75Srobert         IsNameExcluded(Name, ExcludedAliasesPrefixes))
15309467b48Spatrick       continue;
15409467b48Spatrick 
155*d415bd75Srobert     GA.setName("alias");
15609467b48Spatrick   }
15709467b48Spatrick 
15809467b48Spatrick   // Rename all global variables
15973471bf0Spatrick   for (GlobalVariable &GV : M.globals()) {
16073471bf0Spatrick     StringRef Name = GV.getName();
161*d415bd75Srobert     if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
162*d415bd75Srobert         IsNameExcluded(Name, ExcludedGlobalsPrefixes))
16309467b48Spatrick       continue;
16409467b48Spatrick 
16573471bf0Spatrick     GV.setName("global");
16609467b48Spatrick   }
16709467b48Spatrick 
16809467b48Spatrick   // Rename all struct types
16909467b48Spatrick   TypeFinder StructTypes;
17009467b48Spatrick   StructTypes.run(M, true);
17109467b48Spatrick   for (StructType *STy : StructTypes) {
172*d415bd75Srobert     StringRef Name = STy->getName();
173*d415bd75Srobert     if (STy->isLiteral() || Name.empty() ||
174*d415bd75Srobert         IsNameExcluded(Name, ExcludedStructsPrefixes))
17573471bf0Spatrick       continue;
17609467b48Spatrick 
17709467b48Spatrick     SmallString<128> NameStorage;
17873471bf0Spatrick     STy->setName(
17973471bf0Spatrick         (Twine("struct.") + renamer.newName()).toStringRef(NameStorage));
18009467b48Spatrick   }
18109467b48Spatrick 
18209467b48Spatrick   // Rename all functions
18309467b48Spatrick   for (auto &F : M) {
18409467b48Spatrick     StringRef Name = F.getName();
18509467b48Spatrick     LibFunc Tmp;
18609467b48Spatrick     // Leave library functions alone because their presence or absence could
18709467b48Spatrick     // affect the behavior of other passes.
18809467b48Spatrick     if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
189*d415bd75Srobert         GetTLI(F).getLibFunc(F, Tmp) ||
190*d415bd75Srobert         IsNameExcluded(Name, ExcludedFuncPrefixes))
19109467b48Spatrick       continue;
19209467b48Spatrick 
19309467b48Spatrick     // Leave @main alone. The output of -metarenamer might be passed to
19409467b48Spatrick     // lli for execution and the latter needs a main entry point.
19509467b48Spatrick     if (Name != "main")
19609467b48Spatrick       F.setName(renamer.newName());
19709467b48Spatrick 
19873471bf0Spatrick     MetaRename(F);
19909467b48Spatrick   }
20009467b48Spatrick }
20109467b48Spatrick 
20273471bf0Spatrick struct MetaRenamer : public ModulePass {
20373471bf0Spatrick   // Pass identification, replacement for typeid
20473471bf0Spatrick   static char ID;
20509467b48Spatrick 
MetaRenamer__anon4d72f7160111::MetaRenamer20673471bf0Spatrick   MetaRenamer() : ModulePass(ID) {
20773471bf0Spatrick     initializeMetaRenamerPass(*PassRegistry::getPassRegistry());
20809467b48Spatrick   }
20973471bf0Spatrick 
getAnalysisUsage__anon4d72f7160111::MetaRenamer21073471bf0Spatrick   void getAnalysisUsage(AnalysisUsage &AU) const override {
21173471bf0Spatrick     AU.addRequired<TargetLibraryInfoWrapperPass>();
21273471bf0Spatrick     AU.setPreservesAll();
21373471bf0Spatrick   }
21473471bf0Spatrick 
runOnModule__anon4d72f7160111::MetaRenamer21573471bf0Spatrick   bool runOnModule(Module &M) override {
21673471bf0Spatrick     auto GetTLI = [this](Function &F) -> TargetLibraryInfo & {
21773471bf0Spatrick       return this->getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
21873471bf0Spatrick     };
21973471bf0Spatrick     MetaRename(M, GetTLI);
22009467b48Spatrick     return true;
22109467b48Spatrick   }
22209467b48Spatrick };
22309467b48Spatrick 
22409467b48Spatrick } // end anonymous namespace
22509467b48Spatrick 
22609467b48Spatrick char MetaRenamer::ID = 0;
22709467b48Spatrick 
22809467b48Spatrick INITIALIZE_PASS_BEGIN(MetaRenamer, "metarenamer",
22909467b48Spatrick                       "Assign new names to everything", false, false)
INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)23009467b48Spatrick INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
23109467b48Spatrick INITIALIZE_PASS_END(MetaRenamer, "metarenamer",
23209467b48Spatrick                     "Assign new names to everything", false, false)
23309467b48Spatrick 
23409467b48Spatrick //===----------------------------------------------------------------------===//
23509467b48Spatrick //
23609467b48Spatrick // MetaRenamer - Rename everything with metasyntactic names.
23709467b48Spatrick //
23809467b48Spatrick ModulePass *llvm::createMetaRenamerPass() {
23909467b48Spatrick   return new MetaRenamer();
24009467b48Spatrick }
24173471bf0Spatrick 
run(Module & M,ModuleAnalysisManager & AM)24273471bf0Spatrick PreservedAnalyses MetaRenamerPass::run(Module &M, ModuleAnalysisManager &AM) {
24373471bf0Spatrick   FunctionAnalysisManager &FAM =
24473471bf0Spatrick       AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
24573471bf0Spatrick   auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & {
24673471bf0Spatrick     return FAM.getResult<TargetLibraryAnalysis>(F);
24773471bf0Spatrick   };
24873471bf0Spatrick   MetaRename(M, GetTLI);
24973471bf0Spatrick 
25073471bf0Spatrick   return PreservedAnalyses::all();
25173471bf0Spatrick }
252