#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/TypeFinder.h"
#include "llvm/InitializePasses.h"
#include "llvm/Pass.h"
+#include "llvm/Support/CommandLine.h"
#include "llvm/Transforms/Utils.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 const char *const metaNames[] = {
// See http://en.wikipedia.org/wiki/Metasyntactic_variable
"foo", "bar", "baz", "quux", "barney", "snork", "zot", "blam", "hoge",
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 MetaRename(Function &F) {
for (Argument &Arg : F.args())
if (!Arg.getType()->isVoidTy())
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.startswith(Prefix); });
+ };
+
// Rename all aliases
for (GlobalAlias &GA : M.aliases()) {
StringRef Name = GA.getName();
- if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1))
+ if (Name.startswith("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.startswith("llvm.") || (!Name.empty() && Name[0] == 1))
+ if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
+ IsNameExcluded(Name, ExcludedGlobalsPrefixes))
continue;
GV.setName("global");
TypeFinder StructTypes;
StructTypes.run(M, true);
for (StructType *STy : StructTypes) {
- if (STy->isLiteral() || STy->getName().empty())
+ StringRef Name = STy->getName();
+ if (STy->isLiteral() || Name.empty() ||
+ IsNameExcluded(Name, ExcludedStructsPrefixes))
continue;
SmallString<128> NameStorage;
// Leave library functions alone because their presence or absence could
// affect the behavior of other passes.
if (Name.startswith("llvm.") || (!Name.empty() && Name[0] == 1) ||
- GetTLI(F).getLibFunc(F, Tmp))
+ GetTLI(F).getLibFunc(F, Tmp) ||
+ IsNameExcluded(Name, ExcludedFuncPrefixes))
continue;
// Leave @main alone. The output of -metarenamer might be passed to
--- /dev/null
+; RUN: opt -passes=metarenamer -rename-exclude-function-prefixes=my_func -rename-exclude-global-prefixes=my_global -rename-exclude-struct-prefixes=my_struct -rename-exclude-alias-prefixes=my_alias -S %s | FileCheck %s
+
+; Check that excluded names don't get renamed while all the other ones do
+
+; CHECK: %my_struct1 = type { i8*, i32 }
+; CHECK: %my_struct2 = type { i8*, i32 }
+; CHECK-NOT: %other_struct = type { i8*, i32 }
+; CHECK: @my_global1 = global i32 42
+; CHECK: @my_global2 = global i32 24
+; CHECK-NOT: @other_global = global i32 24
+; CHECK: @my_alias1 = alias i32, i32* @my_global1
+; CHECK: @my_alias2 = alias i32, i32* @my_global2
+; CHECK-NOT: @other_alias = alias i32, i32* @other_global
+; CHECK: declare void @my_func1
+; CHECK: declare void @my_func2
+; CHECK-NOT: declare void @other_func
+
+; CHECK: call void @my_func1
+; CHECK: call void @my_func2
+; CHECK-NOT: call void @other_func
+; CHECK: load i32, i32* @my_global1
+; CHECK: load i32, i32* @my_global2
+; CHECK-NOT: load i32, i32* @other_global
+; CHECK: load i32, i32* @my_alias1
+; CHECK: load i32, i32* @my_alias2
+; CHECK-NOT: load i32, i32* @other_alias
+; CHECK: alloca %my_struct1
+; CHECK: alloca %my_struct2
+; CHECK-NOT: alloca %other_struct
+
+%my_struct1 = type { i8*, i32 }
+%my_struct2 = type { i8*, i32 }
+%other_struct = type { i8*, i32 }
+@my_global1 = global i32 42
+@my_global2 = global i32 24
+@other_global = global i32 24
+@my_alias1 = alias i32, i32* @my_global1
+@my_alias2 = alias i32, i32* @my_global2
+@other_alias = alias i32, i32* @other_global
+declare void @my_func1()
+declare void @my_func2()
+declare void @other_func()
+
+define void @some_func() {
+ call void @my_func1()
+ call void @my_func2()
+ call void @other_func()
+ %a = load i32, i32* @my_global1
+ %b = load i32, i32* @my_global2
+ %c = load i32, i32* @other_global
+ %d = load i32, i32* @my_alias1
+ %e = load i32, i32* @my_alias2
+ %f = load i32, i32* @other_alias
+ %g = alloca %my_struct1
+ %h = alloca %my_struct2
+ %i = alloca %other_struct
+ ret void
+}