Ensure that the arguments passed to sys::Program::ExecuteAndWait include
[oota-llvm.git] / tools / llvmc / CompilerDriver.cpp
index b890220c9ca1eee1ae1a8452e5a956091423e7e7..1a316c84390bbb471b9f35ede6495096a50257f1 100644 (file)
@@ -21,6 +21,7 @@
 #include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/StringExtras.h"
 #include <iostream>
+#include "llvm/Config/alloca.h"
 
 using namespace llvm;
 
@@ -28,9 +29,9 @@ namespace {
 
 void WriteAction(CompilerDriver::Action* action ) {
   std::cerr << action->program.c_str();
-  std::vector<std::string>::iterator I = action->args.begin();
+  std::vector<std::string>::const_iterator I = action->args.begin();
   while (I != action->args.end()) {
-    std::cerr << " " + *I;
+    std::cerr << " " << *I;
     ++I;
   }
   std::cerr << "\n";
@@ -38,9 +39,9 @@ void WriteAction(CompilerDriver::Action* action ) {
 
 void DumpAction(CompilerDriver::Action* action) {
   std::cerr << "command = " << action->program.c_str();
-  std::vector<std::string>::iterator I = action->args.begin();
+  std::vector<std::string>::const_iterator I = action->args.begin();
   while (I != action->args.end()) {
-    std::cerr << " " + *I;
+    std::cerr << " " << *I;
     ++I;
   }
   std::cerr << "\n";
@@ -134,7 +135,7 @@ public:
     StringVector::const_iterator E = paths.end();
     while (I != E) {
       sys::Path tmp;
-      tmp.set_directory(*I);
+      tmp.setDirectory(*I);
       IncludePaths.push_back(tmp);
       ++I;
     }
@@ -149,7 +150,7 @@ public:
     StringVector::const_iterator E = paths.end();
     while (I != E) {
       sys::Path tmp;
-      tmp.set_directory(*I);
+      tmp.setDirectory(*I);
       LibraryPaths.push_back(tmp);
       ++I;
     }
@@ -159,6 +160,10 @@ public:
     LibraryPaths.push_back(libPath);
   }
 
+  virtual void addToolPath( const sys::Path& toolPath ) {
+    ToolPaths.push_back(toolPath);
+  }
+
   virtual void setfPassThrough(const StringVector& fOpts) {
     fOptions = fOpts;
   }
@@ -172,6 +177,7 @@ public:
   virtual void setWPassThrough(const StringVector& WOpts) {
     WOptions = WOpts;
   }
+
 /// @}
 /// @name Functions
 /// @{
@@ -182,19 +188,19 @@ private:
 
   void cleanup() {
     if (!isSet(KEEP_TEMPS_FLAG)) {
-      if (TempDir.is_directory() && TempDir.writable())
-        TempDir.destroy_directory(/*remove_contents=*/true);
+      if (TempDir.isDirectory() && TempDir.writable())
+        TempDir.destroyDirectory(/*remove_contents=*/true);
     } else {
-      std::cout << "Temporary files are in " << TempDir.get() << "\n";
+      std::cout << "Temporary files are in " << TempDir << "\n";
     }
   }
 
   sys::Path MakeTempFile(const std::string& basename, 
                          const std::string& suffix ) {
     sys::Path result(TempDir);
-    if (!result.append_file(basename))
+    if (!result.appendFile(basename))
       throw basename + ": can't use this file name";
-    if (!result.append_suffix(suffix))
+    if (!result.appendSuffix(suffix))
       throw suffix + ": can't use this file suffix";
     return result;
   }
@@ -257,19 +263,20 @@ private:
             break;
           case 'f':
             if (*PI == "%fOpts%") {
-              action->args.insert(action->args.end(), fOptions.begin(), 
-                                  fOptions.end());
+              if (!fOptions.empty())
+                action->args.insert(action->args.end(), fOptions.begin(), 
+                                    fOptions.end());
             } else
               found = false;
             break;
           case 'i':
             if (*PI == "%in%") {
-              action->args.push_back(input.get());
+              action->args.push_back(input.toString());
             } else if (*PI == "%incls%") {
               PathVector::iterator I = IncludePaths.begin();
               PathVector::iterator E = IncludePaths.end();
               while (I != E) {
-                action->args.push_back( std::string("-I") + I->get() );
+                action->args.push_back( std::string("-I") + I->toString() );
                 ++I;
               }
             } else
@@ -280,7 +287,7 @@ private:
               PathVector::iterator I = LibraryPaths.begin();
               PathVector::iterator E = LibraryPaths.end();
               while (I != E) {
-                action->args.push_back( std::string("-L") + I->get() );
+                action->args.push_back( std::string("-L") + I->toString() );
                 ++I;
               }
             } else
@@ -288,7 +295,7 @@ private:
             break;
           case 'o':
             if (*PI == "%out%") {
-              action->args.push_back(output.get());
+              action->args.push_back(output.toString());
             } else if (*PI == "%opt%") {
               if (!isSet(EMIT_RAW_FLAG)) {
                 if (cd->opts.size() > static_cast<unsigned>(optLevel) && 
@@ -327,16 +334,19 @@ private:
               found  = false;
             break;
           case 'M':
-            if (*PI == "%Mopts") {
-              action->args.insert(action->args.end(), MOptions.begin(), 
-                                  MOptions.end());
+            if (*PI == "%Mopts%") {
+              if (!MOptions.empty())
+                action->args.insert(action->args.end(), MOptions.begin(), 
+                                    MOptions.end());
             } else
               found = false;
             break;
           case 'W':
-            if (*PI == "%Wopts") {
-              action->args.insert(action->args.end(), WOptions.begin(), 
-                                  WOptions.end());
+            if (*PI == "%Wopts%") {
+              for (StringVector::iterator I = WOptions.begin(),
+                   E = WOptions.end(); I != E ; ++I ) {
+                action->args.push_back( std::string("-W") + *I );
+              }
             } else
               found = false;
             break;
@@ -349,13 +359,13 @@ private:
           if (PI->length()>1 && (*PI)[0] == '%' && 
               (*PI)[PI->length()-1] == '%') {
             throw std::string("Invalid substitution token: '") + *PI +
-                  "' for command '" + pat->program.get() + "'";
-          } else {
+                  "' for command '" + pat->program.toString() + "'";
+          } else if (!PI->empty()) {
             // It's not a legal substitution, just pass it through
             action->args.push_back(*PI);
           }
         }
-      } else {
+      } else if (!PI->empty()) {
         // Its not a substitution, just put it in the action
         action->args.push_back(*PI);
       }
@@ -372,58 +382,72 @@ private:
       WriteAction(action);
     if (!isSet(DRY_RUN_FLAG)) {
       sys::Path progpath = sys::Program::FindProgramByName(
-        action->program.get());
-      if (progpath.is_empty())
-        throw std::string("Can't find program '"+progpath.get()+"'");
+        action->program.toString());
+      if (progpath.isEmpty())
+        throw std::string("Can't find program '" +
+                          action->program.toString()+"'");
       else if (progpath.executable())
         action->program = progpath;
       else
-        throw std::string("Program '"+progpath.get()+"' is not executable.");
+        throw std::string("Program '"+action->program.toString()+
+                          "' is not executable.");
 
       // Invoke the program
+      const char** Args = (const char**) 
+        alloca(sizeof(const char*)*(action->args.size()+2));
+      Args[0] = action->program.toString().c_str();
+      for (unsigned i = 1; i != action->args.size(); ++i)
+        Args[i] = action->args[i].c_str();
+      Args[action->args.size()] = 0;  // null terminate list.
       if (isSet(TIME_ACTIONS_FLAG)) {
-        Timer timer(action->program.get());
+        Timer timer(action->program.toString());
         timer.startTimer();
-        int resultCode = 
-          sys::Program::ExecuteAndWait(action->program,action->args);
+        int resultCode = sys::Program::ExecuteAndWait(action->program, Args);
         timer.stopTimer();
         timer.print(timer,std::cerr);
         return resultCode == 0;
       }
       else
-        return 0 == 
-          sys::Program::ExecuteAndWait(action->program, action->args);
+        return 0 == sys::Program::ExecuteAndWait(action->program, Args);
     }
     return true;
   }
 
   /// This method tries various variants of a linkage item's file
   /// name to see if it can find an appropriate file to link with
-  /// in the directory specified.
+  /// in the directories of the LibraryPaths.
   llvm::sys::Path GetPathForLinkageItem(const std::string& link_item,
-                                        const sys::Path& dir,
                                         bool native = false) {
-    sys::Path fullpath(dir);
-    fullpath.append_file(link_item);
-    if (native) {
-      fullpath.append_suffix("a");
-    } else {
-      fullpath.append_suffix("bc");
-      if (fullpath.readable()) 
-        return fullpath;
-      fullpath.elide_suffix();
-      fullpath.append_suffix("o");
-      if (fullpath.readable()) 
-        return fullpath;
-      fullpath = dir;
-      fullpath.append_file(std::string("lib") + link_item);
-      fullpath.append_suffix("a");
-      if (fullpath.readable())
-        return fullpath;
-      fullpath.elide_suffix();
-      fullpath.append_suffix("so");
+    sys::Path fullpath;
+    fullpath.setFile(link_item);
+    if (fullpath.readable())
+      return fullpath;
+    for (PathVector::iterator PI = LibraryPaths.begin(), 
+         PE = LibraryPaths.end(); PI != PE; ++PI) {
+      fullpath.setDirectory(PI->toString());
+      fullpath.appendFile(link_item);
       if (fullpath.readable())
         return fullpath;
+      if (native) {
+        fullpath.appendSuffix("a");
+      } else {
+        fullpath.appendSuffix("bc");
+        if (fullpath.readable()) 
+          return fullpath;
+        fullpath.elideSuffix();
+        fullpath.appendSuffix("o");
+        if (fullpath.readable()) 
+          return fullpath;
+        fullpath = *PI;
+        fullpath.appendFile(std::string("lib") + link_item);
+        fullpath.appendSuffix("a");
+        if (fullpath.readable())
+          return fullpath;
+        fullpath.elideSuffix();
+        fullpath.appendSuffix("so");
+        if (fullpath.readable())
+          return fullpath;
+      }
     }
 
     // Didn't find one.
@@ -442,20 +466,15 @@ private:
     // we must track down the file in the lib search path.
     sys::Path fullpath;
     if (!link_item.readable()) {
-      // First, look for the library using the -L arguments specified
+      // look for the library using the -L arguments specified
       // on the command line.
-      PathVector::iterator PI = LibraryPaths.begin();
-      PathVector::iterator PE = LibraryPaths.end();
-      while (PI != PE && fullpath.is_empty()) {
-        fullpath = GetPathForLinkageItem(link_item.get(),*PI);
-        ++PI;
-      }
+      fullpath = GetPathForLinkageItem(link_item.toString());
 
       // If we didn't find the file in any of the library search paths
-      // so we have to bail. No where else to look.
-      if (fullpath.is_empty()) {
+      // we have to bail. No where else to look.
+      if (fullpath.isEmpty()) {
         err = 
-          std::string("Can't find linkage item '") + link_item.get() + "'";
+          std::string("Can't find linkage item '") + link_item.toString() + "'";
         return false;
       }
     } else {
@@ -466,10 +485,10 @@ private:
     set.insert(fullpath);
 
     // If its an LLVM bytecode file ...
-    if (fullpath.is_bytecode_file()) {
+    if (fullpath.isBytecodeFile()) {
       // Process the dependent libraries recursively
       Module::LibraryListType modlibs;
-      if (GetBytecodeDependentLibraries(fullpath.get(),modlibs)) {
+      if (GetBytecodeDependentLibraries(fullpath.toString(),modlibs)) {
         // Traverse the dependent libraries list
         Module::lib_iterator LI = modlibs.begin();
         Module::lib_iterator LE = modlibs.end();
@@ -478,9 +497,9 @@ private:
             if (err.empty()) {
               err = std::string("Library '") + *LI + 
                     "' is not valid for linking but is required by file '" +
-                    fullpath.get() + "'";
+                    fullpath.toString() + "'";
             } else {
-              err += " which is required by file '" + fullpath.get() + "'";
+              err += " which is required by file '" + fullpath.toString() + "'";
             }
             return false;
           }
@@ -489,7 +508,7 @@ private:
       } else if (err.empty()) {
         err = std::string(
           "The dependent libraries could not be extracted from '") + 
-          fullpath.get();
+          fullpath.toString();
         return false;
       }
     }
@@ -516,11 +535,11 @@ public:
         std::cerr << "OutputMachine = " << machine << "\n";
         InputList::const_iterator I = InpList.begin();
         while ( I != InpList.end() ) {
-          std::cerr << "Input: " << I->first.get() << "(" << I->second 
+          std::cerr << "Input: " << I->first << "(" << I->second 
                     << ")\n";
           ++I;
         }
-        std::cerr << "Output: " << Output.get() << "\n";
+        std::cerr << "Output: " << Output << "\n";
       }
 
       // If there's no input, we're done.
@@ -530,13 +549,13 @@ public:
       // If they are asking for linking and didn't provide an output
       // file then its an error (no way for us to "make up" a meaningful
       // file name based on the various linker input files).
-      if (finalPhase == LINKING && Output.is_empty())
+      if (finalPhase == LINKING && Output.isEmpty())
         throw std::string(
           "An output file name must be specified for linker output");
 
       // If they are not asking for linking, provided an output file and
       // there is more than one input file, its an error
-      if (finalPhase != LINKING && !Output.is_empty() && InpList.size() > 1)
+      if (finalPhase != LINKING && !Output.isEmpty() && InpList.size() > 1)
         throw std::string("An output file name cannot be specified ") +
           "with more than one input file name when not linking";
 
@@ -546,9 +565,10 @@ public:
       /// PRE-PROCESSING / TRANSLATION / OPTIMIZATION / ASSEMBLY phases
       // for each input item
       SetVector<sys::Path> LinkageItems;
-      std::vector<std::string> LibFiles;
+      StringVector LibFiles;
       InputList::const_iterator I = InpList.begin();
-      while ( I != InpList.end() ) {
+      for (InputList::const_iterator I = InpList.begin(), E = InpList.end();
+           I != E; ++I ) {
         // Get the suffix of the file name
         const std::string& ftype = I->second;
 
@@ -563,10 +583,10 @@ public:
               "Pre-compiled objects found but linking not requested");
           }
           if (ftype.empty())
-            LibFiles.push_back(I->first.get());
+            LibFiles.push_back(I->first.toString());
           else
             LinkageItems.insert(I->first);
-          ++I; continue; // short circuit remainder of loop
+          continue; // short circuit remainder of loop
         }
 
         // At this point, we know its something we need to translate
@@ -579,21 +599,31 @@ public:
         if (isSet(DEBUG_FLAG))
           DumpConfigData(cd,I->second);
 
+        // Add the config data's library paths to the end of the list
+        for (StringVector::iterator LPI = cd->libpaths.begin(),
+             LPE = cd->libpaths.end(); LPI != LPE; ++LPI){
+          LibraryPaths.push_back(sys::Path(*LPI));
+        }
+
         // Initialize the input and output files
         sys::Path InFile(I->first);
-        sys::Path OutFile(I->first.get_basename());
+        sys::Path OutFile(I->first.getBasename());
 
         // PRE-PROCESSING PHASE
         Action& action = cd->PreProcessor;
 
         // Get the preprocessing action, if needed, or error if appropriate
-        if (!action.program.is_empty()) {
+        if (!action.program.isEmpty()) {
           if (action.isSet(REQUIRED_FLAG) || finalPhase == PREPROCESSING) {
             if (finalPhase == PREPROCESSING) {
-              OutFile.append_suffix("E");
-              actions.push_back(GetAction(cd,InFile,OutFile,PREPROCESSING));
+              if (Output.isEmpty()) {
+                OutFile.appendSuffix("E");
+                actions.push_back(GetAction(cd,InFile,OutFile,PREPROCESSING));
+              } else {
+                actions.push_back(GetAction(cd,InFile,Output,PREPROCESSING));
+              }
             } else {
-              sys::Path TempFile(MakeTempFile(I->first.get_basename(),"E"));
+              sys::Path TempFile(MakeTempFile(I->first.getBasename(),"E"));
               actions.push_back(GetAction(cd,InFile,TempFile,
                 PREPROCESSING));
               InFile = TempFile;
@@ -608,19 +638,23 @@ public:
 
         // Short-circuit remaining actions if all they want is 
         // pre-processing
-        if (finalPhase == PREPROCESSING) { ++I; continue; };
+        if (finalPhase == PREPROCESSING) { continue; };
 
         /// TRANSLATION PHASE
         action = cd->Translator;
 
         // Get the translation action, if needed, or error if appropriate
-        if (!action.program.is_empty()) {
+        if (!action.program.isEmpty()) {
           if (action.isSet(REQUIRED_FLAG) || finalPhase == TRANSLATION) {
             if (finalPhase == TRANSLATION) {
-              OutFile.append_suffix("o");
-              actions.push_back(GetAction(cd,InFile,OutFile,TRANSLATION));
+              if (Output.isEmpty()) {
+                OutFile.appendSuffix("o");
+                actions.push_back(GetAction(cd,InFile,OutFile,TRANSLATION));
+              } else {
+                actions.push_back(GetAction(cd,InFile,Output,TRANSLATION));
+              }
             } else {
-              sys::Path TempFile(MakeTempFile(I->first.get_basename(),"trans")); 
+              sys::Path TempFile(MakeTempFile(I->first.getBasename(),"trans")); 
               actions.push_back(GetAction(cd,InFile,TempFile,TRANSLATION));
               InFile = TempFile;
             }
@@ -630,11 +664,11 @@ public:
               /// The output of the translator is an LLVM Assembly program
               /// We need to translate it to bytecode
               Action* action = new Action();
-              action->program.set_file("llvm-as");
-              action->args.push_back(InFile.get());
+              action->program.setFile("llvm-as");
+              action->args.push_back(InFile.toString());
               action->args.push_back("-o");
-              InFile.append_suffix("bc");
-              action->args.push_back(InFile.get());
+              InFile.appendSuffix("bc");
+              action->args.push_back(InFile.toString());
               actions.push_back(action);
             }
           }
@@ -646,20 +680,24 @@ public:
         }
 
         // Short-circuit remaining actions if all they want is translation
-        if (finalPhase == TRANSLATION) { ++I; continue; }
+        if (finalPhase == TRANSLATION) { continue; }
 
         /// OPTIMIZATION PHASE
         action = cd->Optimizer;
 
         // Get the optimization action, if needed, or error if appropriate
         if (!isSet(EMIT_RAW_FLAG)) {
-          if (!action.program.is_empty()) {
+          if (!action.program.isEmpty()) {
             if (action.isSet(REQUIRED_FLAG) || finalPhase == OPTIMIZATION) {
               if (finalPhase == OPTIMIZATION) {
-                OutFile.append_suffix("o");
-                actions.push_back(GetAction(cd,InFile,OutFile,OPTIMIZATION));
+                if (Output.isEmpty()) {
+                  OutFile.appendSuffix("o");
+                  actions.push_back(GetAction(cd,InFile,OutFile,OPTIMIZATION));
+                } else {
+                  actions.push_back(GetAction(cd,InFile,Output,OPTIMIZATION));
+                }
               } else {
-                sys::Path TempFile(MakeTempFile(I->first.get_basename(),"opt"));
+                sys::Path TempFile(MakeTempFile(I->first.getBasename(),"opt"));
                 actions.push_back(GetAction(cd,InFile,TempFile,OPTIMIZATION));
                 InFile = TempFile;
               }
@@ -668,12 +706,12 @@ public:
                 /// The output of the optimizer is an LLVM Assembly program
                 /// We need to translate it to bytecode with llvm-as
                 Action* action = new Action();
-                action->program.set_file("llvm-as");
-                action->args.push_back(InFile.get());
+                action->program.setFile("llvm-as");
+                action->args.push_back(InFile.toString());
                 action->args.push_back("-f");
                 action->args.push_back("-o");
-                InFile.append_suffix("bc");
-                action->args.push_back(InFile.get());
+                InFile.appendSuffix("bc");
+                action->args.push_back(InFile.toString());
                 actions.push_back(action);
               }
             }
@@ -686,43 +724,52 @@ public:
         }
 
         // Short-circuit remaining actions if all they want is optimization
-        if (finalPhase == OPTIMIZATION) { ++I; continue; }
+        if (finalPhase == OPTIMIZATION) { continue; }
 
         /// ASSEMBLY PHASE
         action = cd->Assembler;
 
         if (finalPhase == ASSEMBLY) {
+
+          // Build either a native compilation action or a disassembly action
+          Action* action = new Action();
           if (isSet(EMIT_NATIVE_FLAG)) {
             // Use llc to get the native assembly file
-            Action* action = new Action();
-            action->program.set_file("llc");
-            action->args.push_back(InFile.get());
+            action->program.setFile("llc");
+            action->args.push_back(InFile.toString());
             action->args.push_back("-f");
             action->args.push_back("-o");
-            OutFile.append_suffix("s");
-            action->args.push_back(OutFile.get());
+            if (Output.isEmpty()) {
+              OutFile.appendSuffix("o");
+              action->args.push_back(OutFile.toString());
+            } else {
+              action->args.push_back(Output.toString());
+            }
+            actions.push_back(action);
           } else {
             // Just convert back to llvm assembly with llvm-dis
-            Action* action = new Action();
-            action->program.set_file("llvm-dis");
-            action->args.push_back(InFile.get());
+            action->program.setFile("llvm-dis");
+            action->args.push_back(InFile.toString());
             action->args.push_back("-f");
             action->args.push_back("-o");
-            OutFile.append_suffix("ll");
-            action->args.push_back(OutFile.get());
-            actions.push_back(action);
+            if (Output.isEmpty()) {
+              OutFile.appendSuffix("ll");
+              action->args.push_back(OutFile.toString());
+            } else {
+              action->args.push_back(Output.toString());
+            }
           }
 
+          // Put the action on the list
+          actions.push_back(action);
+
           // Short circuit the rest of the loop, we don't want to link 
-          ++I; 
           continue;
         }
 
         // Register the result of the actions as a link candidate
         LinkageItems.insert(InFile);
 
-        // Go to next file to be processed
-        ++I;
       } // end while loop over each input file
 
       /// RUN THE COMPILATION ACTIONS
@@ -738,12 +785,13 @@ public:
       if (finalPhase == LINKING) {
 
         // Insert the platform-specific system libraries to the path list
-        LibraryPaths.push_back(sys::Path::GetSystemLibraryPath1());
-        LibraryPaths.push_back(sys::Path::GetSystemLibraryPath2());
+        std::vector<sys::Path> SysLibs;
+        sys::Path::GetSystemLibraryPaths(SysLibs);
+        LibraryPaths.insert(LibraryPaths.end(), SysLibs.begin(), SysLibs.end());
 
         // Set up the linking action with llvm-ld
         Action* link = new Action();
-        link->program.set_file("llvm-ld");
+        link->program.setFile("llvm-ld");
 
         // Add in the optimization level requested
         switch (optLevel) {
@@ -771,17 +819,17 @@ public:
         // -l arguments specified.
         for (PathVector::const_iterator I=LinkageItems.begin(), 
              E=LinkageItems.end(); I != E; ++I )
-          link->args.push_back(I->get());
+          link->args.push_back(I->toString());
 
         // Add in all the libraries we found.
-        for (std::vector<std::string>::const_iterator I=LibFiles.begin(),
+        for (StringVector::const_iterator I=LibFiles.begin(),
              E=LibFiles.end(); I != E; ++I )
           link->args.push_back(std::string("-l")+*I);
 
         // Add in all the library paths to the command line
         for (PathVector::const_iterator I=LibraryPaths.begin(),
              E=LibraryPaths.end(); I != E; ++I)
-          link->args.push_back( std::string("-L") + I->get());
+          link->args.push_back( std::string("-L") + I->toString());
 
         // Add in the additional linker arguments requested
         for (StringVector::const_iterator I=AdditionalArgs[LINKING].begin(),
@@ -806,7 +854,7 @@ public:
 
         // Add in mandatory flags
         link->args.push_back("-o");
-        link->args.push_back(Output.get());
+        link->args.push_back(Output.toString());
 
         // Execute the link
         if (!DoAction(link))
@@ -834,6 +882,7 @@ private:
   std::string machine;          ///< Target machine name
   PathVector LibraryPaths;      ///< -L options
   PathVector IncludePaths;      ///< -I options
+  PathVector ToolPaths;         ///< -B options
   StringVector Defines;         ///< -D options
   sys::Path TempDir;            ///< Name of the temporary directory.
   StringTable AdditionalArgs;   ///< The -Txyz options