| Chris Lattner | b79757c | 2001-10-04 01:40:53 +0000 | [diff] [blame] | 1 | //===-- llc.cpp - Implement the LLVM Compiler -----------------------------===// | 
| Chris Lattner | e737c7a | 2001-09-07 22:20:50 +0000 | [diff] [blame] | 2 | // | 
 | 3 | // This is the llc compiler driver. | 
 | 4 | // | 
| Chris Lattner | b79757c | 2001-10-04 01:40:53 +0000 | [diff] [blame] | 5 | //===----------------------------------------------------------------------===// | 
| Vikram S. Adve | cb465fc | 2001-07-21 12:42:29 +0000 | [diff] [blame] | 6 |  | 
| Vikram S. Adve | cb465fc | 2001-07-21 12:42:29 +0000 | [diff] [blame] | 7 | #include "llvm/Bytecode/Reader.h" | 
| Chris Lattner | b26bcc5 | 2001-09-14 05:34:53 +0000 | [diff] [blame] | 8 | #include "llvm/Target/Sparc.h" | 
| Vikram S. Adve | 805eb96 | 2001-09-18 13:10:45 +0000 | [diff] [blame] | 9 | #include "llvm/Target/TargetMachine.h" | 
| Vikram S. Adve | 2f64f9f | 2001-10-14 23:29:28 +0000 | [diff] [blame] | 10 | #include "llvm/Transforms/Instrumentation/TraceValues.h" | 
| Chris Lattner | 65f1b89 | 2002-05-07 20:03:27 +0000 | [diff] [blame] | 11 | #include "llvm/Transforms/Scalar.h" | 
| Chris Lattner | 39fd659 | 2002-05-20 21:20:08 +0000 | [diff] [blame] | 12 | #include "llvm/Transforms/Utils/Linker.h" | 
| Chris Lattner | 2197d21 | 2001-10-18 20:32:07 +0000 | [diff] [blame] | 13 | #include "llvm/Assembly/PrintModulePass.h" | 
 | 14 | #include "llvm/Bytecode/WriteBytecodePass.h" | 
| Chris Lattner | d9d8c07 | 2002-07-23 22:04:43 +0000 | [diff] [blame] | 15 | #include "llvm/Transforms/IPO.h" | 
| Chris Lattner | 46ac43c | 2001-09-07 21:26:31 +0000 | [diff] [blame] | 16 | #include "llvm/Module.h" | 
| Chris Lattner | 2fbfdcf | 2002-04-07 20:49:59 +0000 | [diff] [blame] | 17 | #include "llvm/Function.h" | 
| Chris Lattner | cd50d3f | 2002-01-31 00:46:45 +0000 | [diff] [blame] | 18 | #include "llvm/PassManager.h" | 
| Chris Lattner | cee8f9a | 2001-11-27 00:03:19 +0000 | [diff] [blame] | 19 | #include "Support/CommandLine.h" | 
| Chris Lattner | 76d1229 | 2002-04-18 19:55:25 +0000 | [diff] [blame] | 20 | #include "Support/Signals.h" | 
| Chris Lattner | da784ee | 2001-09-18 17:04:18 +0000 | [diff] [blame] | 21 | #include <memory> | 
| Chris Lattner | 78f7e1a | 2001-09-19 16:52:09 +0000 | [diff] [blame] | 22 | #include <fstream> | 
| Chris Lattner | 697954c | 2002-01-20 22:54:45 +0000 | [diff] [blame] | 23 | using std::string; | 
| Anand Shukla | cf17bcc | 2002-06-25 21:57:48 +0000 | [diff] [blame] | 24 | using std::cerr; | 
| Chris Lattner | 8f367bd | 2001-07-23 02:35:57 +0000 | [diff] [blame] | 25 |  | 
| Chris Lattner | 5ff62e9 | 2002-07-22 02:10:13 +0000 | [diff] [blame] | 26 | static cl::opt<string> | 
 | 27 | InputFilename(cl::Positional, cl::desc("<input bytecode>"), cl::init("-")); | 
 | 28 |  | 
 | 29 | static cl::opt<string> | 
 | 30 | OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename")); | 
 | 31 |  | 
 | 32 | static cl::opt<bool> Force("f", cl::desc("Overwrite output files")); | 
 | 33 |  | 
 | 34 | static cl::opt<bool> | 
 | 35 | DumpAsm("d", cl::desc("Print bytecode before native code generation"), | 
 | 36 |         cl::Hidden); | 
 | 37 |  | 
 | 38 | static cl::opt<string> | 
 | 39 | TraceLibPath("tracelibpath", cl::desc("Path to libinstr for trace code"), | 
 | 40 |              cl::value_desc("directory"), cl::Hidden); | 
