*** empty log message ***
[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/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/Function.h"
18 #include "llvm/PassManager.h"
19 #include "Support/CommandLine.h"
20 #include "Support/Signals.h"
21 #include <memory>
22 #include <fstream>
23 using std::string;
24 using std::cerr;
25
26 static cl::opt<string>
27 InputFilename(cl::Positional, cl::desc("<input bytecode>"), cl::init("-"));
28
29 static cl::opt<string>
30 OutputFilename("o", cl::desc("Output filename"), cl::value_desc("filename"));
31
32 static cl::opt<bool> Force("f", cl::desc("Overwrite output files"));
33
34 static cl::opt<bool>
35 DumpAsm("d", cl::desc("Print bytecode before native code generation"),
36         cl::Hidden);
37
38 static cl::opt<string>
39 TraceLibPath("tracelibpath", cl::desc("Path to libinstr for trace code"),
40              cl::value_desc("directory"), cl::Hidden);
41
42 enum TraceLevel {
43   TraceOff, TraceFunctions, TraceBasicBlocks
44 };
45
46 static cl::opt<TraceLevel>
47 TraceValues("trace", cl::desc("Trace values through functions or basic blocks"),
48             cl::values(
49   clEnumValN(TraceOff        , "off",        "Disable trace code"),
50   clEnumValN(TraceFunctions  , "function",   "Trace each function"),
51   clEnumValN(TraceBasicBlocks, "basicblock", "Trace each basic block"),
52                        0));
53
54 // GetFileNameRoot - Helper function to get the basename of a filename...
55 static inline string GetFileNameRoot(const string &InputFilename) {
56   string IFN = InputFilename;
57   string outputFilename;
58   int Len = IFN.length();
59   if (IFN[Len-3] == '.' && IFN[Len-2] == 'b' && IFN[Len-1] == 'c') {
60     outputFilename = string(IFN.begin(), IFN.end()-3); // s/.bc/.s/
61   } else {
62     outputFilename = IFN;
63   }
64   return outputFilename;
65 }
66
67 static void insertTraceCodeFor(Module &M) {
68   PassManager Passes;
69
70   // Insert trace code in all functions in the module
71   switch (TraceValues) {
72   case TraceBasicBlocks:
73     Passes.add(createTraceValuesPassForBasicBlocks());
74     break;
75   case TraceFunctions:
76     Passes.add(createTraceValuesPassForFunction());
77     break;
78   default:
79     assert(0 && "Bad value for TraceValues!");
80     abort();
81   }
82   
83   // Eliminate duplication in constant pool
84   Passes.add(createConstantMergePass());
85
86   // Run passes to insert and clean up trace code...
87   Passes.run(M);
88
89   std::string ErrorMessage;
90
91   // Load the module that contains the runtime helper routines neccesary for
92   // pointer hashing and stuff...  link this module into the program if possible
93   //
94   Module *TraceModule = ParseBytecodeFile(TraceLibPath+"libinstr.bc");
95
96   // Ok, the TraceLibPath didn't contain a valid module.  Try to load the module
97   // from the current LLVM-GCC install directory.  This is kindof a hack, but
98   // allows people to not HAVE to have built the library.
99   //
100   if (TraceModule == 0)
101     TraceModule = ParseBytecodeFile("/home/vadve/lattner/cvs/gcc_install/lib/"
102                                     "gcc-lib/llvm/3.1/libinstr.bc");
103
104   // If we still didn't get it, cancel trying to link it in...
105   if (TraceModule == 0) {
106     cerr << "Warning, could not load trace routines to link into program!\n";
107   } else {
108
109     // Link in the trace routines... if the link fails, don't panic, because the
110     // compile should still succeed, just the native linker will probably fail.
111     //
112     std::auto_ptr<Module> TraceRoutines(TraceModule);
113     if (LinkModules(&M, TraceRoutines.get(), &ErrorMessage))
114       cerr << "Warning: Error linking in trace routines: "
115            << ErrorMessage << "\n";
116   }
117
118
119   // Write out the module with tracing code just before code generation
120   if (InputFilename != "-") {
121     string TraceFilename = GetFileNameRoot(InputFilename) + ".trace.bc";
122
123     std::ofstream Out(TraceFilename.c_str());
124     if (!Out.good()) {
125       cerr << "Error opening '" << TraceFilename
126            << "'!: Skipping output of trace code as bytecode\n";
127     } else {
128       cerr << "Emitting trace code to '" << TraceFilename
129            << "' for comparison...\n";
130       WriteBytecodeToFile(&M, Out);
131     }
132   }
133
134 }
135   
136
137 //===---------------------------------------------------------------------===//
138 // Function main()
139 // 
140 // Entry point for the llc compiler.
141 //===---------------------------------------------------------------------===//
142
143 int main(int argc, char **argv) {
144   cl::ParseCommandLineOptions(argc, argv, " llvm system compiler\n");
145   
146   // Allocate a target... in the future this will be controllable on the
147   // command line.
148   std::auto_ptr<TargetMachine> target(allocateSparcTargetMachine());
149   assert(target.get() && "Could not allocate target machine!");
150
151   TargetMachine &Target = *target.get();
152   
153   // Load the module to be compiled...
154   std::auto_ptr<Module> M(ParseBytecodeFile(InputFilename));
155   if (M.get() == 0) {
156     cerr << "bytecode didn't read correctly.\n";
157     return 1;
158   }
159
160   if (TraceValues != TraceOff)    // If tracing enabled...
161     insertTraceCodeFor(*M.get()); // Hack up module before using passmanager...
162
163   // Build up all of the passes that we want to do to the module...
164   PassManager Passes;
165
166   // Decompose multi-dimensional refs into a sequence of 1D refs
167   Passes.add(createDecomposeMultiDimRefsPass());
168   
169   // Replace malloc and free instructions with library calls.
170   // Do this after tracing until lli implements these lib calls.
171   // For now, it will emulate malloc and free internally.
172   Passes.add(createLowerAllocationsPass(Target.DataLayout));
173   
174   // If LLVM dumping after transformations is requested, add it to the pipeline
175   if (DumpAsm)
176     Passes.add(new PrintFunctionPass("Code after xformations: \n", &cerr));
177
178   // Strip all of the symbols from the bytecode so that it will be smaller...
179   Passes.add(createSymbolStrippingPass());
180
181   // Figure out where we are going to send the output...
182   std::ostream *Out = 0;
183   if (OutputFilename != "") {   // Specified an output filename?
184     if (!Force && std::ifstream(OutputFilename.c_str())) {
185       // If force is not specified, make sure not to overwrite a file!
186       cerr << "Error opening '" << OutputFilename << "': File exists!\n"
187            << "Use -f command line argument to force output\n";
188       return 1;
189     }
190     Out = new std::ofstream(OutputFilename.c_str());
191
192     // Make sure that the Out file gets unlink'd from the disk if we get a
193     // SIGINT
194     RemoveFileOnSignal(OutputFilename);
195   } else {
196     if (InputFilename == "-") {
197       OutputFilename = "-";
198       Out = &std::cout;
199     } else {
200       string OutputFilename = GetFileNameRoot(InputFilename); 
201       OutputFilename += ".s";
202
203       if (!Force && std::ifstream(OutputFilename.c_str())) {
204         // If force is not specified, make sure not to overwrite a file!
205         cerr << "Error opening '" << OutputFilename << "': File exists!\n"
206              << "Use -f command line argument to force output\n";
207         return 1;
208       }
209
210       Out = new std::ofstream(OutputFilename.c_str());
211       if (!Out->good()) {
212         cerr << "Error opening " << OutputFilename << "!\n";
213         delete Out;
214         return 1;
215       }
216       // Make sure that the Out file gets unlink'd from the disk if we get a
217       // SIGINT
218       RemoveFileOnSignal(OutputFilename);
219     }
220   }
221   
222   Target.addPassesToEmitAssembly(Passes, *Out);
223   
224   // Run our queue of passes all at once now, efficiently.
225   Passes.run(*M.get());
226
227   if (Out != &std::cout) delete Out;
228
229   return 0;
230 }