f0ae129cea89583b3f417a892541880e03cccf64
[oota-llvm.git] / tools / llvmc / CompilerDriver.cpp
1 //===- CompilerDriver.cpp - The LLVM Compiler Driver ------------*- C++ -*-===//
2 //
3 // 
4 //                     The LLVM Compiler Infrastructure
5 //
6 // This file was developed by Reid Spencer and is distributed under the 
7 // University of Illinois Open Source License. See LICENSE.TXT for details.
8 // 
9 //===----------------------------------------------------------------------===//
10 //
11 // This file implements the bulk of the LLVM Compiler Driver (llvmc).
12 //
13 //===------------------------------------------------------------------------===
14
15 #include "CompilerDriver.h"
16 #include "ConfigLexer.h"
17 #include <iostream>
18
19 using namespace llvm;
20
21 namespace {
22   inline std::string RemoveSuffix(const std::string& fullName) {
23     size_t dotpos = fullName.rfind('.',fullName.size());
24     if ( dotpos == std::string::npos ) return fullName;
25     return fullName.substr(0, dotpos);
26   }
27
28   inline std::string GetSuffix(const std::string& fullName) {
29     size_t dotpos = fullName.rfind('.',fullName.size());
30     if ( dotpos = std::string::npos ) return "";
31     return fullName.substr(dotpos+1);
32   }
33
34   const char OutputSuffix[] = ".o";
35
36   void WriteAction(CompilerDriver::Action* a ) {
37     std::cerr << a->program;
38     std::vector<std::string>::iterator I = a->args.begin();
39     while (I != a->args.end()) {
40       std::cerr << " " + *I;
41       ++I;
42     }
43     std::cerr << "\n";
44   }
45
46   void DumpAction(CompilerDriver::Action* a) {
47     std::cerr << "command = " << a->program;
48     std::vector<std::string>::iterator I = a->args.begin();
49     while (I != a->args.end()) {
50       std::cerr << " " + *I;
51       ++I;
52     }
53     std::cerr << "\n";
54     std::cerr << "flags = " << a->flags << "\n";
55     std::cerr << "inputAt = " << a->inputAt << "\n";
56     std::cerr << "outputAt = " << a->outputAt << "\n";
57   }
58
59   void DumpConfigData(CompilerDriver::ConfigData* cd, const std::string& type ){
60     std::cerr << "Configuration Data For '" << cd->langName << "' (" << type 
61       << ")\n";
62     std::cerr << "PreProcessor: ";
63     DumpAction(&cd->PreProcessor);
64     std::cerr << "Translator: ";
65     DumpAction(&cd->Translator);
66     std::cerr << "Optimizer: ";
67     DumpAction(&cd->Optimizer);
68     std::cerr << "Assembler: ";
69     DumpAction(&cd->Assembler);
70     std::cerr << "Linker: ";
71     DumpAction(&cd->Linker);
72   }
73
74   void CleanupTempFile(const char* fname) {
75     if (0 == access(fname, F_OK | R_OK))
76       unlink(fname);
77   }
78
79   /// This specifies the passes to run for OPT_FAST_COMPILE (-O1)
80   /// which should reduce the volume of code and make compilation
81   /// faster. This is also safe on any llvm module. 
82   static const char* DefaultOptimizations[] = {
83     "-simplifycfg", "-mem2reg", "-mergereturn", "-instcombine",
84   };
85 }
86
87 CompilerDriver::CompilerDriver(ConfigDataProvider& confDatProv )
88   : cdp(&confDatProv)
89   , finalPhase(LINKING)
90   , optLevel(OPT_FAST_COMPILE) 
91   , isDryRun(false)
92   , isVerbose(false)
93   , isDebug(false)
94   , timeActions(false)
95   , emitRawCode(false)
96   , emitNativeCode(false)
97   , machine()
98   , LibraryPaths()
99   , PreprocessorOptions()
100   , TranslatorOptions()
101   , OptimizerOptions()
102   , AssemblerOptions()
103   , LinkerOptions()
104 {
105   // FIXME: These libraries are platform specific
106   LibraryPaths.push_back("/lib");
107   LibraryPaths.push_back("/usr/lib");
108 }
109
110 CompilerDriver::~CompilerDriver() {
111   cdp = 0;
112   LibraryPaths.clear();
113   PreprocessorOptions.clear();
114   TranslatorOptions.clear();
115   OptimizerOptions.clear();
116   AssemblerOptions.clear();
117   LinkerOptions.clear();
118 }
119
120 void CompilerDriver::error( const std::string& errmsg ) {
121   std::cerr << "Error: " << errmsg << ".\n";
122   exit(1);
123 }
124
125 inline std::string makeDashO(CompilerDriver::OptimizationLevels lev) {
126   if (lev == CompilerDriver::OPT_NONE) return "";
127   std::string result("-O");
128   switch (lev) {
129     case CompilerDriver::OPT_FAST_COMPILE :     result.append("1"); break;
130     case CompilerDriver::OPT_SIMPLE:            result.append("2"); break;
131     case CompilerDriver::OPT_AGGRESSIVE:        result.append("3"); break;
132     case CompilerDriver::OPT_LINK_TIME:         result.append("4"); break;
133     case CompilerDriver::OPT_AGGRESSIVE_LINK_TIME: result.append("5"); break;
134     default:                    assert(!"Invalid optimization level!");
135   }
136   return result;
137 }
138
139 CompilerDriver::Action* CompilerDriver::GetAction(ConfigData* cd, 
140                           const std::string& input, 
141                           const std::string& output,
142                           Phases phase)
143 {
144   Action* pat = 0;
145   // Get the action pattern
146   switch (phase) {
147     case PREPROCESSING: pat = &cd->PreProcessor; break;
148     case TRANSLATION:   pat = &cd->Translator; break;
149     case OPTIMIZATION:  pat = &cd->Optimizer; break;
150     case ASSEMBLY:      pat = &cd->Assembler; break;
151     case LINKING:       pat = &cd->Linker; break;
152     default:
153       assert(!"Invalid driver phase!");
154       break;
155   }
156   assert(pat != 0 && "Invalid command pattern");
157
158   // Create the resulting action
159   Action* a = new Action(*pat);
160
161   // Replace the substitution arguments
162   if (pat->inputAt < a->args.size())
163     a->args[pat->inputAt] = input;
164   if (pat->outputAt < a->args.size())
165     a->args[pat->outputAt] = output;
166
167   // Insert specific options for each kind of action type
168   switch (phase) {
169     case PREPROCESSING:
170       a->args.insert(a->args.begin(), PreprocessorOptions.begin(), 
171                     PreprocessorOptions.end());
172       break;
173     case TRANSLATION:   
174       a->args.insert(a->args.begin(), TranslatorOptions.begin(), 
175                     TranslatorOptions.end());
176       if (a->isSet(GROKS_DASH_O_FLAG))
177         a->args.insert(a->args.begin(), makeDashO(optLevel));
178       else if (a->isSet(GROKS_O10N_FLAG))
179         a->args.insert(a->args.begin(), cd->opts[optLevel].begin(),
180             cd->opts[optLevel].end());
181       break;
182     case OPTIMIZATION:  
183       a->args.insert(a->args.begin(), OptimizerOptions.begin(), 
184                     OptimizerOptions.end());
185       if (a->isSet(GROKS_DASH_O_FLAG))
186         a->args.insert(a->args.begin(), makeDashO(optLevel));
187       else if (a->isSet(GROKS_O10N_FLAG))
188         a->args.insert(a->args.begin(), cd->opts[optLevel].begin(),
189             cd->opts[optLevel].end());
190       break;
191     case ASSEMBLY:      
192       a->args.insert(a->args.begin(), AssemblerOptions.begin(), 
193                     AssemblerOptions.end());
194       break;
195     case LINKING:       
196       a->args.insert(a->args.begin(), LinkerOptions.begin(), 
197                     LinkerOptions.end());
198       if (a->isSet(GROKS_DASH_O_FLAG))
199         a->args.insert(a->args.begin(), makeDashO(optLevel));
200       else if (a->isSet(GROKS_O10N_FLAG))
201         a->args.insert(a->args.begin(), cd->opts[optLevel].begin(),
202             cd->opts[optLevel].end());
203       break;
204     default:
205       assert(!"Invalid driver phase!");
206       break;
207   }
208   return a;
209 }
210
211 void CompilerDriver::DoAction(Action*a)
212 {
213   if (isVerbose)
214     WriteAction(a);
215   if (!isDryRun) {
216     std::cerr << "execve(\"" << a->program << "\",[\"";
217     std::vector<std::string>::iterator I = a->args.begin();
218     while (I != a->args.end()) {
219       std::cerr << *I;
220       ++I;
221       if (I != a->args.end())
222         std::cerr << "\",\"";
223     }
224     std::cerr << "\"],ENV);\n";
225   }
226 }
227
228 int CompilerDriver::execute(const InputList& InpList, 
229                             const std::string& Output ) {
230   // Echo the configuration of options if we're running verbose
231   if (isDebug)
232   {
233     std::cerr << "Compiler Driver Options:\n";
234     std::cerr << "DryRun = " << isDryRun << "\n";
235     std::cerr << "Verbose = " << isVerbose << " \n";
236     std::cerr << "TimeActions = " << timeActions << "\n";
237     std::cerr << "EmitRawCode = " << emitRawCode << "\n";
238     std::cerr << "OutputMachine = " << machine << "\n";
239     std::cerr << "EmitNativeCode = " << emitNativeCode << "\n";
240     InputList::const_iterator I = InpList.begin();
241     while ( I != InpList.end() ) {
242       std::cerr << "Input: " << I->first << "(" << I->second << ")\n";
243       ++I;
244     }
245     std::cerr << "Output: " << Output << "\n";
246   }
247
248   // If there's no input, we're done.
249   if (InpList.empty())
250     error("Nothing to compile.");
251
252   // If they are asking for linking and didn't provide an output
253   // file then its an error (no way for us to "make up" a meaningful
254   // file name based on the various linker input files).
255   if (finalPhase == LINKING && Output.empty())
256     error("An output file name must be specified for linker output");
257
258   // This vector holds all the resulting actions of the following loop.
259   std::vector<Action*> actions;
260
261   // Create a temporary directory for our temporary files
262   char temp_name[64];
263   strcpy(temp_name,"/tmp/llvm_XXXXXX");
264   if (0 == mkdtemp(temp_name))
265       error("Can't create temporary directory");
266   std::string TempDir(temp_name);
267   std::string TempPreprocessorOut(TempDir + "/preproc.tmp");
268   std::string TempTranslatorOut(TempDir + "/trans.tmp");
269   std::string TempOptimizerOut(TempDir + "/opt.tmp");
270   std::string TempAssemblerOut(TempDir + "/asm.tmp");
271
272   /// PRE-PROCESSING / TRANSLATION / OPTIMIZATION / ASSEMBLY phases
273   // for each input item
274   std::vector<std::string> LinkageItems;
275   InputList::const_iterator I = InpList.begin();
276   while ( I != InpList.end() ) {
277     // Get the suffix of the file name
278     std::string suffix = GetSuffix(I->first);
279
280     // If its a library, bytecode file, or object file, save 
281     // it for linking below and short circuit the 
282     // pre-processing/translation/assembly phases
283     if (I->second.empty() || suffix == "o" || suffix == "bc") {
284       // We shouldn't get any of these types of files unless we're 
285       // later going to link. Enforce this limit now.
286       if (finalPhase != LINKING) {
287         error("Pre-compiled objects found but linking not requested");
288       }
289       LinkageItems.push_back(I->first);
290       continue; // short circuit remainder of loop
291     }
292
293     // At this point, we know its something we need to translate
294     // and/or optimize. See if we can get the configuration data
295     // for this kind of file.
296     ConfigData* cd = cdp->ProvideConfigData(I->second);
297     if (cd == 0)
298       error(std::string("Files of type '") + I->second + 
299             "' are not recognized." ); 
300     if (isDebug)
301       DumpConfigData(cd,I->second);
302
303     // We have valid configuration data, now figure out where the output
304     // of compilation should end up.
305     std::string OutFile;
306     if (finalPhase != LINKING) {
307       if (InpList.size() == 1 && !Output.empty()) 
308         OutFile = Output;
309       else
310         OutFile = RemoveSuffix(I->first) + OutputSuffix;
311     } else {
312       OutFile = Output;
313     }
314
315     // PRE-PROCESSING PHASE
316     Action& a = cd->PreProcessor;
317
318     // Get the preprocessing action, if needed, or error if appropriate
319     if (!a.program.empty()) {
320       if (a.isSet(REQUIRED_FLAG) || finalPhase == PREPROCESSING) {
321         actions.push_back(GetAction(cd,I->first,
322               TempPreprocessorOut,PREPROCESSING));
323       }
324     } else if (finalPhase == PREPROCESSING) {
325       error(cd->langName + " does not support pre-processing");
326     } else if (a.isSet(REQUIRED_FLAG)) {
327       error(std::string("Don't know how to pre-process ") + 
328             cd->langName + " files");
329     }
330     // Short-circuit remaining actions if all they want is pre-processing
331     if (finalPhase == PREPROCESSING) { ++I; continue; };
332
333     /// TRANSLATION PHASE
334     a = cd->Translator;
335
336     // Get the translation action, if needed, or error if appropriate
337     if (!a.program.empty()) {
338       if (a.isSet(REQUIRED_FLAG) || finalPhase == TRANSLATION) {
339         actions.push_back(GetAction(cd,I->first,TempTranslatorOut,TRANSLATION));
340       }
341     } else if (finalPhase == TRANSLATION) {
342       error(cd->langName + " does not support translation");
343     } else if (a.isSet(REQUIRED_FLAG)) {
344       error(std::string("Don't know how to translate ") + 
345             cd->langName + " files");
346     }
347     // Short-circuit remaining actions if all they want is translation
348     if (finalPhase == TRANSLATION) { ++I; continue; }
349
350     /// OPTIMIZATION PHASE
351     a = cd->Optimizer;
352
353     // Get the optimization action, if needed, or error if appropriate
354     if (!a.program.empty()) {
355       actions.push_back(GetAction(cd,I->first,TempOptimizerOut,OPTIMIZATION));
356     } else if (finalPhase == OPTIMIZATION) {
357       error(cd->langName + " does not support optimization");
358     } else if (a.isSet(REQUIRED_FLAG)) {
359       error(std::string("Don't know how to optimize ") + 
360             cd->langName + " files");
361     }
362     // Short-circuit remaining actions if all they want is optimization
363     if (finalPhase == OPTIMIZATION) { ++I; continue; }
364
365     ++I;
366   }
367
368   /// LINKING PHASE
369
370   /// RUN THE ACTIONS
371   std::vector<Action*>::iterator aIter = actions.begin();
372   while (aIter != actions.end()) {
373     DoAction(*aIter);
374     aIter++;
375   }
376
377   // Cleanup files
378   CleanupTempFile(TempPreprocessorOut.c_str());
379   CleanupTempFile(TempTranslatorOut.c_str());
380   CleanupTempFile(TempOptimizerOut.c_str());
381
382   // Cleanup temporary directory we created
383   if (0 == access(TempDir.c_str(), F_OK | W_OK))
384     rmdir(TempDir.c_str());
385
386   return 0;
387 }
388
389 // vim: sw=2 smartindent smarttab tw=80 autoindent expandtab