Skip to content

Commit

Permalink
Improve handling of blockaddresses in bugpoint when splitting a modul…
Browse files Browse the repository at this point in the history
…e. Patch by Daniel Reynaud.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@151115 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information
eefriedman committed Feb 22, 2012
1 parent f3b06a9 commit 967570f
Showing 1 changed file with 54 additions and 6 deletions.
60 changes: 54 additions & 6 deletions tools/bugpoint/ExtractFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,39 @@ namespace {
cl::opt<bool, true>
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<Constant*> Todo;
std::set<Constant*> Done;
Todo.push_back(I);

while (!Todo.empty()) {
Constant* V = Todo.back();
Todo.pop_back();
Done.insert(V);

if (BlockAddress *BA = dyn_cast<BlockAddress>(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<Constant>(*i);
if (C && !isa<GlobalValue>(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
Expand Down Expand Up @@ -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<Function *> TestFunctions;
for (unsigned i = 0, e = F.size(); i != e; ++i) {
Expand All @@ -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<GlobalVariable>(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);
Expand Down

0 comments on commit 967570f

Please sign in to comment.