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