Files
llvm-project/llvm/lib/Transforms/Utils/MetaRenamer.cpp
Matt Arsenault 9d5574dda6 llvm: Delete bugpoint (#182320)
For crash reduction, I don't think it does anything that llvm-reduce
can't. Pass pipeline reduction also has a separate reduction script.
The main thing there isn't a replacement tool is the miscompilation
reducer, but I'm not sure that's actually functioned for years.

There are still some references to bugpoint in various comments
and pieces of documentation that don't all necessarily make sense
to replace or remove. In particular there are a few passes documented
as "only for bugpoint", but I've left those alone in case they are
useful for manual reductions.
2026-02-25 08:47:28 +01:00

237 lines
7.2 KiB
C++

//===- MetaRenamer.cpp - Rename everything with metasyntatic names --------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This pass renames everything with metasyntatic names. The intent is to use
// this pass after llvm-reduce reduction to conceal the nature of the original
// program.
//
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/MetaRenamer.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/TargetLibraryInfo.h"
#include "llvm/IR/Argument.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/DerivedTypes.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalAlias.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/InstIterator.h"
#include "llvm/IR/Module.h"
#include "llvm/IR/PassManager.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/TypeFinder.h"
#include "llvm/Support/CommandLine.h"
using namespace llvm;
static cl::opt<std::string> RenameExcludeFunctionPrefixes(
"rename-exclude-function-prefixes",
cl::desc("Prefixes for functions that don't need to be renamed, separated "
"by a comma"),
cl::Hidden);
static cl::opt<std::string> RenameExcludeAliasPrefixes(
"rename-exclude-alias-prefixes",
cl::desc("Prefixes for aliases that don't need to be renamed, separated "
"by a comma"),
cl::Hidden);
static cl::opt<std::string> RenameExcludeGlobalPrefixes(
"rename-exclude-global-prefixes",
cl::desc(
"Prefixes for global values that don't need to be renamed, separated "
"by a comma"),
cl::Hidden);
static cl::opt<std::string> RenameExcludeStructPrefixes(
"rename-exclude-struct-prefixes",
cl::desc("Prefixes for structs that don't need to be renamed, separated "
"by a comma"),
cl::Hidden);
static cl::opt<bool>
RenameOnlyInst("rename-only-inst", cl::init(false),
cl::desc("only rename the instructions in the function"),
cl::Hidden);
static const char *const metaNames[] = {
// See http://en.wikipedia.org/wiki/Metasyntactic_variable
"foo", "bar", "baz", "quux", "barney", "snork", "zot", "blam", "hoge",
"wibble", "wobble", "widget", "wombat", "ham", "eggs", "pluto", "spam"
};
namespace {
// This PRNG is from the ISO C spec. It is intentionally simple and
// unsuitable for cryptographic use. We're just looking for enough
// variety to surprise and delight users.
struct PRNG {
unsigned long next;
void srand(unsigned int seed) { next = seed; }
int rand() {
next = next * 1103515245 + 12345;
return (unsigned int)(next / 65536) % 32768;
}
};
struct Renamer {
Renamer(unsigned int seed) { prng.srand(seed); }
const char *newName() {
return metaNames[prng.rand() % std::size(metaNames)];
}
PRNG prng;
};
static void
parseExcludedPrefixes(StringRef PrefixesStr,
SmallVectorImpl<StringRef> &ExcludedPrefixes) {
for (;;) {
auto PrefixesSplit = PrefixesStr.split(',');
if (PrefixesSplit.first.empty())
break;
ExcludedPrefixes.push_back(PrefixesSplit.first);
PrefixesStr = PrefixesSplit.second;
}
}
void MetaRenameOnlyInstructions(Function &F) {
for (auto &I : instructions(F))
if (!I.getType()->isVoidTy() && I.getName().empty())
I.setName(I.getOpcodeName());
}
void MetaRename(Function &F) {
for (Argument &Arg : F.args())
if (!Arg.getType()->isVoidTy())
Arg.setName("arg");
for (auto &BB : F) {
BB.setName("bb");
for (auto &I : BB)
if (!I.getType()->isVoidTy())
I.setName(I.getOpcodeName());
}
}
void MetaRename(Module &M,
function_ref<TargetLibraryInfo &(Function &)> GetTLI) {
// Seed our PRNG with simple additive sum of ModuleID. We're looking to
// simply avoid always having the same function names, and we need to
// remain deterministic.
unsigned int randSeed = 0;
for (auto C : M.getModuleIdentifier())
randSeed += C;
Renamer renamer(randSeed);
SmallVector<StringRef, 8> ExcludedAliasesPrefixes;
SmallVector<StringRef, 8> ExcludedGlobalsPrefixes;
SmallVector<StringRef, 8> ExcludedStructsPrefixes;
SmallVector<StringRef, 8> ExcludedFuncPrefixes;
parseExcludedPrefixes(RenameExcludeAliasPrefixes, ExcludedAliasesPrefixes);
parseExcludedPrefixes(RenameExcludeGlobalPrefixes, ExcludedGlobalsPrefixes);
parseExcludedPrefixes(RenameExcludeStructPrefixes, ExcludedStructsPrefixes);
parseExcludedPrefixes(RenameExcludeFunctionPrefixes, ExcludedFuncPrefixes);
auto IsNameExcluded = [](StringRef &Name,
SmallVectorImpl<StringRef> &ExcludedPrefixes) {
return any_of(ExcludedPrefixes,
[&Name](auto &Prefix) { return Name.starts_with(Prefix); });
};
// Leave library functions alone because their presence or absence could
// affect the behavior of other passes.
auto ExcludeLibFuncs = [&](Function &F) {
LibFunc Tmp;
StringRef Name = F.getName();
return F.isIntrinsic() || (!Name.empty() && Name[0] == 1) ||
GetTLI(F).getLibFunc(F, Tmp) ||
IsNameExcluded(Name, ExcludedFuncPrefixes);
};
if (RenameOnlyInst) {
// Rename all functions
for (auto &F : M) {
if (ExcludeLibFuncs(F))
continue;
MetaRenameOnlyInstructions(F);
}
return;
}
// Rename all aliases
for (GlobalAlias &GA : M.aliases()) {
StringRef Name = GA.getName();
if (Name.starts_with("llvm.") || (!Name.empty() && Name[0] == 1) ||
IsNameExcluded(Name, ExcludedAliasesPrefixes))
continue;
GA.setName("alias");
}
// Rename all global variables
for (GlobalVariable &GV : M.globals()) {
StringRef Name = GV.getName();
if (Name.starts_with("llvm.") || (!Name.empty() && Name[0] == 1) ||
IsNameExcluded(Name, ExcludedGlobalsPrefixes))
continue;
GV.setName("global");
}
// Rename all struct types
TypeFinder StructTypes;
StructTypes.run(M, true);
for (StructType *STy : StructTypes) {
StringRef Name = STy->getName();
if (STy->isLiteral() || Name.empty() ||
IsNameExcluded(Name, ExcludedStructsPrefixes))
continue;
SmallString<128> NameStorage;
STy->setName(
(Twine("struct.") + renamer.newName()).toStringRef(NameStorage));
}
// Rename all functions
for (auto &F : M) {
if (ExcludeLibFuncs(F))
continue;
// Leave @main alone. The output of -metarenamer might be passed to
// lli for execution and the latter needs a main entry point.
if (F.getName() != "main")
F.setName(renamer.newName());
MetaRename(F);
}
}
} // end anonymous namespace
PreservedAnalyses MetaRenamerPass::run(Module &M, ModuleAnalysisManager &AM) {
FunctionAnalysisManager &FAM =
AM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
auto GetTLI = [&FAM](Function &F) -> TargetLibraryInfo & {
return FAM.getResult<TargetLibraryAnalysis>(F);
};
MetaRename(M, GetTLI);
return PreservedAnalyses::all();
}