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