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