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