llc.cpp revision 68492725a08ca3b356f24b90cdfc57a247abbeb3
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/TargetMachineImpls.h" 9#include "llvm/Target/TargetMachine.h" 10#include "llvm/Transforms/Instrumentation.h" 11#include "llvm/Transforms/Scalar.h" 12#include "llvm/Transforms/Utils/Linker.h" 13#include "llvm/Assembly/PrintModulePass.h" 14#include "llvm/Bytecode/WriteBytecodePass.h" 15#include "llvm/Transforms/IPO.h" 16#include "llvm/Module.h" 17#include "llvm/PassManager.h" 18#include "llvm/Pass.h" 19#include "llvm/Support/PassNameParser.h" 20#include "Support/CommandLine.h" 21#include "Support/Signals.h" 22#include <memory> 23#include <fstream> 24 25//------------------------------------------------------------------------------ 26// Option declarations for LLC. 27//------------------------------------------------------------------------------ 28 29// Make all registered optimization passes available to llc. These passes 30// will all be run before the simplification and lowering steps used by the 31// back-end code generator, and will be run in the order specified on the 32// command line. The OptimizationList is automatically populated with 33// registered Passes by the PassNameParser. 34// 35static cl::list<const PassInfo*, bool, 36 FilteredPassNameParser<PassInfo::Optimization> > 37OptimizationList(cl::desc("Optimizations available:")); 38 39 40// General options for llc. Other pass-specific options are specified 41// within the corresponding llc passes, and target-specific options 42// and back-end code generation options are specified with the target machine. 43// 44static cl::opt<std::string> 45InputFilename(cl::Positional, cl::desc("<input bytecode>"), cl::init("-")); 46 47static cl::opt<std::string> 48OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename")); 49 50static cl::opt<bool> Force("f", cl::desc("Overwrite output files")); 51 52static cl::opt<bool> 53DisableStrip("disable-strip", 54 cl::desc("Do not strip the LLVM bytecode included in the executable")); 55 56static cl::opt<bool> 57DumpAsm("d", cl::desc("Print bytecode before native code generation"), 58 cl::Hidden); 59 60static cl::opt<std::string> 61TraceLibPath("tracelibpath", cl::desc("Path to libinstr for trace code"), 62 cl::value_desc("directory"), cl::Hidden); 63 64 65// flags set from -tracem and -trace options to control tracing 66static bool TraceFunctions = false; 67static bool TraceBasicBlocks = false; 68 69 70// GetFileNameRoot - Helper function to get the basename of a filename... 71static inline std::string 72GetFileNameRoot(const std::string &InputFilename) 73{ 74 std::string IFN = InputFilename; 75 std::string outputFilename; 76 int Len = IFN.length(); 77 if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c') { 78 outputFilename = std::string(IFN.begin(), IFN.end()-3); // s/.bc/.s/ 79 } else { 80 outputFilename = IFN; 81 } 82 return outputFilename; 83} 84 85static bool 86insertTraceCodeFor(Module &M) 87{ 88 PassManager Passes; 89 90 // Insert trace code in all functions in the module 91 if (TraceBasicBlocks) 92 Passes.add(createTraceValuesPassForBasicBlocks()); 93 else if (TraceFunctions) 94 Passes.add(createTraceValuesPassForFunction()); 95 else 96 return false; 97 98 // Eliminate duplication in constant pool 99 Passes.add(createConstantMergePass()); 100 101 // Run passes to insert and clean up trace code... 102 Passes.run(M); 103 104 std::string ErrorMessage; 105 106 // Load the module that contains the runtime helper routines neccesary for 107 // pointer hashing and stuff... link this module into the program if possible 108 // 109 Module *TraceModule = ParseBytecodeFile(TraceLibPath+"libinstr.bc"); 110 111 // Check if the TraceLibPath contains a valid module. If not, try to load 112 // the module from the current LLVM-GCC install directory. This is kindof 113 // a hack, but allows people to not HAVE to have built the library. 114 // 115 if (TraceModule == 0) 116 TraceModule = ParseBytecodeFile("/home/vadve/lattner/cvs/gcc_install/lib/" 117 "gcc-lib/llvm/3.1/libinstr.bc"); 118 119 // If we still didn't get it, cancel trying to link it in... 120 if (TraceModule == 0) 121 std::cerr <<"WARNING: couldn't load trace routines to link into program!\n"; 122 else 123 { 124 // Link in the trace routines... if this fails, don't panic, because the 125 // compile should still succeed, but the native linker will probably fail. 126 // 127 std::auto_ptr<Module> TraceRoutines(TraceModule); 128 if (LinkModules(&M, TraceRoutines.get(), &ErrorMessage)) 129 std::cerr << "WARNING: Error linking in trace routines: " 130 << ErrorMessage << "\n"; 131 } 132 133 // Write out the module with tracing code just before code generation 134 assert (InputFilename != "-" 135 && "Cannot write out traced bytecode when reading input from stdin"); 136 std::string TraceFilename = GetFileNameRoot(InputFilename) + ".trace.bc"; 137 138 std::ofstream Out(TraceFilename.c_str()); 139 if (!Out.good()) 140 std::cerr << "Error opening '" << TraceFilename 141 << "'!: Skipping output of trace code as bytecode\n"; 142 else 143 { 144 std::cerr << "Emitting trace code to '" << TraceFilename 145 << "' for comparison...\n"; 146 WriteBytecodeToFile(&M, Out); 147 } 148 149 return true; 150} 151 152// Making tracing a module pass so the entire module with tracing 153// can be written out before continuing. 154struct InsertTracingCodePass: public Pass { 155 virtual bool run(Module &M) { 156 return insertTraceCodeFor(M); 157 } 158}; 159 160 161//===---------------------------------------------------------------------===// 162// Function main() 163// 164// Entry point for the llc compiler. 165//===---------------------------------------------------------------------===// 166 167int 168main(int argc, char **argv) 169{ 170 cl::ParseCommandLineOptions(argc, argv, " llvm system compiler\n"); 171 172 // Allocate a target... in the future this will be controllable on the 173 // command line. 174 std::auto_ptr<TargetMachine> target(allocateSparcTargetMachine()); 175 assert(target.get() && "Could not allocate target machine!"); 176 177 TargetMachine &Target = *target.get(); 178 const TargetData &TD = Target.getTargetData(); 179 180 // Load the module to be compiled... 181 std::auto_ptr<Module> M(ParseBytecodeFile(InputFilename)); 182 if (M.get() == 0) 183 { 184 std::cerr << argv[0] << ": bytecode didn't read correctly.\n"; 185 return 1; 186 } 187 188 // Build up all of the passes that we want to do to the module... 189 PassManager Passes; 190 191 Passes.add(new TargetData("llc", TD.isLittleEndian(), TD.getPointerSize(), 192 TD.getPointerAlignment(), TD.getDoubleAlignment())); 193 194 // Create a new optimization pass for each one specified on the command line 195 // Deal specially with tracing passes, which must be run differently than opt. 196 // 197 for (unsigned i = 0; i < OptimizationList.size(); ++i) 198 { 199 const PassInfo *Opt = OptimizationList[i]; 200 201 if (std::string(Opt->getPassArgument()) == "trace") 202 TraceFunctions = !(TraceBasicBlocks = true); 203 else if (std::string(Opt->getPassArgument()) == "tracem") 204 TraceFunctions = !(TraceBasicBlocks = false); 205 else 206 { // handle other passes as normal optimization passes 207 if (Opt->getNormalCtor()) 208 Passes.add(Opt->getNormalCtor()()); 209 else if (Opt->getTargetCtor()) 210 Passes.add(Opt->getTargetCtor()(Target)); 211 else 212 std::cerr << argv[0] << ": cannot create pass: " 213 << Opt->getPassName() << "\n"; 214 } 215 } 216 217 // Run tracing passes after other optimization passes and before llc passes. 218 if (TraceFunctions || TraceBasicBlocks) 219 Passes.add(new InsertTracingCodePass); 220 221 // Decompose multi-dimensional refs into a sequence of 1D refs 222 Passes.add(createDecomposeMultiDimRefsPass()); 223 224 // Replace malloc and free instructions with library calls. 225 // Do this after tracing until lli implements these lib calls. 226 // For now, it will emulate malloc and free internally. 227 Passes.add(createLowerAllocationsPass()); 228 229 // If LLVM dumping after transformations is requested, add it to the pipeline 230 if (DumpAsm) 231 Passes.add(new PrintFunctionPass("Code after xformations: \n", &std::cerr)); 232 233 // Strip all of the symbols from the bytecode so that it will be smaller... 234 if (!DisableStrip) 235 Passes.add(createSymbolStrippingPass()); 236 237 // Figure out where we are going to send the output... 238 std::ostream *Out = 0; 239 if (OutputFilename != "") 240 { // Specified an output filename? 241 if (!Force && std::ifstream(OutputFilename.c_str())) { 242 // If force is not specified, make sure not to overwrite a file! 243 std::cerr << argv[0] << ": error opening '" << OutputFilename 244 << "': file exists!\n" 245 << "Use -f command line argument to force output\n"; 246 return 1; 247 } 248 Out = new std::ofstream(OutputFilename.c_str()); 249 250 // Make sure that the Out file gets unlink'd from the disk if we get a 251 // SIGINT 252 RemoveFileOnSignal(OutputFilename); 253 } 254 else 255 { 256 if (InputFilename == "-") 257 { 258 OutputFilename = "-"; 259 Out = &std::cout; 260 } 261 else 262 { 263 std::string OutputFilename = GetFileNameRoot(InputFilename); 264 OutputFilename += ".s"; 265 266 if (!Force && std::ifstream(OutputFilename.c_str())) 267 { 268 // If force is not specified, make sure not to overwrite a file! 269 std::cerr << argv[0] << ": error opening '" << OutputFilename 270 << "': file exists!\n" 271 << "Use -f command line argument to force output\n"; 272 return 1; 273 } 274 275 Out = new std::ofstream(OutputFilename.c_str()); 276 if (!Out->good()) 277 { 278 std::cerr << argv[0] << ": error opening " << OutputFilename 279 << "!\n"; 280 delete Out; 281 return 1; 282 } 283 284 // Make sure that the Out file gets unlink'd from the disk if we get a 285 // SIGINT 286 RemoveFileOnSignal(OutputFilename); 287 } 288 } 289 290 // Ask the target to add backend passes as neccesary 291 if (Target.addPassesToEmitAssembly(Passes, *Out)) { 292 std::cerr << argv[0] << ": target '" << Target.getName() 293 << " does not support static compilation!\n"; 294 } else { 295 // Run our queue of passes all at once now, efficiently. 296 Passes.run(*M.get()); 297 } 298 299 // Delete the ostream if it's not a stdout stream 300 if (Out != &std::cout) delete Out; 301 302 return 0; 303} 304