| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 1 | //===----------------------------------------------------------------------===// | 
|  | 2 | // LLVM extract Utility | 
|  | 3 | // | 
|  | 4 | // This utility changes the input module to only contain a single function, | 
|  | 5 | // which is primarily used for debugging transformations. | 
|  | 6 | // | 
|  | 7 | //===----------------------------------------------------------------------===// | 
|  | 8 |  | 
|  | 9 | #include "llvm/Module.h" | 
|  | 10 | #include "llvm/PassManager.h" | 
|  | 11 | #include "llvm/Bytecode/Reader.h" | 
|  | 12 | #include "llvm/Bytecode/WriteBytecodePass.h" | 
| Chris Lattner | 33974ca | 2002-07-23 22:04:40 +0000 | [diff] [blame] | 13 | #include "llvm/Transforms/IPO.h" | 
| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 14 | #include "Support/CommandLine.h" | 
|  | 15 | #include <memory> | 
|  | 16 |  | 
| Chris Lattner | 5ff62e9 | 2002-07-22 02:10:13 +0000 | [diff] [blame] | 17 | // InputFilename - The filename to read from. | 
| Chris Lattner | c7a0985 | 2002-07-25 16:31:09 +0000 | [diff] [blame] | 18 | static cl::opt<std::string> | 
| Chris Lattner | 5ff62e9 | 2002-07-22 02:10:13 +0000 | [diff] [blame] | 19 | InputFilename(cl::Positional, cl::desc("<input bytecode file>"), | 
|  | 20 | cl::init("-"), cl::value_desc("filename")); | 
|  | 21 |  | 
|  | 22 |  | 
|  | 23 | // ExtractFunc - The function to extract from the module... defaults to main. | 
| Chris Lattner | c7a0985 | 2002-07-25 16:31:09 +0000 | [diff] [blame] | 24 | static cl::opt<std::string> | 
| Chris Lattner | 5ff62e9 | 2002-07-22 02:10:13 +0000 | [diff] [blame] | 25 | ExtractFunc("func", cl::desc("Specify function to extract"), cl::init("main"), | 
|  | 26 | cl::value_desc("function")); | 
|  | 27 |  | 
| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 28 |  | 
|  | 29 | struct FunctionExtractorPass : public Pass { | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 30 | bool run(Module &M) { | 
| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 31 | // Mark all global variables to be internal | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 32 | for (Module::giterator I = M.gbegin(), E = M.gend(); I != E; ++I) | 
|  | 33 | I->setInternalLinkage(true); | 
| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 34 |  | 
|  | 35 | Function *Named = 0; | 
|  | 36 |  | 
|  | 37 | // Loop over all of the functions in the module, dropping all references in | 
|  | 38 | // functions that are not the named function. | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 39 | for (Module::iterator I = M.begin(), E = M.end(); I != E;) | 
| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 40 | // Check to see if this is the named function! | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 41 | if (!Named && I->getName() == ExtractFunc) { | 
| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 42 | // Yes, it is.  Keep track of it... | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 43 | Named = I; | 
| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 44 |  | 
| Chris Lattner | 6a13592 | 2002-05-23 18:36:25 +0000 | [diff] [blame] | 45 | // Make sure it's globally accessable... | 
|  | 46 | Named->setInternalLinkage(false); | 
|  | 47 |  | 
| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 48 | // Remove the named function from the module. | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 49 | M.getFunctionList().remove(I); | 
| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 50 | } else { | 
|  | 51 | // Nope it's not the named function, delete the body of the function | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 52 | I->dropAllReferences(); | 
| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 53 | ++I; | 
|  | 54 | } | 
|  | 55 |  | 
|  | 56 | // All of the functions that still have uses now must be used by global | 
|  | 57 | // variables or the named function.  Loop through them and create a new, | 
|  | 58 | // external function for the used ones... making all uses point to the new | 
|  | 59 | // functions. | 
|  | 60 | std::vector<Function*> NewFunctions; | 
|  | 61 |  | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 62 | for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) | 
|  | 63 | if (!I->use_empty()) { | 
|  | 64 | Function *New = new Function(I->getFunctionType(), false, I->getName()); | 
|  | 65 | I->replaceAllUsesWith(New); | 
| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 66 | NewFunctions.push_back(New); | 
|  | 67 | } | 
|  | 68 |  | 
|  | 69 | // Now the module only has unused functions with their references dropped. | 
|  | 70 | // Delete them all now! | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 71 | M.getFunctionList().clear(); | 
| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 72 |  | 
|  | 73 | // Re-insert the named function... | 
|  | 74 | if (Named) | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 75 | M.getFunctionList().push_back(Named); | 
| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 76 | else | 
|  | 77 | std::cerr << "Warning: Function '" << ExtractFunc << "' not found!\n"; | 
|  | 78 |  | 
|  | 79 | // Insert all of the function stubs... | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 80 | M.getFunctionList().insert(M.end(), NewFunctions.begin(), | 
|  | 81 | NewFunctions.end()); | 
| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 82 | return true; | 
|  | 83 | } | 
|  | 84 | }; | 
|  | 85 |  | 
|  | 86 |  | 
| Chris Lattner | 33974ca | 2002-07-23 22:04:40 +0000 | [diff] [blame] | 87 | static RegisterPass<FunctionExtractorPass> X("extract", "Function Extractor"); | 
|  | 88 |  | 
|  | 89 |  | 
| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 90 | int main(int argc, char **argv) { | 
|  | 91 | cl::ParseCommandLineOptions(argc, argv, " llvm extractor\n"); | 
|  | 92 |  | 
|  | 93 | std::auto_ptr<Module> M(ParseBytecodeFile(InputFilename)); | 
|  | 94 | if (M.get() == 0) { | 
|  | 95 | std::cerr << "bytecode didn't read correctly.\n"; | 
|  | 96 | return 1; | 
|  | 97 | } | 
|  | 98 |  | 
|  | 99 | // In addition to just parsing the input from GCC, we also want to spiff it up | 
|  | 100 | // a little bit.  Do this now. | 
|  | 101 | // | 
|  | 102 | PassManager Passes; | 
|  | 103 | Passes.add(new FunctionExtractorPass()); | 
|  | 104 | Passes.add(createGlobalDCEPass());              // Delete unreachable globals | 
|  | 105 | Passes.add(createConstantMergePass());          // Merge dup global constants | 
| Chris Lattner | 33974ca | 2002-07-23 22:04:40 +0000 | [diff] [blame] | 106 | Passes.add(createDeadTypeEliminationPass());    // Remove dead types... | 
| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 107 | Passes.add(new WriteBytecodePass(&std::cout));  // Write bytecode to file... | 
|  | 108 |  | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 109 | Passes.run(*M.get()); | 
| Chris Lattner | 579d914 | 2002-05-22 20:27:00 +0000 | [diff] [blame] | 110 | return 0; | 
|  | 111 | } |