From c818be073d3d48389d1cd05792acc9715335df8e Mon Sep 17 00:00:00 2001 From: Hal Finkel Date: Thu, 26 Nov 2015 19:23:49 +0000 Subject: [PATCH] [bugpoint] Fix "Alias must point to a definition" problems GlobalAliases may reference function definitions, but not function declarations. bugpoint would sometimes create invalid IR by deleting a function's body (thus mutating a function definition into a declaration) without first 'fixing' any GlobalAliases that reference that function definition. This change iteratively prevents that issue. Before deleting a function's body, it scans the module for GlobalAliases which reference that function. When found, it eliminates them using replaceAllUsesWith. Fixes PR20788. Patch by Nick Johnson! git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@254171 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/bugpoint/BugDriver.h | 5 +++++ tools/bugpoint/CrashDebugger.cpp | 4 ++-- tools/bugpoint/ExtractFunction.cpp | 36 ++++++++++++++++++++++++++++-- 3 files changed, 41 insertions(+), 4 deletions(-) diff --git a/tools/bugpoint/BugDriver.h b/tools/bugpoint/BugDriver.h index 1bd2e80a630..45fcf74aa6b 100644 --- a/tools/bugpoint/BugDriver.h +++ b/tools/bugpoint/BugDriver.h @@ -321,6 +321,11 @@ void PrintFunctionList(const std::vector &Funcs); /// void PrintGlobalVariableList(const std::vector &GVs); +// DeleteGlobalInitializer - "Remove" the global variable by deleting its +// initializer, making it external. +// +void DeleteGlobalInitializer(GlobalVariable *GV); + // DeleteFunctionBody - "Remove" the function by deleting all of it's basic // blocks, making it external. // diff --git a/tools/bugpoint/CrashDebugger.cpp b/tools/bugpoint/CrashDebugger.cpp index 1bfcc87e06e..631a58455c5 100644 --- a/tools/bugpoint/CrashDebugger.cpp +++ b/tools/bugpoint/CrashDebugger.cpp @@ -162,7 +162,7 @@ ReduceCrashingGlobalVariables::TestGlobalVariables( // playing with... for (GlobalVariable &I : M->globals()) if (I.hasInitializer() && !GVSet.count(&I)) { - I.setInitializer(nullptr); + DeleteGlobalInitializer(&I); I.setLinkage(GlobalValue::ExternalLinkage); } @@ -664,7 +664,7 @@ static bool DebugACrash(BugDriver &BD, for (Module::global_iterator I = M->global_begin(), E = M->global_end(); I != E; ++I) if (I->hasInitializer()) { - I->setInitializer(nullptr); + DeleteGlobalInitializer(&*I); I->setLinkage(GlobalValue::ExternalLinkage); DeletedInit = true; } diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp index 21d3d984599..7b98cb8fb55 100644 --- a/tools/bugpoint/ExtractFunction.cpp +++ b/tools/bugpoint/ExtractFunction.cpp @@ -179,11 +179,43 @@ std::unique_ptr BugDriver::extractLoop(Module *M) { return NewM; } +static void eliminateAliases(GlobalValue *GV) { + // First, check whether a GlobalAlias references this definition. + // GlobalAlias MAY NOT reference declarations. + for (;;) { + // 1. Find aliases + SmallVector aliases; + Module *M = GV->getParent(); + for (Module::alias_iterator I=M->alias_begin(), E=M->alias_end(); I!=E; ++I) + if (I->getAliasee()->stripPointerCasts() == GV) + aliases.push_back(&*I); + if (aliases.empty()) + break; + // 2. Resolve aliases + for (unsigned i=0, e=aliases.size(); ireplaceAllUsesWith(aliases[i]->getAliasee()); + aliases[i]->eraseFromParent(); + } + // 3. Repeat until no more aliases found; there might + // be an alias to an alias... + } +} + +// +// DeleteGlobalInitializer - "Remove" the global variable by deleting its initializer, +// making it external. +// +void llvm::DeleteGlobalInitializer(GlobalVariable *GV) { + eliminateAliases(GV); + GV->setInitializer(nullptr); +} // DeleteFunctionBody - "Remove" the function by deleting all of its basic // blocks, making it external. // void llvm::DeleteFunctionBody(Function *F) { + eliminateAliases(F); + // delete the body of the function... F->deleteBody(); assert(F->isDeclaration() && "This didn't make the function external!"); @@ -323,10 +355,10 @@ llvm::SplitFunctionsOutOfModule(Module *M, << "' and from test function '" << TestFn->getName() << "'.\n"; exit(1); } - I.setInitializer(nullptr); // Delete the initializer to make it external + DeleteGlobalInitializer(&I); // Delete the initializer to make it external } else { // If we keep it in the safe module, then delete it in the test module - GV->setInitializer(nullptr); + DeleteGlobalInitializer(GV); } } -- 2.34.1