f124219a0daf504119f0f0a81fadc9f76305ec62
[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 "Support/SystemUtils.h"
18 #include <iostream>
19
20 using namespace llvm;
21
22 namespace {
23   inline std::string RemoveSuffix(const std::string& fullName) {
24     size_t dotpos = fullName.rfind('.',fullName.size());
25     if ( dotpos == std::string::npos ) return fullName;
26     return fullName.substr(0, dotpos);
27   }
28
29   inline std::string GetSuffix(const std::string& fullName) {
30     size_t dotpos = fullName.rfind('.',fullName.size());
31     if ( dotpos = std::string::npos ) return "";
32     return fullName.substr(dotpos+1);
33   }
34
35   const char OutputSuffix[] = ".o";
36
37   void WriteAction(CompilerDriver::Action* action ) {
38     std::cerr << action->program;
39     std::vector<std::string>::iterator I = action->args.begin();
40     while (I != action->args.end()) {
41       std::cerr << " " + *I;
42       ++I;
43     }
44     std::cerr << "\n";
45   }
46
47   void DumpAction(CompilerDriver::Action* action) {
48     std::cerr << "command = " << action->program;
49     std::vector<std::string>::iterator I = action->args.begin();
50     while (I != action->args.end()) {
51       std::cerr << " " + *I;
52       ++I;
53     }
54     std::cerr << "\n";
55     std::cerr << "flags = " << action->flags << "\n";
56   }
57
58   void DumpConfigData(CompilerDriver::ConfigData* cd, const std::string& type ){
59     std::cerr << "Configuration Data For '" << cd->langName << "' (" << type 
60       << ")\n";
61     std::cerr << "PreProcessor: ";
62     DumpAction(&cd->PreProcessor);
63     std::cerr << "Translator: ";
64     DumpAction(&cd->Translator);
65     std::cerr << "Optimizer: ";
66     DumpAction(&cd->Optimizer);
67     std::cerr << "Assembler: ";
68     DumpAction(&cd->Assembler);
69     std::cerr << "Linker: ";
70     DumpAction(&cd->Linker);
71   }
72
73   void CleanupTempFile(const char* fname) {
74     if (0 == access(fname, F_OK | R_OK))
75       unlink(fname);
76   }
77
78   /// This specifies the passes to run for OPT_FAST_COMPILE (-O1)
79   /// which should reduce the volume of code and make compilation
80   /// faster. This is also safe on any llvm module. 
81   static const char* DefaultFastCompileOptimizations[] = {
82     "-simplifycfg", "-mem2reg", "-instcombine"
83   };
84 }
85
86 // Stuff in this namespace properly belongs in lib/System and needs
87 // to be portable but we're avoiding that for now.
88 namespace sys {
89   std::string MakeTemporaryDirectory() {
90     char temp_name[64];
91     strcpy(temp_name,"/tmp/llvm_XXXXXX");
92     if (0 == mkdtemp(temp_name))
93       throw std::string("Can't create temporary directory");
94     return temp_name;
95   }
96
97   std::string FindExecutableInPath(const std::string& program) {
98     // First, just see if the program is already executable
99     if (isExecutableFile(program)) return program;
100
101     // Get the path. If its empty, we can't do anything
102     const char *PathStr = getenv("PATH");
103     if (PathStr == 0) return "";
104
105     // Now we have a colon separated list of directories to search; try them.
106     unsigned PathLen = strlen(PathStr);
107     while (PathLen) {
108       // Find the first colon...
109       const char *Colon = std::find(PathStr, PathStr+PathLen, ':');
110     
111       // Check to see if this first directory contains the executable...
112       std::string FilePath = std::string(PathStr, Colon) + '/' + program;
113       if (isExecutableFile(FilePath))
114         return FilePath;                    // Found the executable!
115    
116       // Nope it wasn't in this directory, check the next range!
117       PathLen -= Colon-PathStr;
118       PathStr = Colon;
119
120       // Advance past duplicate coons
121       while (*PathStr == ':') {
122         PathStr++;
123         PathLen--;
124       }
125     }
126
127     // If we fell out, we ran out of directories in PATH to search, return failure
128     return "";
129   }
130 }
131
132 CompilerDriver::CompilerDriver(ConfigDataProvider& confDatProv )
133   : cdp(&confDatProv)
134   , finalPhase(LINKING)
135   , optLevel(OPT_FAST_COMPILE) 
136   , isDryRun(false)
137   , isVerbose(false)
138   , isDebug(false)
139   , timeActions(false)
140   , emitRawCode(false)
141   , emitNativeCode(false)
142   , keepTemps(false)
143   , machine()
144   , LibraryPaths()
145   , AdditionalArgs()
146   , TempDir()
147 {
148   // FIXME: These libraries are platform specific
149   LibraryPaths.push_back("/lib");
150   LibraryPaths.push_back("/usr/lib");
151   AdditionalArgs.reserve(NUM_PHASES);
152   StringVector emptyVec;
153   for (unsigned i = 0; i < NUM_PHASES; ++i)
154     AdditionalArgs.push_back(emptyVec);
155 }
156
157 CompilerDriver::~CompilerDriver() {
158   cdp = 0;
159   LibraryPaths.clear();
160   AdditionalArgs.clear();
161 }
162
163 CompilerDriver::ConfigData::ConfigData()
164   : langName()
165   , PreProcessor()
166   , Translator()
167   , Optimizer()
168   , Assembler()
169   , Linker()
170 {
171   StringVector emptyVec;
172   for (unsigned i = 0; i < NUM_PHASES; ++i)
173     opts.push_back(emptyVec);
174 }
175
176 void CompilerDriver::error( const std::string& errmsg ) {
177   std::cerr << "llvmc: Error: " << errmsg << ".\n";
178   exit(1);
179 }
180
181 CompilerDriver::Action* CompilerDriver::GetAction(ConfigData* cd, 
182                           const std::string& input, 
183                           const std::string& output,
184                           Phases phase)
185 {
186   Action* pat = 0; ///< The pattern/template for the action
187   Action* action = new Action; ///< The actual action to execute
188
189   // Get the action pattern
190   switch (phase) {
191     case PREPROCESSING: pat = &cd->PreProcessor; break;
192     case TRANSLATION:   pat = &cd->Translator; break;
193     case OPTIMIZATION:  pat = &cd->Optimizer; break;
194     case ASSEMBLY:      pat = &cd->Assembler; break;
195     case LINKING:       pat = &cd->Linker; break;
196     default:
197       assert(!"Invalid driver phase!");
198       break;
199   }
200   assert(pat != 0 && "Invalid command pattern");
201
202   // Copy over some pattern things that don't need to change
203   action->program = pat->program;
204   action->flags = pat->flags;
205
206   // Do the substitutions from the pattern to the actual
207   StringVector::iterator PI = pat->args.begin();
208   StringVector::iterator PE = pat->args.end();
209   while (PI != PE) {
210     if ((*PI)[0] == '@') {
211       if (*PI == "@in@") {
212         action->args.push_back(input);
213       } else if (*PI == "@out@") {
214         action->args.push_back(output);
215       } else if (*PI == "@time@") {
216         if (timePasses)
217           action->args.push_back("-time-passes");
218       } else if (*PI == "@stats@") {
219         if (showStats)
220           action->args.push_back("-stats");
221       } else if (*PI == "@target@") {
222         // FIXME: Ignore for now
223       } else if (*PI == "@opt@") {
224         if (!emitRawCode) {
225           if (pat->isSet(GROKS_DASH_O)) {
226             if (optLevel != OPT_NONE) {
227               std::string optArg("-O");
228               switch (optLevel) {
229                 case OPT_FAST_COMPILE : optArg.append("1"); break;
230                 case OPT_SIMPLE:        optArg.append("2"); break;
231                 case OPT_AGGRESSIVE:    optArg.append("3"); break;
232                 case OPT_LINK_TIME:     optArg.append("4"); break;
233                 case OPT_AGGRESSIVE_LINK_TIME: optArg.append("5"); break;
234                 default : 
235                   assert(!"Invalid optimization argument!");
236                   optArg.append("0"); 
237                   break;
238               }
239               action->args.push_back(optArg);
240             }
241           } else {
242             if (cd->opts.size() > static_cast<unsigned>(optLevel) && 
243                 !cd->opts[optLevel].empty())
244               action->args.insert(action->args.end(), cd->opts[optLevel].begin(),
245                 cd->opts[optLevel].end());
246           }
247         }
248       } else {
249         error("Invalid substitution name");
250       }
251     } else {
252       // Its not a substitution, just put it in the action
253       action->args.push_back(*PI);
254     }
255     PI++;
256   }
257
258   // Get specific options for each kind of action type
259   StringVector& args = AdditionalArgs[phase];
260
261   // Add specific options for each kind of action type
262   action->args.insert(action->args.end(), args.begin(), args.end());
263
264   // Finally, we're done
265   return action;
266 }
267
268 bool CompilerDriver::DoAction(Action*action) {
269   assert(action != 0 && "Invalid Action!");
270   if (isVerbose)
271     WriteAction(action);
272   if (!isDryRun) {
273     std::string prog(sys::FindExecutableInPath(action->program));
274     if (prog.empty())
275       error("Can't find program '" + action->program + "'");
276
277     // Get the program's arguments
278     const char* argv[action->args.size() + 1];
279     argv[0] = prog.c_str();
280     unsigned i = 1;
281     for (; i <= action->args.size(); ++i)
282       argv[i] = action->args[i-1].c_str();
283     argv[i] = 0;
284
285     // Invoke the program
286     return !ExecWait(argv, environ);
287   }
288   return true;
289 }
290
291 int CompilerDriver::execute(const InputList& InpList, 
292                             const std::string& Output ) {
293   // Echo the configuration of options if we're running verbose
294   if (isDebug)
295   {
296     std::cerr << "Compiler Driver Options:\n";
297     std::cerr << "DryRun = " << isDryRun << "\n";
298     std::cerr << "Verbose = " << isVerbose << " \n";
299     std::cerr << "TimeActions = " << timeActions << "\n";
300     std::cerr << "EmitRawCode = " << emitRawCode << "\n";
301     std::cerr << "OutputMachine = " << machine << "\n";
302     std::cerr << "EmitNativeCode = " << emitNativeCode << "\n";
303     InputList::const_iterator I = InpList.begin();
304     while ( I != InpList.end() ) {
305       std::cerr << "Input: " << I->first << "(" << I->second << ")\n";
306       ++I;
307     }
308     std::cerr << "Output: " << Output << "\n";
309   }
310
311   // If there's no input, we're done.
312   if (InpList.empty())
313     error("Nothing to compile.");
314
315   // If they are asking for linking and didn't provide an output
316   // file then its an error (no way for us to "make up" a meaningful
317   // file name based on the various linker input files).
318   if (finalPhase == LINKING && Output.empty())
319     error("An output file name must be specified for linker output");
320
321   // This vector holds all the resulting actions of the following loop.
322   std::vector<Action*> actions;
323
324   // Create a temporary directory for our temporary files
325   std::string TempDir(sys::MakeTemporaryDirectory());
326   std::string TempPreprocessorOut(TempDir + "/preproc.o");
327   std::string TempTranslatorOut(TempDir + "/trans.o");
328   std::string TempOptimizerOut(TempDir + "/opt.o");
329   std::string TempAssemblerOut(TempDir + "/asm.o");
330
331   /// PRE-PROCESSING / TRANSLATION / OPTIMIZATION / ASSEMBLY phases
332   // for each input item
333   std::vector<std::string> LinkageItems;
334   InputList::const_iterator I = InpList.begin();
335   while ( I != InpList.end() ) {
336     // Get the suffix of the file name
337     std::string suffix = GetSuffix(I->first);
338
339     // If its a library, bytecode file, or object file, save 
340     // it for linking below and short circuit the 
341     // pre-processing/translation/assembly phases
342     if (I->second.empty() || suffix == "o" || suffix == "bc") {
343       // We shouldn't get any of these types of files unless we're 
344       // later going to link. Enforce this limit now.
345       if (finalPhase != LINKING) {
346         error("Pre-compiled objects found but linking not requested");
347       }
348       LinkageItems.push_back(I->first);
349       continue; // short circuit remainder of loop
350     }
351
352     // At this point, we know its something we need to translate
353     // and/or optimize. See if we can get the configuration data
354     // for this kind of file.
355     ConfigData* cd = cdp->ProvideConfigData(I->second);
356     if (cd == 0)
357       error(std::string("Files of type '") + I->second + 
358             "' are not recognized." ); 
359     if (isDebug)
360       DumpConfigData(cd,I->second);
361
362     // We have valid configuration data, now figure out where the output
363     // of compilation should end up.
364     std::string OutFile;
365     if (finalPhase != LINKING) {
366       if (InpList.size() == 1 && !Output.empty()) 
367         OutFile = Output;
368       else
369         OutFile = RemoveSuffix(I->first) + OutputSuffix;
370     } else {
371       OutFile = Output;
372     }
373
374     // Initialize the input file
375     std::string InFile(I->first);
376
377     // PRE-PROCESSING PHASE
378     Action& action = cd->PreProcessor;
379
380     // Get the preprocessing action, if needed, or error if appropriate
381     if (!action.program.empty()) {
382       if (action.isSet(REQUIRED_FLAG) || finalPhase == PREPROCESSING) {
383         if (finalPhase == PREPROCESSING)
384           actions.push_back(GetAction(cd,InFile,OutFile,PREPROCESSING));
385         else {
386           actions.push_back(GetAction(cd,InFile,TempPreprocessorOut,
387                             PREPROCESSING));
388           InFile = TempPreprocessorOut;
389         }
390       }
391     } else if (finalPhase == PREPROCESSING) {
392       error(cd->langName + " does not support pre-processing");
393     } else if (action.isSet(REQUIRED_FLAG)) {
394       error(std::string("Don't know how to pre-process ") + 
395             cd->langName + " files");
396     }
397
398     // Short-circuit remaining actions if all they want is pre-processing
399     if (finalPhase == PREPROCESSING) { ++I; continue; };
400
401     /// TRANSLATION PHASE
402     action = cd->Translator;
403
404     // Get the translation action, if needed, or error if appropriate
405     if (!action.program.empty()) {
406       if (action.isSet(REQUIRED_FLAG) || finalPhase == TRANSLATION) {
407         if (finalPhase == TRANSLATION) 
408           actions.push_back(GetAction(cd,InFile,OutFile,TRANSLATION));
409         else {
410           actions.push_back(GetAction(cd,InFile,TempTranslatorOut,TRANSLATION));
411           InFile = TempTranslatorOut;
412         }
413
414         // ll -> bc Helper
415         if (action.isSet(OUTPUT_IS_ASM_FLAG)) {
416           /// The output of the translator is an LLVM Assembly program
417           /// We need to translate it to bytecode
418           Action* action = new Action();
419           action->program = "llvm-as";
420           action->args.push_back(InFile);
421           action->args.push_back("-o");
422           InFile += ".bc";
423           action->args.push_back(InFile);
424           actions.push_back(action);
425         }
426       }
427     } else if (finalPhase == TRANSLATION) {
428       error(cd->langName + " does not support translation");
429     } else if (action.isSet(REQUIRED_FLAG)) {
430       error(std::string("Don't know how to translate ") + 
431             cd->langName + " files");
432     }
433
434     // Short-circuit remaining actions if all they want is translation
435     if (finalPhase == TRANSLATION) { ++I; continue; }
436
437     /// OPTIMIZATION PHASE
438     action = cd->Optimizer;
439
440     // Get the optimization action, if needed, or error if appropriate
441     if (!action.program.empty() && !emitRawCode) {
442       if (action.isSet(REQUIRED_FLAG) || finalPhase == OPTIMIZATION) {
443         if (finalPhase == OPTIMIZATION)
444           actions.push_back(GetAction(cd,InFile,OutFile,OPTIMIZATION));
445         else {
446           actions.push_back(GetAction(cd,InFile,TempOptimizerOut,OPTIMIZATION));
447           InFile = TempOptimizerOut;
448         }
449         // ll -> bc Helper
450         if (action.isSet(OUTPUT_IS_ASM_FLAG)) {
451           /// The output of the translator is an LLVM Assembly program
452           /// We need to translate it to bytecode
453           Action* action = new Action();
454           action->program = "llvm-as";
455           action->args.push_back(InFile);
456           action->args.push_back("-o");
457           InFile += ".bc";
458           action->args.push_back(InFile);
459           actions.push_back(action);
460         }
461       }
462     } else if (finalPhase == OPTIMIZATION) {
463       error(cd->langName + " does not support optimization");
464     } else if (action.isSet(REQUIRED_FLAG)) {
465       error(std::string("Don't know how to optimize ") + 
466             cd->langName + " files");
467     }
468
469     // Short-circuit remaining actions if all they want is optimization
470     if (finalPhase == OPTIMIZATION) { ++I; continue; }
471
472     /// ASSEMBLY PHASE
473     if (emitNativeCode) {
474       // We must cause native code to be generated
475     } else {
476     }
477       
478     // Go to next file to be processed
479     ++I;
480   }
481
482   /// LINKING PHASE
483   if (emitNativeCode) {
484   } else {
485   }
486
487   /// RUN THE ACTIONS
488   std::vector<Action*>::iterator aIter = actions.begin();
489   while (aIter != actions.end()) {
490     if (!DoAction(*aIter))
491       error("Action failed");
492     aIter++;
493   }
494
495   if (!keepTemps) {
496     // Cleanup files
497     CleanupTempFile(TempPreprocessorOut.c_str());
498     CleanupTempFile(TempTranslatorOut.c_str());
499     CleanupTempFile(TempOptimizerOut.c_str());
500
501     // Cleanup temporary directory we created
502     if (0 == access(TempDir.c_str(), F_OK | W_OK))
503       rmdir(TempDir.c_str());
504   }
505
506   return 0;
507 }
508
509 // vim: sw=2 smartindent smarttab tw=80 autoindent expandtab