| Chris Lattner | 4ddcd54 | 2002-02-26 21:36:53 +0000 | [diff] [blame] | 41 |  | 
 | 42 | enum TraceLevel { | 
| Chris Lattner | 2fbfdcf | 2002-04-07 20:49:59 +0000 | [diff] [blame] | 43 |   TraceOff, TraceFunctions, TraceBasicBlocks | 
| Chris Lattner | 4ddcd54 | 2002-02-26 21:36:53 +0000 | [diff] [blame] | 44 | }; | 
 | 45 |  | 
| Chris Lattner | 5ff62e9 | 2002-07-22 02:10:13 +0000 | [diff] [blame] | 46 | static cl::opt<TraceLevel> | 
 | 47 | TraceValues("trace", cl::desc("Trace values through functions or basic blocks"), | 
 | 48 |             cl::values( | 
| Chris Lattner | 4ddcd54 | 2002-02-26 21:36:53 +0000 | [diff] [blame] | 49 |   clEnumValN(TraceOff        , "off",        "Disable trace code"), | 
| Chris Lattner | 2fbfdcf | 2002-04-07 20:49:59 +0000 | [diff] [blame] | 50 |   clEnumValN(TraceFunctions  , "function",   "Trace each function"), | 
| Chris Lattner | 5ff62e9 | 2002-07-22 02:10:13 +0000 | [diff] [blame] | 51 |   clEnumValN(TraceBasicBlocks, "basicblock", "Trace each basic block"), | 
 | 52 |                        0)); | 
| Vikram S. Adve | 805eb96 | 2001-09-18 13:10:45 +0000 | [diff] [blame] | 53 |  | 
| Chris Lattner | 3524fc2 | 2001-10-15 17:30:47 +0000 | [diff] [blame] | 54 | // GetFileNameRoot - Helper function to get the basename of a filename... | 
 | 55 | static inline string GetFileNameRoot(const string &InputFilename) { | 
| Vikram S. Adve | 2f64f9f | 2001-10-14 23:29:28 +0000 | [diff] [blame] | 56 |   string IFN = InputFilename; | 
 | 57 |   string outputFilename; | 
 | 58 |   int Len = IFN.length(); | 
 | 59 |   if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c') { | 
 | 60 |     outputFilename = string(IFN.begin(), IFN.end()-3); // s/.bc/.s/ | 
 | 61 |   } else { | 
| Chris Lattner | 3524fc2 | 2001-10-15 17:30:47 +0000 | [diff] [blame] | 62 |     outputFilename = IFN; | 
| Vikram S. Adve | 2f64f9f | 2001-10-14 23:29:28 +0000 | [diff] [blame] | 63 |   } | 
 | 64 |   return outputFilename; | 
 | 65 | } | 
 | 66 |  | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 67 | static void insertTraceCodeFor(Module &M) { | 
| Chris Lattner | 39fd659 | 2002-05-20 21:20:08 +0000 | [diff] [blame] | 68 |   PassManager Passes; | 
 | 69 |  | 
 | 70 |   // Insert trace code in all functions in the module | 
 | 71 |   switch (TraceValues) { | 
 | 72 |   case TraceBasicBlocks: | 
 | 73 |     Passes.add(createTraceValuesPassForBasicBlocks()); | 
 | 74 |     break; | 
 | 75 |   case TraceFunctions: | 
 | 76 |     Passes.add(createTraceValuesPassForFunction()); | 
 | 77 |     break; | 
 | 78 |   default: | 
 | 79 |     assert(0 && "Bad value for TraceValues!"); | 
 | 80 |     abort(); | 
 | 81 |   } | 
 | 82 |    | 
 | 83 |   // Eliminate duplication in constant pool | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 84 |   Passes.add(createConstantMergePass()); | 
| Chris Lattner | 39fd659 | 2002-05-20 21:20:08 +0000 | [diff] [blame] | 85 |  | 
 | 86 |   // Run passes to insert and clean up trace code... | 
 | 87 |   Passes.run(M); | 
 | 88 |  | 
 | 89 |   std::string ErrorMessage; | 
 | 90 |  | 
 | 91 |   // Load the module that contains the runtime helper routines neccesary for | 
 | 92 |   // pointer hashing and stuff...  link this module into the program if possible | 
 | 93 |   // | 
 | 94 |   Module *TraceModule = ParseBytecodeFile(TraceLibPath+"libinstr.bc"); | 
 | 95 |  | 
 | 96 |   // Ok, the TraceLibPath didn't contain a valid module.  Try to load the module | 
 | 97 |   // from the current LLVM-GCC install directory.  This is kindof a hack, but | 
 | 98 |   // allows people to not HAVE to have built the library. | 
 | 99 |   // | 
 | 100 |   if (TraceModule == 0) | 
 | 101 |     TraceModule = ParseBytecodeFile("/home/vadve/lattner/cvs/gcc_install/lib/" | 
 | 102 |                                     "gcc-lib/llvm/3.1/libinstr.bc"); | 
 | 103 |  | 
 | 104 |   // If we still didn't get it, cancel trying to link it in... | 
 | 105 |   if (TraceModule == 0) { | 
 | 106 |     cerr << "Warning, could not load trace routines to link into program!\n"; | 
 | 107 |   } else { | 
 | 108 |  | 
 | 109 |     // Link in the trace routines... if the link fails, don't panic, because the | 
 | 110 |     // compile should still succeed, just the native linker will probably fail. | 
 | 111 |     // | 
 | 112 |     std::auto_ptr<Module> TraceRoutines(TraceModule); | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 113 |     if (LinkModules(&M, TraceRoutines.get(), &ErrorMessage)) | 
| Chris Lattner | 39fd659 | 2002-05-20 21:20:08 +0000 | [diff] [blame] | 114 |       cerr << "Warning: Error linking in trace routines: " | 
 | 115 |            << ErrorMessage << "\n"; | 
 | 116 |   } | 
 | 117 |  | 
 | 118 |  | 
 | 119 |   // Write out the module with tracing code just before code generation | 
 | 120 |   if (InputFilename != "-") { | 
 | 121 |     string TraceFilename = GetFileNameRoot(InputFilename) + ".trace.bc"; | 
 | 122 |  | 
 | 123 |     std::ofstream Out(TraceFilename.c_str()); | 
 | 124 |     if (!Out.good()) { | 
 | 125 |       cerr << "Error opening '" << TraceFilename | 
 | 126 |            << "'!: Skipping output of trace code as bytecode\n"; | 
 | 127 |     } else { | 
 | 128 |       cerr << "Emitting trace code to '" << TraceFilename | 
 | 129 |            << "' for comparison...\n"; | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 130 |       WriteBytecodeToFile(&M, Out); | 
| Chris Lattner | 39fd659 | 2002-05-20 21:20:08 +0000 | [diff] [blame] | 131 |     } | 
 | 132 |   } | 
 | 133 |  | 
 | 134 | } | 
 | 135 |    | 
