//===----------------------------------------------------------------------===// // LLVM 'OPT' UTILITY // // Optimizations may be specified an arbitrary number of times on the command // line, they are run in the order specified. // //===----------------------------------------------------------------------===// #include "llvm/Module.h" #include "llvm/PassManager.h" #include "llvm/Bytecode/Reader.h" #include "llvm/Bytecode/WriteBytecodePass.h" #include "llvm/Assembly/PrintModulePass.h" #include "llvm/Analysis/Verifier.h" #include "llvm/Target/TargetData.h" #include "Support/CommandLine.h" #include "Support/Signals.h" #include #include #include using std::cerr; //===----------------------------------------------------------------------===// // PassNameParser class - Make use of the pass registration mechanism to // automatically add a command line argument to opt for each pass. // namespace { // anonymous namespace for local class... class PassNameParser : public PassRegistrationListener, public cl::parser { cl::Option *Opt; public: PassNameParser() : Opt(0) {} void initialize(cl::Option &O) { Opt = &O; cl::parser::initialize(O); // Add all of the passes to the map that got initialized before 'this' did. enumeratePasses(); } static inline bool ignorablePass(const PassInfo *P) { // Ignore non-selectable and non-constructible passes! return P->getPassArgument() == 0 || (P->getNormalCtor() == 0 && P->getDataCtor() == 0); } // Implement the PassRegistrationListener callbacks used to populate our map // virtual void passRegistered(const PassInfo *P) { if (ignorablePass(P) || !Opt) return; assert(findOption(P->getPassArgument()) == getNumOptions() && "Two passes with the same argument attempted to be registered!"); addLiteralOption(P->getPassArgument(), P, P->getPassName()); Opt->addArgument(P->getPassArgument()); } virtual void passEnumerate(const PassInfo *P) { passRegistered(P); } virtual void passUnregistered(const PassInfo *P) { if (ignorablePass(P) || !Opt) return; assert(findOption(P->getPassArgument()) != getNumOptions() && "Registered Pass not in the pass map!"); removeLiteralOption(P->getPassArgument()); Opt->removeArgument(P->getPassArgument()); } // ValLessThan - Provide a sorting comparator for Values elements... typedef std::pair > ValType; static bool ValLessThan(const ValType &VT1, const ValType &VT2) { return std::string(VT1.first) < std::string(VT2.first); } // printOptionInfo - Print out information about this option. Override the // default implementation to sort the table before we print... virtual void printOptionInfo(const cl::Option &O, unsigned GlobalWidth) const{ PassNameParser *PNP = const_cast(this); std::sort(PNP->Values.begin(), PNP->Values.end(), ValLessThan); cl::parser::printOptionInfo(O, GlobalWidth); } }; } // end anonymous namespace // The OptimizationList is automatically populated with registered Passes by the // PassNameParser. // static cl::list OptimizationList(cl::desc("Optimizations available:")); // Other command line options... // static cl::opt InputFilename(cl::Positional, cl::desc(""), cl::init("-")); static cl::opt OutputFilename("o", cl::desc("Override output filename"), cl::value_desc("filename")); static cl::opt Force("f", cl::desc("Overwrite output files")); static cl::opt PrintEachXForm("p", cl::desc("Print module after each transformation")); static cl::opt Quiet("q", cl::desc("Don't print modifying pass names")); static cl::alias QuietA("quiet", cl::desc("Alias for -q"), cl::aliasopt(Quiet)); //===----------------------------------------------------------------------===// // main for opt // int main(int argc, char **argv) { cl::ParseCommandLineOptions(argc, argv, " llvm .bc -> .bc modular optimizer\n"); // FIXME: This should be parameterizable eventually for different target // types... TargetData TD("opt target"); // Load the input module... std::auto_ptr M(ParseBytecodeFile(InputFilename)); if (M.get() == 0) { cerr << "bytecode didn't read correctly.\n"; return 1; } // Figure out what stream we are supposed to write to... std::ostream *Out = &std::cout; // Default to printing to stdout... if (OutputFilename != "") { if (!Force && std::ifstream(OutputFilename.c_str())) { // If force is not specified, make sure not to overwrite a file! cerr << "Error opening '" << OutputFilename << "': File exists!\n" << "Use -f command line argument to force output\n"; return 1; } Out = new std::ofstream(OutputFilename.c_str()); if (!Out->good()) { cerr << "Error opening " << OutputFilename << "!\n"; return 1; } // Make sure that the Output file gets unlink'd from the disk if we get a // SIGINT RemoveFileOnSignal(OutputFilename); } // Create a PassManager to hold and optimize the collection of passes we are // about to build... // PassManager Passes; // Create a new optimization pass for each one specified on the command line for (unsigned i = 0; i < OptimizationList.size(); ++i) { const PassInfo *Opt = OptimizationList[i]; if (Opt->getNormalCtor()) Passes.add(Opt->getNormalCtor()()); else if (Opt->getDataCtor()) Passes.add(Opt->getDataCtor()(TD)); // Pass dummy target data... else cerr << "Cannot create pass: " << Opt->getPassName() << "\n"; if (PrintEachXForm) Passes.add(new PrintModulePass(&cerr)); } // Check that the module is well formed on completion of optimization Passes.add(createVerifierPass()); // Write bytecode out to disk or cout as the last step... Passes.add(new WriteBytecodePass(Out, Out != &std::cout)); // Now that we have all of the passes ready, run them. if (Passes.run(*M.get()) && !Quiet) cerr << "Program modified.\n"; return 0; }