xref: /freebsd/contrib/llvm-project/llvm/lib/Transforms/Utils/MetaRenamer.cpp (revision ec0ea6efa1ad229d75c394c1a9b9cac33af2b1d3)
1 //===- MetaRenamer.cpp - Rename everything with metasyntatic names --------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This pass renames everything with metasyntatic names. The intent is to use
10 // this pass after bugpoint reduction to conceal the nature of the original
11 // program.
12 //
13 //===----------------------------------------------------------------------===//
14 
15 #include "llvm/Transforms/Utils/MetaRenamer.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/SmallString.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ADT/Twine.h"
20 #include "llvm/Analysis/TargetLibraryInfo.h"
21 #include "llvm/IR/Argument.h"
22 #include "llvm/IR/BasicBlock.h"
23 #include "llvm/IR/DerivedTypes.h"
24 #include "llvm/IR/Function.h"
25 #include "llvm/IR/GlobalAlias.h"
26 #include "llvm/IR/GlobalVariable.h"
27 #include "llvm/IR/Instruction.h"
28 #include "llvm/IR/Module.h"
29 #include "llvm/IR/PassManager.h"
30 #include "llvm/IR/Type.h"
31 #include "llvm/IR/TypeFinder.h"
32 #include "llvm/InitializePasses.h"
33 #include "llvm/Pass.h"
34 #include "llvm/Transforms/Utils.h"
35 
36 using namespace llvm;
37 
38 static const char *const metaNames[] = {
39   // See http://en.wikipedia.org/wiki/Metasyntactic_variable
40   "foo", "bar", "baz", "quux", "barney", "snork", "zot", "blam", "hoge",
41   "wibble", "wobble", "widget", "wombat", "ham", "eggs", "pluto", "spam"
42 };
43 
44 namespace {
45 // This PRNG is from the ISO C spec. It is intentionally simple and
46 // unsuitable for cryptographic use. We're just looking for enough
47 // variety to surprise and delight users.
48 struct PRNG {
49   unsigned long next;
50 
51   void srand(unsigned int seed) { next = seed; }
52 
53   int rand() {
54     next = next * 1103515245 + 12345;
55     return (unsigned int)(next / 65536) % 32768;
56   }
57 };
58 
59 struct Renamer {
60   Renamer(unsigned int seed) { prng.srand(seed); }
61 
62   const char *newName() {
63     return metaNames[prng.rand() % array_lengthof(metaNames)];
64   }
65 
66   PRNG prng;
67 };
68 
69 void MetaRename(Function &F) {
70   for (Argument &Arg : F.args())
71     if (!Arg.getType()->isVoidTy())
72       Arg.setName("arg");
73 
74   for (auto &BB : F) {
75     BB.setName("bb");
76 
77     for (auto &I : BB)
78       if (!I.getType()->isVoidTy())
79         I.setName("tmp");
80   }
81 }
82 
83 void MetaRename(Module &M,
84                 function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
85   // Seed our PRNG with simple additive sum of ModuleID. We're looking to
86   // simply avoid always having the same function names, and we need to
87   // remain deterministic.
88   unsigned int randSeed = 0;
89   for (auto C : M.getModuleIdentifier())
90     randSeed += C;
91 
92   Renamer renamer(randSeed);
93 
94   // Rename all aliases
95   for (auto AI = M.alias_begin(), AE = M.alias_end(); AI != AE; ++AI) {
96     StringRef Name = AI->getName();
97     if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1))
98       continue;
99 
100     AI->setName("alias");
101   }
102 
103   // Rename all global variables
104   for (GlobalVariable &GV : M.globals()) {
105     StringRef Name = GV.getName();
106     if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1))
107       continue;
108 
109     GV.setName("global");
110   }
111 
112   // Rename all struct types
113   TypeFinder StructTypes;
114   StructTypes.run(M, true);
115   for (StructType *STy : StructTypes) {
116     if (STy->isLiteral() || STy->getName().empty())
117       continue;
118 
119     SmallString<128> NameStorage;
120     STy->setName(
121         (Twine("struct.") + renamer.newName()).toStringRef(NameStorage));
122   }
123 
124   // Rename all functions
125   for (auto &F : M) {
126     StringRef Name = F.getName();
127     LibFunc Tmp;
128     // Leave library functions alone because their presence or absence could
129     // affect the behavior of other passes.
130     if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
131         GetTLI(F).getLibFunc(F, Tmp))
132       continue;
133 
134     // Leave @main alone. The output of -metarenamer might be passed to
135     // lli for execution and the latter needs a main entry point.
136     if (Name != "main")
137       F.setName(renamer.newName());
138 
139     MetaRename(F);
140   }
141 }
142 
143 struct MetaRenamer : public ModulePass {
144   // Pass identification, replacement for typeid
145   static char ID;
146 
147   MetaRenamer() : ModulePass(ID) {
148     initializeMetaRenamerPass(*PassRegistry::getPassRegistry());
149   }
150 
151   void getAnalysisUsage(AnalysisUsage &AU) const override {
152     AU.addRequired<TargetLibraryInfoWrapperPass>();
153     AU.setPreservesAll();
154   }
155 
156   bool runOnModule(Module &M) override {
157     auto GetTLI = [this](Function &F) -> TargetLibraryInfo & {
158       return this->getAnalysis<TargetLibraryInfoWrapperPass>().getTLI(F);
159     };
160     MetaRename(M, GetTLI);
161     return true;
162   }
163 };
164 
165 } // end anonymous namespace
166 
167 char MetaRenamer::ID = 0;
168 
169 INITIALIZE_PASS_BEGIN(MetaRenamer, "metarenamer",
170                       "Assign new names to everything", false, false)
171 INITIALIZE_PASS_DEPENDENCY(TargetLibraryInfoWrapperPass)
172 INITIALIZE_PASS_END(MetaRenamer, "metarenamer",
173                     "Assign new names to everything", false, false)
174 
175 //===----------------------------------------------------------------------===//
176 //
177 // MetaRenamer - Rename everything with metasyntactic names.
178 //
179 ModulePass *llvm::createMetaRenamerPass() {
180   return new MetaRenamer();
181 }
182 
183 PreservedAnalyses MetaRenamerPass::run(Module &M, ModuleAnalysisManager &AM) {
184   FunctionAnalysisManager &FAM =
185       AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
186   auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & {
187     return FAM.getResult<TargetLibraryAnalysis>(F);
188   };
189   MetaRename(M, GetTLI);
190 
191   return PreservedAnalyses::all();
192 }
193