//===- ExtractFunction.cpp - Extract a function from Program --------------===//
-//
+//
// The LLVM Compiler Infrastructure
//
// This file was developed by the LLVM research group and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
-//
+//
//===----------------------------------------------------------------------===//
//
// This file implements several methods that are used to extract functions,
//===----------------------------------------------------------------------===//
#include "BugDriver.h"
-#include "llvm/Constant.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
#include "llvm/Module.h"
#include "llvm/PassManager.h"
#include "llvm/Pass.h"
-#include "llvm/Type.h"
#include "llvm/Analysis/Verifier.h"
#include "llvm/Transforms/IPO.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Utils/Cloning.h"
#include "llvm/Transforms/Utils/FunctionUtils.h"
#include "llvm/Target/TargetData.h"
-#include "Support/CommandLine.h"
-#include "Support/Debug.h"
-#include "Support/FileUtilities.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/FileUtilities.h"
#include <set>
+#include <iostream>
using namespace llvm;
namespace llvm {
// Remove the instruction from the program.
TheInst->getParent()->getInstList().erase(TheInst);
+
+ //writeProgramToFile("current.bc", Result);
+
// Spiff up the output a little bit.
PassManager Passes;
// Make sure that the appropriate target data is always used...
- Passes.add(new TargetData("bugpoint", Result));
+ Passes.add(new TargetData(Result));
/// FIXME: If this used runPasses() like the methods below, we could get rid
/// of the -disable-* options!
/// performFinalCleanups - This method clones the current Program and performs
/// a series of cleanups intended to get rid of extra cruft on the module
-/// before handing it to the user...
+/// before handing it to the user.
///
Module *BugDriver::performFinalCleanups(Module *M, bool MayModifySemantics) {
// Make all functions external, so GlobalDCE doesn't delete them...
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
I->setLinkage(GlobalValue::ExternalLinkage);
-
+
std::vector<const PassInfo*> CleanupPasses;
- CleanupPasses.push_back(getPI(createFunctionResolvingPass()));
CleanupPasses.push_back(getPI(createGlobalDCEPass()));
CleanupPasses.push_back(getPI(createDeadTypeEliminationPass()));
Module *New = runPassesOn(M, CleanupPasses);
if (New == 0) {
std::cerr << "Final cleanups failed. Sorry. :( Please report a bug!\n";
+ return M;
}
delete M;
return New;
}
// Check to see if we created any new functions. If not, no loops were
- // extracted and we should return null.
- if (M->size() == NewM->size()) {
+ // extracted and we should return null. Limit the number of loops we extract
+ // to avoid taking forever.
+ static unsigned NumExtracted = 32;
+ if (M->size() == NewM->size() || --NumExtracted == 0) {
delete NewM;
return 0;
+ } else {
+ assert(M->size() < NewM->size() && "Loop extract removed functions?");
+ Module::iterator MI = NewM->begin();
+ for (unsigned i = 0, e = M->size(); i != e; ++i)
+ ++MI;
}
-
+
return NewM;
}
void llvm::DeleteFunctionBody(Function *F) {
// delete the body of the function...
F->deleteBody();
- assert(F->isExternal() && "This didn't make the function external!");
+ assert(F->isDeclaration() && "This didn't make the function external!");
+}
+
+/// GetTorInit - Given a list of entries for static ctors/dtors, return them
+/// as a constant array.
+static Constant *GetTorInit(std::vector<std::pair<Function*, int> > &TorList) {
+ assert(!TorList.empty() && "Don't create empty tor list!");
+ std::vector<Constant*> ArrayElts;
+ for (unsigned i = 0, e = TorList.size(); i != e; ++i) {
+ std::vector<Constant*> Elts;
+ Elts.push_back(ConstantInt::get(Type::Int32Ty, TorList[i].second));
+ Elts.push_back(TorList[i].first);
+ ArrayElts.push_back(ConstantStruct::get(Elts));
+ }
+ return ConstantArray::get(ArrayType::get(ArrayElts[0]->getType(),
+ ArrayElts.size()),
+ ArrayElts);
+}
+
+/// SplitStaticCtorDtor - A module was recently split into two parts, M1/M2, and
+/// M1 has all of the global variables. If M2 contains any functions that are
+/// static ctors/dtors, we need to add an llvm.global_[cd]tors global to M2, and
+/// prune appropriate entries out of M1s list.
+static void SplitStaticCtorDtor(const char *GlobalName, Module *M1, Module *M2){
+ GlobalVariable *GV = M1->getNamedGlobal(GlobalName);
+ if (!GV || GV->isDeclaration() || GV->hasInternalLinkage() ||
+ !GV->use_empty()) return;
+
+ std::vector<std::pair<Function*, int> > M1Tors, M2Tors;
+ ConstantArray *InitList = dyn_cast<ConstantArray>(GV->getInitializer());
+ if (!InitList) return;
+
+ for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) {
+ if (ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(i))){
+ if (CS->getNumOperands() != 2) return; // Not array of 2-element structs.
+
+ if (CS->getOperand(1)->isNullValue())
+ break; // Found a null terminator, stop here.
+
+ ConstantInt *CI = dyn_cast<ConstantInt>(CS->getOperand(0));
+ int Priority = CI ? CI->getSExtValue() : 0;
+
+ Constant *FP = CS->getOperand(1);
+ if (ConstantExpr *CE = dyn_cast<ConstantExpr>(FP))
+ if (CE->isCast())
+ FP = CE->getOperand(0);
+ if (Function *F = dyn_cast<Function>(FP)) {
+ if (!F->isDeclaration())
+ M1Tors.push_back(std::make_pair(F, Priority));
+ else {
+ // Map to M2's version of the function.
+ F = M2->getFunction(F->getName());
+ M2Tors.push_back(std::make_pair(F, Priority));
+ }
+ }
+ }
+ }
+
+ GV->eraseFromParent();
+ if (!M1Tors.empty()) {
+ Constant *M1Init = GetTorInit(M1Tors);
+ new GlobalVariable(M1Init->getType(), false, GlobalValue::AppendingLinkage,
+ M1Init, GlobalName, M1);
+ }
+
+ GV = M2->getNamedGlobal(GlobalName);
+ assert(GV && "Not a clone of M1?");
+ assert(GV->use_empty() && "llvm.ctors shouldn't have uses!");
+
+ GV->eraseFromParent();
+ if (!M2Tors.empty()) {
+ Constant *M2Init = GetTorInit(M2Tors);
+ new GlobalVariable(M2Init->getType(), false, GlobalValue::AppendingLinkage,
+ M2Init, GlobalName, M2);
+ }
}
+
/// SplitFunctionsOutOfModule - Given a module and a list of functions in the
/// module, split the functions OUT of the specified module, and place them in
/// the new module.
-///
-/// FIXME: this could be made DRAMATICALLY more efficient for large programs if
-/// we just MOVED functions from one module to the other, instead of cloning the
-/// whole module, then proceeding to delete an entire module's worth of stuff.
-///
Module *llvm::SplitFunctionsOutOfModule(Module *M,
const std::vector<Function*> &F) {
// Make sure functions & globals are all external so that linkage
// between the two modules will work.
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
I->setLinkage(GlobalValue::ExternalLinkage);
- for (Module::giterator I = M->gbegin(), E = M->gend(); I != E; ++I)
+ for (Module::global_iterator I = M->global_begin(), E = M->global_end();
+ I != E; ++I)
I->setLinkage(GlobalValue::ExternalLinkage);
Module *New = CloneModule(M);
// Make sure global initializers exist only in the safe module (CBE->.so)
- for (Module::giterator I = New->gbegin(), E = New->gend(); I != E; ++I)
+ 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<std::pair<std::string, const PointerType*> > TestFunctions;
for (unsigned i = 0, e = F.size(); i != e; ++i) {
- TestFunctions.insert(std::make_pair(F[i]->getName(), F[i]->getType()));
- Function *TNOF = M->getFunction(F[i]->getName(), F[i]->getFunctionType());
- DEBUG(std::cerr << "Removing function " << F[i]->getName() << "\n");
+ TestFunctions.insert(std::make_pair(F[i]->getName(), F[i]->getType()));
+ Function *TNOF = M->getFunction(F[i]->getName());
assert(TNOF && "Function doesn't exist in module!");
+ assert(TNOF->getFunctionType() == F[i]->getFunctionType() && "wrong type?");
+ DEBUG(std::cerr << "Removing function " << F[i]->getName() << "\n");
DeleteFunctionBody(TNOF); // Function is now external in this module!
}
+
// Remove the Safe functions from the Test module
for (Module::iterator I = New->begin(), E = New->end(); I != E; ++I)
if (!TestFunctions.count(std::make_pair(I->getName(), I->getType())))
DeleteFunctionBody(I);
+
+
+ // 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);
+ SplitStaticCtorDtor("llvm.global_dtors", M, New);
+
return New;
}
/// BlockExtractorPass - This pass is used by bugpoint to extract all blocks
/// from the module into their own functions except for those specified by the
/// BlocksToNotExtract list.
- class BlockExtractorPass : public Pass {
- bool run(Module &M);
+ class BlockExtractorPass : public ModulePass {
+ bool runOnModule(Module &M);
+ public:
+ static char ID; // Pass ID, replacement for typeid
+ BlockExtractorPass() : ModulePass((intptr_t)&ID) {}
};
- RegisterOpt<BlockExtractorPass>
+ char BlockExtractorPass::ID = 0;
+ RegisterPass<BlockExtractorPass>
XX("extract-bbs", "Extract Basic Blocks From Module (for bugpoint use)");
}
-bool BlockExtractorPass::run(Module &M) {
+bool BlockExtractorPass::runOnModule(Module &M) {
std::set<BasicBlock*> TranslatedBlocksToNotExtract;
for (unsigned i = 0, e = BlocksToNotExtract.size(); i != e; ++i) {
BasicBlock *BB = BlocksToNotExtract[i];
Function *F = BB->getParent();
// Map the corresponding function in this module.
- Function *MF = M.getFunction(F->getName(), F->getFunctionType());
+ Function *MF = M.getFunction(F->getName());
// Figure out which index the basic block is in its function.
Function::iterator BBI = MF->begin();
for (unsigned i = 0, e = BlocksToExtract.size(); i != e; ++i)
ExtractBasicBlock(BlocksToExtract[i]);
-
+
return !BlocksToExtract.empty();
}
PI.push_back(getPI(new BlockExtractorPass()));
Module *Ret = runPassesOn(M, PI);
BlocksToNotExtract.clear();
- if (Ret == 0)
+ if (Ret == 0) {
std::cout << "*** Basic Block extraction failed, please report a bug!\n";
+ M = swapProgramIn(M);
+ EmitProgressBytecode("basicblockextractfail", true);
+ swapProgramIn(M);
+ }
return Ret;
}