llc.cpp revision 712ac2b951ea563dec9d0fc33a469fade3fe832e
1//===-- llc.cpp - Implement the LLVM Compiler -----------------------------===// 2// 3// This is the llc compiler driver. 4// 5//===----------------------------------------------------------------------===// 6 7#include "llvm/Bytecode/Reader.h" 8#include "llvm/Target/Sparc.h" 9#include "llvm/Target/TargetMachine.h" 10#include "llvm/Transforms/Instrumentation/TraceValues.h" 11#include "llvm/Transforms/LowerAllocations.h" 12#include "llvm/Transforms/HoistPHIConstants.h" 13#include "llvm/Transforms/PrintModulePass.h" 14#include "llvm/Support/CommandLine.h" 15#include "llvm/Module.h" 16#include "llvm/Method.h" 17#include <memory> 18#include <string> 19#include <fstream> 20 21cl::String InputFilename ("", "Input filename", cl::NoFlags, "-"); 22cl::String OutputFilename("o", "Output filename", cl::NoFlags, ""); 23cl::Flag Force ("f", "Overwrite output files"); 24cl::Flag DumpAsm ("d", "Print bytecode before native code generation", 25 cl::Hidden); 26cl::Flag DoNotEmitAssembly("noasm", "Do not emit assembly code", cl::Hidden); 27cl::Flag TraceBBValues ("trace", 28 "Trace values at basic block and method exits"); 29cl::Flag TraceMethodValues("tracem", "Trace values only at method exits"); 30cl::Flag DebugTrace ("debugtrace", 31 "output trace code as assembly instead of bytecode"); 32 33 34// GetFileNameRoot - Helper function to get the basename of a filename... 35static inline string GetFileNameRoot(const string &InputFilename) { 36 string IFN = InputFilename; 37 string outputFilename; 38 int Len = IFN.length(); 39 if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c') { 40 outputFilename = string(IFN.begin(), IFN.end()-3); // s/.bc/.s/ 41 } else { 42 outputFilename = IFN; 43 } 44 return outputFilename; 45} 46 47 48//===---------------------------------------------------------------------===// 49// GenerateCodeForTarget Pass 50// 51// Native code generation for a specified target. 52//===---------------------------------------------------------------------===// 53 54class GenerateCodeForTarget : public Pass { 55 TargetMachine &Target; 56public: 57 inline GenerateCodeForTarget(TargetMachine &T) : Target(T) {} 58 59 // doPerMethodWork - This method does the actual work of generating code for 60 // the specified method. 61 // 62 bool doPerMethodWork(Method *M) { 63 if (!M->isExternal() && Target.compileMethod(M)) { 64 cerr << "Error compiling " << InputFilename << "!\n"; 65 return true; 66 } 67 68 return false; 69 } 70}; 71 72 73//===---------------------------------------------------------------------===// 74// EmitAssembly Pass 75// 76// Write assembly code to specified output stream 77//===---------------------------------------------------------------------===// 78 79class EmitAssembly : public Pass { 80 const TargetMachine &Target; // Target to compile for 81 ostream *Out; // Stream to print on 82 bool DeleteStream; // Delete stream in dtor? 83public: 84 inline EmitAssembly(const TargetMachine &T, ostream *O, bool D) 85 : Target(T), Out(O), DeleteStream(D) {} 86 87 88 virtual bool doPassFinalization(Module *M) { 89 Target.emitAssembly(M, *Out); 90 91 if (DeleteStream) delete Out; 92 return false; 93 } 94}; 95 96 97//===---------------------------------------------------------------------===// 98// Function main() 99// 100// Entry point for the llc compiler. 101//===---------------------------------------------------------------------===// 102 103int main(int argc, char **argv) { 104 int retCode = 0; 105 cl::ParseCommandLineOptions(argc, argv, " llvm system compiler\n"); 106 107 // Allocate a target... in the future this will be controllable on the 108 // command line. 109 auto_ptr<TargetMachine> target(allocateSparcTargetMachine()); 110 assert(target.get() && "Could not allocate target machine!"); 111 112 TargetMachine &Target = *target.get(); 113 114 // Load the module to be compiled... 115 auto_ptr<Module> M(ParseBytecodeFile(InputFilename)); 116 if (M.get() == 0) { 117 cerr << "bytecode didn't read correctly.\n"; 118 return 1; 119 } 120 121 // Build up all of the passes that we want to do to the module... 122 vector<Pass*> Passes; 123 124 // Hoist constants out of PHI nodes into predecessor BB's 125 Passes.push_back(new HoistPHIConstants()); 126 127 if (TraceBBValues || TraceMethodValues) // If tracing enabled... 128 { 129 // Insert trace code in all methods in the module 130 Passes.push_back(new InsertTraceCode(TraceBBValues, 131 TraceBBValues ||TraceMethodValues)); 132 133 // Then write out the module with tracing code before code generation 134 assert(InputFilename != "-" && 135 "files on stdin not supported with tracing"); 136 string traceFileName = GetFileNameRoot(InputFilename) 137 + (DebugTrace? ".trace.ll" : ".trace.bc"); 138 ostream *os = new ofstream(traceFileName.c_str(), 139 (Force ? 0 : ios::noreplace)|ios::out); 140 if (!os->good()) { 141 cerr << "Error opening " << traceFileName 142 << "! SKIPPING OUTPUT OF TRACE CODE\n"; 143 delete os; 144 retCode = 1; 145 } else { 146 Passes.push_back(new PrintModulePass("", os, 147 /*deleteStream*/ true, 148 /*printPerMethod*/ false, 149 /*printAsBytecode*/ !DebugTrace)); 150 } 151 } 152 153 // Replace malloc and free instructions with library calls. 154 // Do this after tracing until lli implements these lib calls. 155 // For now, it will emulate malloc and free internally. 156 Passes.push_back(new LowerAllocations(Target.DataLayout)); 157 158 // If LLVM dumping after transformations is requested, add it to the pipeline 159 if (DumpAsm) 160 Passes.push_back(new PrintModulePass("Code after xformations: \n",&cerr)); 161 162 // Generate Target code... 163 Passes.push_back(new GenerateCodeForTarget(Target)); 164 165 if (!DoNotEmitAssembly) { // If asm output is enabled... 166 // Figure out where we are going to send the output... 167 ostream *Out = 0; 168 if (OutputFilename != "") { // Specified an output filename? 169 Out = new ofstream(OutputFilename.c_str(), 170 (Force ? 0 : ios::noreplace)|ios::out); 171 } else { 172 if (InputFilename == "-") { 173 OutputFilename = "-"; 174 Out = &cout; 175 } else { 176 string OutputFilename = GetFileNameRoot(InputFilename); 177 OutputFilename += ".s"; 178 Out = new ofstream(OutputFilename.c_str(), 179 (Force ? 0 : ios::noreplace)|ios::out); 180 if (!Out->good()) { 181 cerr << "Error opening " << OutputFilename << "!\n"; 182 delete Out; 183 return 1; 184 } 185 } 186 } 187 188 // Output assembly language to the .s file 189 Passes.push_back(new EmitAssembly(Target, Out, Out != &cout)); 190 } 191 192 // Run our queue of passes all at once now, efficiently. This form of 193 // runAllPasses frees the Pass objects after runAllPasses completes. 194 Pass::runAllPassesAndFree(M.get(), Passes); 195 196 return retCode; 197} 198 199 200