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