| Vikram S. Adve | 805eb96 | 2001-09-18 13:10:45 +0000 | [diff] [blame] | 136 |  | 
 | 137 | //===---------------------------------------------------------------------===// | 
| Vikram S. Adve | 2f64f9f | 2001-10-14 23:29:28 +0000 | [diff] [blame] | 138 | // Function main() | 
 | 139 | //  | 
 | 140 | // Entry point for the llc compiler. | 
 | 141 | //===---------------------------------------------------------------------===// | 
 | 142 |  | 
| Chris Lattner | 25c1229 | 2001-10-15 17:41:24 +0000 | [diff] [blame] | 143 | int main(int argc, char **argv) { | 
| Vikram S. Adve | 2f64f9f | 2001-10-14 23:29:28 +0000 | [diff] [blame] | 144 |   cl::ParseCommandLineOptions(argc, argv, " llvm system compiler\n"); | 
 | 145 |    | 
 | 146 |   // Allocate a target... in the future this will be controllable on the | 
 | 147 |   // command line. | 
| Chris Lattner | 697954c | 2002-01-20 22:54:45 +0000 | [diff] [blame] | 148 |   std::auto_ptr<TargetMachine> target(allocateSparcTargetMachine()); | 
| Chris Lattner | 3524fc2 | 2001-10-15 17:30:47 +0000 | [diff] [blame] | 149 |   assert(target.get() && "Could not allocate target machine!"); | 
 | 150 |  | 
 | 151 |   TargetMachine &Target = *target.get(); | 
| Vikram S. Adve | 2f64f9f | 2001-10-14 23:29:28 +0000 | [diff] [blame] | 152 |    | 
 | 153 |   // Load the module to be compiled... | 
| Chris Lattner | 697954c | 2002-01-20 22:54:45 +0000 | [diff] [blame] | 154 |   std::auto_ptr<Module> M(ParseBytecodeFile(InputFilename)); | 
| Vikram S. Adve | 2f64f9f | 2001-10-14 23:29:28 +0000 | [diff] [blame] | 155 |   if (M.get() == 0) { | 
| Chris Lattner | 50e3a20 | 2002-07-30 21:43:22 +0000 | [diff] [blame^] | 156 |     cerr << argv[0] << ": bytecode didn't read correctly.\n"; | 
| Vikram S. Adve | 2f64f9f | 2001-10-14 23:29:28 +0000 | [diff] [blame] | 157 |     return 1; | 
 | 158 |   } | 
| Chris Lattner | 3524fc2 | 2001-10-15 17:30:47 +0000 | [diff] [blame] | 159 |  | 
| Chris Lattner | 39fd659 | 2002-05-20 21:20:08 +0000 | [diff] [blame] | 160 |   if (TraceValues != TraceOff)    // If tracing enabled... | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 161 |     insertTraceCodeFor(*M.get()); // Hack up module before using passmanager... | 
| Chris Lattner | 39fd659 | 2002-05-20 21:20:08 +0000 | [diff] [blame] | 162 |  | 
| Chris Lattner | 3524fc2 | 2001-10-15 17:30:47 +0000 | [diff] [blame] | 163 |   // Build up all of the passes that we want to do to the module... | 
| Chris Lattner | f4de63f | 2002-01-21 07:31:50 +0000 | [diff] [blame] | 164 |   PassManager Passes; | 
| Chris Lattner | 3524fc2 | 2001-10-15 17:30:47 +0000 | [diff] [blame] | 165 |  | 
| Vikram S. Adve | d32e70a | 2002-03-24 03:19:54 +0000 | [diff] [blame] | 166 |   // Decompose multi-dimensional refs into a sequence of 1D refs | 
 | 167 |   Passes.add(createDecomposeMultiDimRefsPass()); | 
 | 168 |    | 
| Vikram S. Adve | 712ac2b | 2001-10-18 18:20:20 +0000 | [diff] [blame] | 169 |   // Replace malloc and free instructions with library calls. | 
 | 170 |   // Do this after tracing until lli implements these lib calls. | 
 | 171 |   // For now, it will emulate malloc and free internally. | 
| Chris Lattner | 4ddcd54 | 2002-02-26 21:36:53 +0000 | [diff] [blame] | 172 |   Passes.add(createLowerAllocationsPass(Target.DataLayout)); | 
| Vikram S. Adve | 712ac2b | 2001-10-18 18:20:20 +0000 | [diff] [blame] | 173 |    | 
| Chris Lattner | 3524fc2 | 2001-10-15 17:30:47 +0000 | [diff] [blame] | 174 |   // If LLVM dumping after transformations is requested, add it to the pipeline | 
 | 175 |   if (DumpAsm) | 
| Chris Lattner | 02d6ef8 | 2002-04-08 22:05:01 +0000 | [diff] [blame] | 176 |     Passes.add(new PrintFunctionPass("Code after xformations: \n", &cerr)); | 
| Chris Lattner | 3524fc2 | 2001-10-15 17:30:47 +0000 | [diff] [blame] | 177 |  | 
| Chris Lattner | c5fbf71 | 2002-06-30 16:25:07 +0000 | [diff] [blame] | 178 |   // Strip all of the symbols from the bytecode so that it will be smaller... | 
 | 179 |   Passes.add(createSymbolStrippingPass()); | 
 | 180 |  | 
| Chris Lattner | e41576d | 2002-02-03 23:43:19 +0000 | [diff] [blame] | 181 |   // Figure out where we are going to send the output... | 
 | 182 |   std::ostream *Out = 0; | 
 | 183 |   if (OutputFilename != "") {   // Specified an output filename? | 
 | 184 |     if (!Force && std::ifstream(OutputFilename.c_str())) { | 
 | 185 |       // If force is not specified, make sure not to overwrite a file! | 
| Chris Lattner | 50e3a20 | 2002-07-30 21:43:22 +0000 | [diff] [blame^] | 186 |       cerr << argv[0] << ": error opening '" << OutputFilename | 
 | 187 |            << "': file exists!\n" | 
| Chris Lattner | e41576d | 2002-02-03 23:43:19 +0000 | [diff] [blame] | 188 |            << "Use -f command line argument to force output\n"; | 
 | 189 |       return 1; | 
 | 190 |     } | 
 | 191 |     Out = new std::ofstream(OutputFilename.c_str()); | 
| Chris Lattner | 76d1229 | 2002-04-18 19:55:25 +0000 | [diff] [blame] | 192 |  | 
 | 193 |     // Make sure that the Out file gets unlink'd from the disk if we get a | 
 | 194 |     // SIGINT | 
 | 195 |     RemoveFileOnSignal(OutputFilename); | 
| Chris Lattner | e41576d | 2002-02-03 23:43:19 +0000 | [diff] [blame] | 196 |   } else { | 
 | 197 |     if (InputFilename == "-") { | 
 | 198 |       OutputFilename = "-"; | 
 | 199 |       Out = &std::cout; | 
 | 200 |     } else { | 
 | 201 |       string OutputFilename = GetFileNameRoot(InputFilename);  | 
 | 202 |       OutputFilename += ".s"; | 
| Chris Lattner | 3524fc2 | 2001-10-15 17:30:47 +0000 | [diff] [blame] | 203 |  | 
| Chris Lattner | 888912d | 2002-01-22 21:07:24 +0000 | [diff] [blame] | 204 |       if (!Force && std::ifstream(OutputFilename.c_str())) { | 
| Chris Lattner | 697954c | 2002-01-20 22:54:45 +0000 | [diff] [blame] | 205 |         // If force is not specified, make sure not to overwrite a file! | 
| Chris Lattner | 50e3a20 | 2002-07-30 21:43:22 +0000 | [diff] [blame^] | 206 |         cerr << argv[0] << ": error opening '" << OutputFilename | 
 | 207 |              << "': file exists!\n" | 
| Chris Lattner | 697954c | 2002-01-20 22:54:45 +0000 | [diff] [blame] | 208 |              << "Use -f command line argument to force output\n"; | 
 | 209 |         return 1; | 
 | 210 |       } | 
| Chris Lattner | e41576d | 2002-02-03 23:43:19 +0000 | [diff] [blame] | 211 |  | 
| Chris Lattner | 697954c | 2002-01-20 22:54:45 +0000 | [diff] [blame] | 212 |       Out = new std::ofstream(OutputFilename.c_str()); | 
| Chris Lattner | e41576d | 2002-02-03 23:43:19 +0000 | [diff] [blame] | 213 |       if (!Out->good()) { | 
| Chris Lattner | 50e3a20 | 2002-07-30 21:43:22 +0000 | [diff] [blame^] | 214 |         cerr << argv[0] << ": error opening " << OutputFilename << "!\n"; | 
| Chris Lattner | e41576d | 2002-02-03 23:43:19 +0000 | [diff] [blame] | 215 |         delete Out; | 
 | 216 |         return 1; | 
| Chris Lattner | 3524fc2 | 2001-10-15 17:30:47 +0000 | [diff] [blame] | 217 |       } | 
| Chris Lattner | 76d1229 | 2002-04-18 19:55:25 +0000 | [diff] [blame] | 218 |       // Make sure that the Out file gets unlink'd from the disk if we get a | 
 | 219 |       // SIGINT | 
 | 220 |       RemoveFileOnSignal(OutputFilename); | 
| Chris Lattner | 3524fc2 | 2001-10-15 17:30:47 +0000 | [diff] [blame] | 221 |     } | 
| Chris Lattner | 3524fc2 | 2001-10-15 17:30:47 +0000 | [diff] [blame] | 222 |   } | 
| Vikram S. Adve | 2f64f9f | 2001-10-14 23:29:28 +0000 | [diff] [blame] | 223 |    | 
| Chris Lattner | e41576d | 2002-02-03 23:43:19 +0000 | [diff] [blame] | 224 |   Target.addPassesToEmitAssembly(Passes, *Out); | 
 | 225 |    | 
| Chris Lattner | f4de63f | 2002-01-21 07:31:50 +0000 | [diff] [blame] | 226 |   // Run our queue of passes all at once now, efficiently. | 
| Chris Lattner | 7e70829 | 2002-06-25 16:13:24 +0000 | [diff] [blame] | 227 |   Passes.run(*M.get()); | 
| Chris Lattner | 05e5e07 | 2001-10-18 01:31:22 +0000 | [diff] [blame] | 228 |  | 
| Chris Lattner | e41576d | 2002-02-03 23:43:19 +0000 | [diff] [blame] | 229 |   if (Out != &std::cout) delete Out; | 
 | 230 |  | 
| Chris Lattner | d7477ee | 2001-10-18 20:33:21 +0000 | [diff] [blame] | 231 |   return 0; | 
| Vikram S. Adve | 2f64f9f | 2001-10-14 23:29:28 +0000 | [diff] [blame] | 232 | } |