diff options
Diffstat (limited to 'tools/llvm-extract/llvm-extract.cpp')
-rw-r--r-- | tools/llvm-extract/llvm-extract.cpp | 83 |
1 files changed, 52 insertions, 31 deletions
diff --git a/tools/llvm-extract/llvm-extract.cpp b/tools/llvm-extract/llvm-extract.cpp index 5df4cb2..fd86541 100644 --- a/tools/llvm-extract/llvm-extract.cpp +++ b/tools/llvm-extract/llvm-extract.cpp @@ -30,14 +30,16 @@ struct FunctionExtractorPass : public Pass { bool run(Module &M) { // Mark all global variables to be internal for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I) - if (!I->isExternal()) - I->setInternalLinkage(true); + if (!I->isExternal()) { + I->setInitializer(0); // Make all variables external + I->setInternalLinkage(false); // Make sure it's not internal + } Function *Named = 0; // Loop over all of the functions in the module, dropping all references in // functions that are not the named function. - for (Module::iterator I = M.begin(), E = M.end(); I != E;) + for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) // Check to see if this is the named function! if (I->getName() == ExtractFunc && !I->isExternal()) { if (Named) { // Two functions, same name? @@ -51,41 +53,59 @@ struct FunctionExtractorPass : public Pass { // Make sure it's globally accessable... Named->setInternalLinkage(false); - - // Remove the named function from the module. - M.getFunctionList().remove(I); - } else { - // Nope it's not the named function, delete the body of the function - I->dropAllReferences(); - ++I; } - - // All of the functions that still have uses now must be used by global - // variables or the named function. Loop through them and create a new, - // external function for the used ones... making all uses point to the new - // functions. + + if (Named == 0) { + std::cerr << "Warning: Function '" << ExtractFunc << "' not found!\n"; + return false; + } + + // All of the functions may be used by global variables or the named + // function. Loop through them and create a new, external functions that + // can be "used", instead of ones with bodies. + // std::vector<Function*> NewFunctions; - for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) - if (!I->use_empty()) { + Function *Last = &M.back(); // Figure out where the last real fn is... + + for (Module::iterator I = M.begin(); ; ++I) { + if (I->getName() != ExtractFunc) { Function *New = new Function(I->getFunctionType(), false, I->getName()); - I->replaceAllUsesWith(New); + I->setName(""); // Remove Old name + + // If it's not the named function, delete the body of the function + I->dropAllReferences(); + + M.getFunctionList().push_back(New); NewFunctions.push_back(New); } + + if (&*I == Last) break; // Stop after processing the last function + } + + // Now that we have replacements all set up, loop through the module, + // deleting the old functions, replacing them with the newly created + // functions. + if (!NewFunctions.empty()) { + unsigned FuncNum = 0; + Module::iterator I = M.begin(); + do { + if (I->getName() != ExtractFunc) { + // Make everything that uses the old function use the new dummy fn + I->replaceAllUsesWith(NewFunctions[FuncNum++]); + + Function *Old = I; + ++I; // Move the iterator to the new function + + // Delete the old function! + M.getFunctionList().erase(Old); + + } else { + ++I; // Skip the function we are extracting + } + } while (&*I != NewFunctions[0]); + } - // Now the module only has unused functions with their references dropped. - // Delete them all now! - M.getFunctionList().clear(); - - // Re-insert the named function... - if (Named) - M.getFunctionList().push_back(Named); - else - std::cerr << "Warning: Function '" << ExtractFunc << "' not found!\n"; - - // Insert all of the function stubs... - M.getFunctionList().insert(M.end(), NewFunctions.begin(), - NewFunctions.end()); return true; } }; @@ -109,6 +129,7 @@ int main(int argc, char **argv) { PassManager Passes; Passes.add(new FunctionExtractorPass()); Passes.add(createGlobalDCEPass()); // Delete unreachable globals + Passes.add(createFunctionResolvingPass()); // Delete prototypes Passes.add(createConstantMergePass()); // Merge dup global constants Passes.add(createDeadTypeEliminationPass()); // Remove dead types... Passes.add(new WriteBytecodePass(&std::cout)); // Write bytecode to file... |