//
// 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 is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
//
//===----------------------------------------------------------------------===//
+#include "llvm/Instructions.h"
#include "llvm/Module.h"
#include "llvm/Pass.h"
#include "llvm/Transforms/IPO.h"
+#include "llvm/Support/Compiler.h"
using namespace llvm;
namespace {
- class FunctionExtractorPass : public ModulePass {
+ /// @brief A pass to extract specific functions and their dependencies.
+ class VISIBILITY_HIDDEN FunctionExtractorPass : public ModulePass {
Function *Named;
bool deleteFunc;
+ bool reLink;
public:
+ static char ID; // Pass identification, replacement for typeid
+
/// FunctionExtractorPass - If deleteFn is true, this pass deletes as the
/// specified function. Otherwise, it deletes as much of the module as
/// possible, except for the function specified.
///
- FunctionExtractorPass(Function *F = 0, bool deleteFn = true)
- : Named(F), deleteFunc(deleteFn) {}
+ explicit FunctionExtractorPass(Function *F = 0, bool deleteFn = true,
+ bool relinkCallees = false)
+ : ModulePass((intptr_t)&ID), Named(F), deleteFunc(deleteFn),
+ reLink(relinkCallees) {}
bool runOnModule(Module &M) {
if (Named == 0) {
- Named = M.getMainFunction();
+ Named = M.getFunction("main");
if (Named == 0) return false; // No function to extract
}
}
bool deleteFunction() {
+ // If we're in relinking mode, set linkage of all internal callees to
+ // external. This will allow us extract function, and then - link
+ // everything together
+ if (reLink) {
+ for (Function::iterator B = Named->begin(), BE = Named->end();
+ B != BE; ++B) {
+ for (BasicBlock::iterator I = B->begin(), E = B->end();
+ I != E; ++I) {
+ if (CallInst* callInst = dyn_cast<CallInst>(&*I)) {
+ Function* Callee = callInst->getCalledFunction();
+ if (Callee && Callee->hasInternalLinkage())
+ Callee->setLinkage(GlobalValue::ExternalLinkage);
+ }
+ }
+ }
+ }
+
Named->setLinkage(GlobalValue::ExternalLinkage);
Named->deleteBody();
- assert(Named->isExternal() && "This didn't make the function external!");
+ assert(Named->isDeclaration() && "This didn't make the function external!");
return true;
}
// Mark all global variables internal
for (Module::global_iterator I = M.global_begin(), E = M.global_end(); I != E; ++I)
- if (!I->isExternal()) {
+ if (!I->isDeclaration()) {
I->setInitializer(0); // Make all variables external
I->setLinkage(GlobalValue::ExternalLinkage);
}
for (Module::iterator I = M.begin(); ; ++I) {
if (&*I != Named) {
Function *New = new Function(I->getFunctionType(),
- GlobalValue::ExternalLinkage,
- I->getName());
- I->setName(""); // Remove Old name
+ GlobalValue::ExternalLinkage);
+ New->setCallingConv(I->getCallingConv());
+ New->setParamAttrs(I->getParamAttrs());
+ if (I->hasCollector())
+ New->setCollector(I->getCollector());
// If it's not the named function, delete the body of the function
I->dropAllReferences();
M.getFunctionList().push_back(New);
NewFunctions.push_back(New);
+ New->takeName(I);
}
if (&*I == Last) break; // Stop after processing the last function
}
};
+ char FunctionExtractorPass::ID = 0;
RegisterPass<FunctionExtractorPass> X("extract", "Function Extractor");
}
-ModulePass *llvm::createFunctionExtractionPass(Function *F, bool deleteFn) {
- return new FunctionExtractorPass(F, deleteFn);
+ModulePass *llvm::createFunctionExtractionPass(Function *F, bool deleteFn,
+ bool relinkCallees) {
+ return new FunctionExtractorPass(F, deleteFn, relinkCallees);
}