From 967570f2ecdbedeae80bcc19744cf111c3e112e1 Mon Sep 17 00:00:00 2001 From: Eli Friedman Date: Wed, 22 Feb 2012 01:43:47 +0000 Subject: Improve handling of blockaddresses in bugpoint when splitting a module. Patch by Daniel Reynaud. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151115 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/bugpoint/ExtractFunction.cpp | 60 ++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 6 deletions(-) diff --git a/tools/bugpoint/ExtractFunction.cpp b/tools/bugpoint/ExtractFunction.cpp index f2e61f8b5d..ac8e159711 100644 --- a/tools/bugpoint/ExtractFunction.cpp +++ b/tools/bugpoint/ExtractFunction.cpp @@ -47,7 +47,39 @@ namespace { cl::opt NoSCFG("disable-simplifycfg", cl::location(DisableSimplifyCFG), cl::desc("Do not use the -simplifycfg pass to reduce testcases")); -} + + Function* globalInitUsesExternalBA(GlobalVariable* GV) { + if (!GV->hasInitializer()) + return 0; + + Constant *I = GV->getInitializer(); + + // walk the values used by the initializer + // (and recurse into things like ConstantExpr) + std::vector Todo; + std::set Done; + Todo.push_back(I); + + while (!Todo.empty()) { + Constant* V = Todo.back(); + Todo.pop_back(); + Done.insert(V); + + if (BlockAddress *BA = dyn_cast(V)) { + Function *F = BA->getFunction(); + if (F->isDeclaration()) + return F; + } + + for (User::op_iterator i = V->op_begin(), e = V->op_end(); i != e; ++i) { + Constant *C = dyn_cast(*i); + if (C && !isa(C) && !Done.count(C)) + Todo.push_back(C); + } + } + return 0; + } +} // end anonymous namespace /// deleteInstructionFromProgram - This method clones the current Program and /// deletes the specified instruction from the cloned module. It then runs a @@ -272,11 +304,6 @@ llvm::SplitFunctionsOutOfModule(Module *M, ValueToValueMapTy NewVMap; Module *New = CloneModule(M, NewVMap); - // Make sure global initializers exist only in the safe module (CBE->.so) - for (Module::global_iterator I = New->global_begin(), E = New->global_end(); - I != E; ++I) - I->setInitializer(0); // Delete the initializer to make it external - // Remove the Test functions from the Safe module std::set TestFunctions; for (unsigned i = 0, e = F.size(); i != e; ++i) { @@ -295,6 +322,27 @@ llvm::SplitFunctionsOutOfModule(Module *M, DeleteFunctionBody(I); + // Try to split the global initializers evenly + for (Module::global_iterator I = M->global_begin(), E = M->global_end(); + I != E; ++I) { + GlobalVariable *GV = cast(NewVMap[I]); + if (Function *TestFn = globalInitUsesExternalBA(I)) { + if (Function *SafeFn = globalInitUsesExternalBA(GV)) { + errs() << "*** Error: when reducing functions, encountered " + "the global '"; + WriteAsOperand(errs(), GV, false); + errs() << "' with an initializer that references blockaddresses " + "from safe function '" << SafeFn->getName() + << "' and from test function '" << TestFn->getName() << "'.\n"; + exit(1); + } + I->setInitializer(0); // 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(0); + } + } + // Make sure that there is a global ctor/dtor array in both halves of the // module if they both have static ctor/dtor functions. SplitStaticCtorDtor("llvm.global_ctors", M, New, NewVMap); -- cgit v1.2.3