llc.cpp revision 4ddcd54751f10234be148b648f3986446ffafc54
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/ChangeAllocations.h" 12#include "llvm/Transforms/HoistPHIConstants.h" 13#include "llvm/Assembly/PrintModulePass.h" 14#include "llvm/Bytecode/WriteBytecodePass.h" 15#include "llvm/Transforms/ConstantMerge.h" 16#include "llvm/Module.h" 17#include "llvm/Method.h" 18#include "llvm/PassManager.h" 19#include "Support/CommandLine.h" 20#include <memory> 21#include <string> 22#include <fstream> 23using std::string; 24 25static cl::String InputFilename ("", "Input filename", cl::NoFlags, "-"); 26static cl::String OutputFilename("o", "Output filename", cl::NoFlags, ""); 27static cl::Flag Force ("f", "Overwrite output files"); 28static cl::Flag DumpAsm ("d", "Print bytecode before native code generation", cl::Hidden); 29 30enum TraceLevel { 31 TraceOff, TraceMethods, TraceBasicBlocks 32}; 33 34static cl::Enum<enum TraceLevel> TraceValues("trace", cl::NoFlags, 35 "Trace values through methods or basic blocks", 36 clEnumValN(TraceOff , "off", "Disable trace code"), 37 clEnumValN(TraceMethods , "method", "Trace each method"), 38 clEnumValN(TraceBasicBlocks, "basicblock", "Trace each basic block"), 0); 39 40 41// GetFileNameRoot - Helper function to get the basename of a filename... 42static inline string GetFileNameRoot(const string &InputFilename) { 43 string IFN = InputFilename; 44 string outputFilename; 45 int Len = IFN.length(); 46 if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c') { 47 outputFilename = string(IFN.begin(), IFN.end()-3); // s/.bc/.s/ 48 } else { 49 outputFilename = IFN; 50 } 51 return outputFilename; 52} 53 54 55//===---------------------------------------------------------------------===// 56// Function main() 57// 58// Entry point for the llc compiler. 59//===---------------------------------------------------------------------===// 60 61int main(int argc, char **argv) { 62 cl::ParseCommandLineOptions(argc, argv, " llvm system compiler\n"); 63 64 // Allocate a target... in the future this will be controllable on the 65 // command line. 66 std::auto_ptr<TargetMachine> target(allocateSparcTargetMachine()); 67 assert(target.get() && "Could not allocate target machine!"); 68 69 TargetMachine &Target = *target.get(); 70 71 // Load the module to be compiled... 72 std::auto_ptr<Module> M(ParseBytecodeFile(InputFilename)); 73 if (M.get() == 0) { 74 cerr << "bytecode didn't read correctly.\n"; 75 return 1; 76 } 77 78 // Build up all of the passes that we want to do to the module... 79 PassManager Passes; 80 81 // Hoist constants out of PHI nodes into predecessor BB's 82 Passes.add(createHoistPHIConstantsPass()); 83 84 if (TraceValues != TraceOff) { // If tracing enabled... 85 // Insert trace code in all methods in the module 86 if (TraceValues == TraceBasicBlocks) 87 Passes.add(createTraceValuesPassForBasicBlocks()); 88 else if (TraceValues == TraceMethods) 89 Passes.add(createTraceValuesPassForMethod()); 90 else 91 assert(0 && "Bad value for TraceValues!"); 92 93 // Eliminate duplication in constant pool 94 Passes.add(createDynamicConstantMergePass()); 95 96 // Then write out the module with tracing code before code generation 97 assert(InputFilename != "-" && 98 "files on stdin not supported with tracing"); 99 string traceFileName = GetFileNameRoot(InputFilename) + ".trace.bc"; 100 101 if (!Force && std::ifstream(OutputFilename.c_str())) { 102 // If force is not specified, make sure not to overwrite a file! 103 cerr << "Error opening '" << OutputFilename << "': File exists!\n" 104 << "Use -f command line argument to force output\n"; 105 return 1; 106 } 107 108 std::ostream *os = new std::ofstream(traceFileName.c_str()); 109 if (!os->good()) { 110 cerr << "Error opening " << traceFileName 111 << "! SKIPPING OUTPUT OF TRACE CODE\n"; 112 delete os; 113 return 1; 114 } 115 116 Passes.add(new WriteBytecodePass(os, true)); 117 } 118 119 // Replace malloc and free instructions with library calls. 120 // Do this after tracing until lli implements these lib calls. 121 // For now, it will emulate malloc and free internally. 122 Passes.add(createLowerAllocationsPass(Target.DataLayout)); 123 124 // If LLVM dumping after transformations is requested, add it to the pipeline 125 if (DumpAsm) 126 Passes.add(new PrintMethodPass("Code after xformations: \n", &cerr)); 127 128 // Figure out where we are going to send the output... 129 std::ostream *Out = 0; 130 if (OutputFilename != "") { // Specified an output filename? 131 if (!Force && std::ifstream(OutputFilename.c_str())) { 132 // If force is not specified, make sure not to overwrite a file! 133 cerr << "Error opening '" << OutputFilename << "': File exists!\n" 134 << "Use -f command line argument to force output\n"; 135 return 1; 136 } 137 Out = new std::ofstream(OutputFilename.c_str()); 138 } else { 139 if (InputFilename == "-") { 140 OutputFilename = "-"; 141 Out = &std::cout; 142 } else { 143 string OutputFilename = GetFileNameRoot(InputFilename); 144 OutputFilename += ".s"; 145 146 if (!Force && std::ifstream(OutputFilename.c_str())) { 147 // If force is not specified, make sure not to overwrite a file! 148 cerr << "Error opening '" << OutputFilename << "': File exists!\n" 149 << "Use -f command line argument to force output\n"; 150 return 1; 151 } 152 153 Out = new std::ofstream(OutputFilename.c_str()); 154 if (!Out->good()) { 155 cerr << "Error opening " << OutputFilename << "!\n"; 156 delete Out; 157 return 1; 158 } 159 } 160 } 161 162 Target.addPassesToEmitAssembly(Passes, *Out); 163 164 // Run our queue of passes all at once now, efficiently. 165 Passes.run(M.get()); 166 167 if (Out != &std::cout) delete Out; 168 169 return 0; 170} 171