[llvm-commits] CVS: llvm/tools/llvmc/CompilerDriver.cpp CompilerDriver.h ConfigLexer.h ConfigLexer.l Configuration.cpp Configuration.h Makefile llvmc.cpp st

Reid Spencer reid at x10sys.com
Sun Aug 29 12:27:07 PDT 2004



Changes in directory llvm/tools/llvmc:

CompilerDriver.cpp updated: 1.10 -> 1.11
CompilerDriver.h updated: 1.9 -> 1.10
ConfigLexer.h updated: 1.5 -> 1.6
ConfigLexer.l updated: 1.6 -> 1.7
Configuration.cpp updated: 1.10 -> 1.11
Configuration.h updated: 1.3 -> 1.4
Makefile updated: 1.5 -> 1.6
llvmc.cpp updated: 1.10 -> 1.11
st updated: 1.5 -> 1.6
---
Log message:

Convert llvmc to use the lib/System interface instead of directly 
using Unix operating system calls.


---
Diffs of the changes:  (+683 -684)

Index: llvm/tools/llvmc/CompilerDriver.cpp
diff -u llvm/tools/llvmc/CompilerDriver.cpp:1.10 llvm/tools/llvmc/CompilerDriver.cpp:1.11
--- llvm/tools/llvmc/CompilerDriver.cpp:1.10	Tue Aug 24 17:54:32 2004
+++ llvm/tools/llvmc/CompilerDriver.cpp	Sun Aug 29 14:26:56 2004
@@ -14,26 +14,19 @@
 
 #include "CompilerDriver.h"
 #include "ConfigLexer.h"
-#include "llvm/Bytecode/Reader.h"
 #include "llvm/Module.h"
+#include "llvm/Bytecode/Reader.h"
 #include "Support/FileUtilities.h"
-#include "Support/SystemUtils.h"
+#include "Support/SetVector.h"
 #include "Support/StringExtras.h"
 #include <iostream>
 
 using namespace llvm;
 
 namespace {
-  inline std::string RemoveSuffix(const std::string& fullName) {
-    size_t dotpos = fullName.rfind('.',fullName.size());
-    if ( dotpos == std::string::npos ) return fullName;
-    return fullName.substr(0, dotpos);
-  }
-
-  const char OutputSuffix[] = ".o";
 
   void WriteAction(CompilerDriver::Action* action ) {
-    std::cerr << action->program;
+    std::cerr << action->program.c_str();
     std::vector<std::string>::iterator I = action->args.begin();
     while (I != action->args.end()) {
       std::cerr << " " + *I;
@@ -43,7 +36,7 @@
   }
 
   void DumpAction(CompilerDriver::Action* action) {
-    std::cerr << "command = " << action->program;
+    std::cerr << "command = " << action->program.c_str();
     std::vector<std::string>::iterator I = action->args.begin();
     while (I != action->args.end()) {
       std::cerr << " " + *I;
@@ -74,558 +67,610 @@
   static const char* DefaultFastCompileOptimizations[] = {
     "-simplifycfg", "-mem2reg", "-instcombine"
   };
-}
-
-// Stuff in this namespace properly belongs in lib/System and needs
-// to be portable but we're avoiding that for now.
-namespace sys {
-
-  bool FileIsReadable(const std::string& fname) {
-    return 0 == access(fname.c_str(), F_OK | R_OK);
-  }
 
-  void CleanupTempFile(const std::string& fname) {
-    if (FileIsReadable(fname))
-      unlink(fname.c_str());
-  }
-
-  std::string MakeTemporaryDirectory() {
-    char temp_name[64];
-    strcpy(temp_name,"/tmp/llvm_XXXXXX");
-    if (0 == mkdtemp(temp_name))
-      throw std::string("Can't create temporary directory");
-    return temp_name;
-  }
-
-  std::string FindExecutableInPath(const std::string& program) {
-    // First, just see if the program is already executable
-    if (isExecutableFile(program)) return program;
-
-    // Get the path. If its empty, we can't do anything
-    const char *PathStr = getenv("PATH");
-    if (PathStr == 0) return "";
-
-    // Now we have a colon separated list of directories to search; try them.
-    unsigned PathLen = strlen(PathStr);
-    while (PathLen) {
-      // Find the first colon...
-      const char *Colon = std::find(PathStr, PathStr+PathLen, ':');
-    
-      // Check to see if this first directory contains the executable...
-      std::string FilePath = std::string(PathStr, Colon) + '/' + program;
-      if (isExecutableFile(FilePath))
-        return FilePath;                    // Found the executable!
-   
-      // Nope it wasn't in this directory, check the next range!
-      PathLen -= Colon-PathStr;
-      PathStr = Colon;
-
-      // Advance past duplicate coons
-      while (*PathStr == ':') {
-        PathStr++;
-        PathLen--;
+  class CompilerDriverImpl : public CompilerDriver {
+    /// @name Constructors
+    /// @{
+    public:
+      CompilerDriverImpl(ConfigDataProvider& confDatProv )
+        : cdp(&confDatProv)
+        , finalPhase(LINKING)
+        , optLevel(OPT_FAST_COMPILE) 
+        , Flags(0)
+        , machine()
+        , LibraryPaths()
+        , TempDir()
+        , AdditionalArgs()
+      {
+        TempDir = sys::Path::GetTemporaryDirectory();
+        sys::RemoveDirectoryOnSignal(TempDir);
+        AdditionalArgs.reserve(NUM_PHASES);
+        StringVector emptyVec;
+        for (unsigned i = 0; i < NUM_PHASES; ++i)
+          AdditionalArgs.push_back(emptyVec);
       }
-    }
 
-    // If we fell out, we ran out of directories in PATH to search, return failure
-    return "";
-  }
-}
-
-CompilerDriver::CompilerDriver(ConfigDataProvider& confDatProv )
-  : cdp(&confDatProv)
-  , finalPhase(LINKING)
-  , optLevel(OPT_FAST_COMPILE) 
-  , isDryRun(false)
-  , isVerbose(false)
-  , isDebug(false)
-  , timeActions(false)
-  , emitRawCode(false)
-  , emitNativeCode(false)
-  , keepTemps(false)
-  , machine()
-  , LibraryPaths()
-  , AdditionalArgs()
-  , TempDir()
-{
-  // FIXME: These libraries are platform specific
-  LibraryPaths.push_back("/lib");
-  LibraryPaths.push_back("/usr/lib");
-  AdditionalArgs.reserve(NUM_PHASES);
-  StringVector emptyVec;
-  for (unsigned i = 0; i < NUM_PHASES; ++i)
-    AdditionalArgs.push_back(emptyVec);
-}
+      virtual ~CompilerDriverImpl() {
+        cleanup();
+        cdp = 0;
+        LibraryPaths.clear();
+        AdditionalArgs.clear();
+      }
 
-CompilerDriver::~CompilerDriver() {
-  cdp = 0;
-  LibraryPaths.clear();
-  AdditionalArgs.clear();
-}
+    /// @}
+    /// @name Methods
+    /// @{
+    public:
+      virtual void setFinalPhase( Phases phase ) { 
+        finalPhase = phase; 
+      }
 
-CompilerDriver::ConfigData::ConfigData()
-  : langName()
-  , PreProcessor()
-  , Translator()
-  , Optimizer()
-  , Assembler()
-  , Linker()
-{
-  StringVector emptyVec;
-  for (unsigned i = 0; i < NUM_PHASES; ++i)
-    opts.push_back(emptyVec);
-}
+      virtual void setOptimization( OptimizationLevels level ) { 
+        optLevel = level; 
+      }
 
-void CompilerDriver::error( const std::string& errmsg ) {
-  std::cerr << "llvmc: Error: " << errmsg << ".\n";
-  exit(1);
-}
+      virtual void setDriverFlags( unsigned flags ) {
+        Flags = flags & DRIVER_FLAGS_MASK; 
+      }
 
-CompilerDriver::Action* CompilerDriver::GetAction(ConfigData* cd, 
-                          const std::string& input, 
-                          const std::string& output,
-                          Phases phase)
-{
-  Action* pat = 0; ///< The pattern/template for the action
-  Action* action = new Action; ///< The actual action to execute
+      virtual void setOutputMachine( const std::string& machineName ) {
+        machine = machineName;
+      }
 
-  // Get the action pattern
-  switch (phase) {
-    case PREPROCESSING: pat = &cd->PreProcessor; break;
-    case TRANSLATION:   pat = &cd->Translator; break;
-    case OPTIMIZATION:  pat = &cd->Optimizer; break;
-    case ASSEMBLY:      pat = &cd->Assembler; break;
-    case LINKING:       pat = &cd->Linker; break;
-    default:
-      assert(!"Invalid driver phase!");
-      break;
-  }
-  assert(pat != 0 && "Invalid command pattern");
+      virtual void setPhaseArgs(Phases phase, const StringVector& opts) {
+        assert(phase <= LINKING && phase >= PREPROCESSING);
+        AdditionalArgs[phase] = opts;
+      }
 
-  // Copy over some pattern things that don't need to change
-  action->program = pat->program;
-  action->flags = pat->flags;
-
-  // Do the substitutions from the pattern to the actual
-  StringVector::iterator PI = pat->args.begin();
-  StringVector::iterator PE = pat->args.end();
-  while (PI != PE) {
-    if ((*PI)[0] == '%') {
-      if (*PI == "%in%") {
-        action->args.push_back(input);
-      } else if (*PI == "%out%") {
-        action->args.push_back(output);
-      } else if (*PI == "%time%") {
-        if (timePasses)
-          action->args.push_back("-time-passes");
-      } else if (*PI == "%stats%") {
-        if (showStats)
-          action->args.push_back("-stats");
-      } else if (*PI == "%target%") {
-        // FIXME: Ignore for now
-      } else if (*PI == "%opt%") {
-        if (!emitRawCode) {
-          if (cd->opts.size() > static_cast<unsigned>(optLevel) && 
-              !cd->opts[optLevel].empty())
-            action->args.insert(action->args.end(), cd->opts[optLevel].begin(),
-                cd->opts[optLevel].end());
-          else
-            error("Optimization options for level " + utostr(unsigned(optLevel)) + 
-                  " were not specified");
+      virtual void setLibraryPaths(const StringVector& paths) {
+        StringVector::const_iterator I = paths.begin();
+        StringVector::const_iterator E = paths.end();
+        while (I != E) {
+          sys::Path tmp;
+          tmp.set_directory(*I);
+          LibraryPaths.push_back(tmp);
+          ++I;
         }
-      } else if (*PI == "%args%") {
-        if (AdditionalArgs.size() > unsigned(phase))
-          if (!AdditionalArgs[phase].empty()) {
-            // Get specific options for each kind of action type
-            StringVector& addargs = AdditionalArgs[phase];
-            // Add specific options for each kind of action type
-            action->args.insert(action->args.end(), addargs.begin(), addargs.end());
-          }
-      } else {
-        error("Invalid substitution name" + *PI);
       }
-    } else {
-      // Its not a substitution, just put it in the action
-      action->args.push_back(*PI);
-    }
-    PI++;
-  }
-
-
-  // Finally, we're done
-  return action;
-}
-
-bool CompilerDriver::DoAction(Action*action) {
-  assert(action != 0 && "Invalid Action!");
-  if (isVerbose)
-    WriteAction(action);
-  if (!isDryRun) {
-    std::string prog(sys::FindExecutableInPath(action->program));
-    if (prog.empty())
-      error("Can't find program '" + action->program + "'");
-
-    // Get the program's arguments
-    const char* argv[action->args.size() + 1];
-    argv[0] = prog.c_str();
-    unsigned i = 1;
-    for (; i <= action->args.size(); ++i)
-      argv[i] = action->args[i-1].c_str();
-    argv[i] = 0;
 
-    // Invoke the program
-    return !ExecWait(argv, environ);
-  }
-  return true;
-}
+      virtual void addLibraryPath( const sys::Path& libPath ) {
+        LibraryPaths.push_back(libPath);
+      }
 
-/// 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.
-std::string CompilerDriver::GetPathForLinkageItem(const std::string& link_item,
-                                                  const std::string& dir) {
-  std::string fullpath(dir + "/" + link_item + ".o");
-  if (::sys::FileIsReadable(fullpath)) 
-    return fullpath;
-  fullpath = dir + "/" + link_item + ".bc";
-  if (::sys::FileIsReadable(fullpath)) 
-    return fullpath;
-  fullpath = dir + "/lib" + link_item + ".a";
-  if (::sys::FileIsReadable(fullpath))
-    return fullpath;
-  fullpath = dir + "/lib" + link_item + ".so";
-  if (::sys::FileIsReadable(fullpath))
-    return fullpath;
-  return "";
-}
+    /// @}
+    /// @name Functions
+    /// @{
+    private:
+      bool isSet(DriverFlags flag) {
+        return 0 != ((flag & DRIVER_FLAGS_MASK) & Flags);
+      }
 
-/// This method processes a linkage item. The item could be a
-/// Bytecode file needing translation to native code and that is
-/// dependent on other bytecode libraries, or a native code
-/// library that should just be linked into the program.
-bool CompilerDriver::ProcessLinkageItem(const std::string& link_item,
-                                        SetVector<std::string>& set,
-                                        std::string& err) {
-  // First, see if the unadorned file name is not readable. If so,
-  // we must track down the file in the lib search path.
-  std::string fullpath;
-  if (!sys::FileIsReadable(link_item)) {
-    // First, look for the library using the -L arguments specified
-    // on the command line.
-    StringVector::iterator PI = LibraryPaths.begin();
-    StringVector::iterator PE = LibraryPaths.end();
-    while (PI != PE && fullpath.empty()) {
-      fullpath = GetPathForLinkageItem(link_item,*PI);
-      ++PI;
-    }
+      void cleanup() {
+        if (!isSet(KEEP_TEMPS_FLAG)) {
+          if (TempDir.is_directory() && TempDir.writable())
+            TempDir.destroy_directory(/*remove_contents=*/true);
+        } else {
+          std::cout << "Temporary files are in " << TempDir.get() << "\n";
+        }
+      }
 
-    // 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.empty()) {
-      err = std::string("Can't find linkage item '") + link_item + "'";
-      return false;
-    }
-  } else {
-    fullpath = link_item;
-  }
+      sys::Path MakeTempFile(const std::string& basename, const std::string& suffix ) {
+        sys::Path result(TempDir);
+        if (!result.append_file(basename))
+          throw basename + ": can't use this file name";
+        if (!result.append_suffix(suffix))
+          throw suffix + ": can't use this file suffix";
+        return result;
+      }
 
-  // If we got here fullpath is the path to the file, and its readable.
-  set.insert(fullpath);
+      Action* GetAction(ConfigData* cd, 
+                        const sys::Path& input, 
+                        const sys::Path& output,
+                        Phases phase)
+      {
+        Action* pat = 0; ///< The pattern/template for the action
+        Action* action = new Action; ///< The actual action to execute
+
+        // Get the action pattern
+        switch (phase) {
+          case PREPROCESSING: pat = &cd->PreProcessor; break;
+          case TRANSLATION:   pat = &cd->Translator; break;
+          case OPTIMIZATION:  pat = &cd->Optimizer; break;
+          case ASSEMBLY:      pat = &cd->Assembler; break;
+          case LINKING:       pat = &cd->Linker; break;
+          default:
+            assert(!"Invalid driver phase!");
+            break;
+        }
+        assert(pat != 0 && "Invalid command pattern");
 
-  // If its an LLVM bytecode file ...
-  if (CheckMagic(fullpath, "llvm")) {
-    // Process the dependent libraries recursively
-    Module::LibraryListType modlibs;
-    if (GetBytecodeDependentLibraries(fullpath,modlibs)) {
-      // Traverse the dependent libraries list
-      Module::lib_iterator LI = modlibs.begin();
-      Module::lib_iterator LE = modlibs.end();
-      while ( LI != LE ) {
-        if (!ProcessLinkageItem(*LI,set,err)) {
-          if (err.empty()) {
-            err = std::string("Library '") + *LI + 
-                  "' is not valid for linking but is required by file '" +
-                  fullpath + "'";
+        // Copy over some pattern things that don't need to change
+        action->program = pat->program;
+        action->flags = pat->flags;
+
+        // Do the substitutions from the pattern to the actual
+        StringVector::iterator PI = pat->args.begin();
+        StringVector::iterator PE = pat->args.end();
+        while (PI != PE) {
+          if ((*PI)[0] == '%') {
+            if (*PI == "%in%") {
+              action->args.push_back(input.get());
+            } else if (*PI == "%out%") {
+              action->args.push_back(output.get());
+            } else if (*PI == "%time%") {
+              if (isSet(TIME_PASSES_FLAG))
+                action->args.push_back("-time-passes");
+            } else if (*PI == "%stats%") {
+              if (isSet(SHOW_STATS_FLAG))
+                action->args.push_back("-stats");
+            } else if (*PI == "%force%") {
+              if (isSet(FORCE_FLAG))
+                action->args.push_back("-f");
+            } else if (*PI == "%verbose%") {
+              if (isSet(VERBOSE_FLAG))
+                action->args.push_back("-v");
+            } else if (*PI == "%target%") {
+              // FIXME: Ignore for now
+            } else if (*PI == "%opt%") {
+              if (!isSet(EMIT_RAW_FLAG)) {
+                if (cd->opts.size() > static_cast<unsigned>(optLevel) && 
+                    !cd->opts[optLevel].empty())
+                  action->args.insert(action->args.end(), cd->opts[optLevel].begin(),
+                      cd->opts[optLevel].end());
+                else
+                  throw std::string("Optimization options for level ") + 
+                        utostr(unsigned(optLevel)) + " were not specified";
+              }
+            } else if (*PI == "%args%") {
+              if (AdditionalArgs.size() > unsigned(phase))
+                if (!AdditionalArgs[phase].empty()) {
+                  // Get specific options for each kind of action type
+                  StringVector& addargs = AdditionalArgs[phase];
+                  // Add specific options for each kind of action type
+                  action->args.insert(action->args.end(), addargs.begin(), addargs.end());
+                }
+            } else {
+              throw "Invalid substitution name" + *PI;
+            }
           } else {
-            err += " which is required by file '" + fullpath + "'";
+            // Its not a substitution, just put it in the action
+            action->args.push_back(*PI);
           }
-          return false;
+          PI++;
         }
-        ++LI;
-      }
-    } else if (err.empty()) {
-      err = std::string("The dependent libraries could not be extracted from '")
-                        + fullpath;
-      return false;
-    }
-  }
-  return true;
-}
-
 
-int CompilerDriver::execute(const InputList& InpList, 
-                            const std::string& Output ) {
-  // Echo the configuration of options if we're running verbose
-  if (isDebug)
-  {
-    std::cerr << "Compiler Driver Options:\n";
-    std::cerr << "DryRun = " << isDryRun << "\n";
-    std::cerr << "Verbose = " << isVerbose << " \n";
-    std::cerr << "TimeActions = " << timeActions << "\n";
-    std::cerr << "EmitRawCode = " << emitRawCode << "\n";
-    std::cerr << "OutputMachine = " << machine << "\n";
-    std::cerr << "EmitNativeCode = " << emitNativeCode << "\n";
-    InputList::const_iterator I = InpList.begin();
-    while ( I != InpList.end() ) {
-      std::cerr << "Input: " << I->first << "(" << I->second << ")\n";
-      ++I;
-    }
-    std::cerr << "Output: " << Output << "\n";
-  }
 
-  // If there's no input, we're done.
-  if (InpList.empty())
-    error("Nothing to compile.");
-
-  // 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.empty())
-    error("An output file name must be specified for linker output");
-
-  // This vector holds all the resulting actions of the following loop.
-  std::vector<Action*> actions;
-
-  // Create a temporary directory for our temporary files
-  std::string TempDir(sys::MakeTemporaryDirectory());
-  std::string TempPreprocessorOut(TempDir + "/preproc.o");
-  std::string TempTranslatorOut(TempDir + "/trans.o");
-  std::string TempOptimizerOut(TempDir + "/opt.o");
-  std::string TempAssemblerOut(TempDir + "/asm.o");
-
-  /// PRE-PROCESSING / TRANSLATION / OPTIMIZATION / ASSEMBLY phases
-  // for each input item
-  std::vector<std::string> LinkageItems;
-  std::string OutFile(Output);
-  InputList::const_iterator I = InpList.begin();
-  while ( I != InpList.end() ) {
-    // Get the suffix of the file name
-    const std::string& ftype = I->second;
-
-    // If its a library, bytecode file, or object file, save 
-    // it for linking below and short circuit the 
-    // pre-processing/translation/assembly phases
-    if (ftype.empty() ||  ftype == "o" || ftype == "bc") {
-      // We shouldn't get any of these types of files unless we're 
-      // later going to link. Enforce this limit now.
-      if (finalPhase != LINKING) {
-        error("Pre-compiled objects found but linking not requested");
+        // Finally, we're done
+        return action;
       }
-      LinkageItems.push_back(I->first);
-      ++I; continue; // short circuit remainder of loop
-    }
 
-    // At this point, we know its something we need to translate
-    // and/or optimize. See if we can get the configuration data
-    // for this kind of file.
-    ConfigData* cd = cdp->ProvideConfigData(I->second);
-    if (cd == 0)
-      error(std::string("Files of type '") + I->second + 
-            "' are not recognized." ); 
-    if (isDebug)
-      DumpConfigData(cd,I->second);
-
-    // Initialize the input file
-    std::string InFile(I->first);
-
-    // PRE-PROCESSING PHASE
-    Action& action = cd->PreProcessor;
-
-    // Get the preprocessing action, if needed, or error if appropriate
-    if (!action.program.empty()) {
-      if (action.isSet(REQUIRED_FLAG) || finalPhase == PREPROCESSING) {
-        if (finalPhase == PREPROCESSING)
-          actions.push_back(GetAction(cd,InFile,OutFile,PREPROCESSING));
-        else {
-          actions.push_back(GetAction(cd,InFile,TempPreprocessorOut,
-                            PREPROCESSING));
-          InFile = TempPreprocessorOut;
+      bool DoAction(Action*action) {
+        assert(action != 0 && "Invalid Action!");
+        if (isSet(VERBOSE_FLAG))
+          WriteAction(action);
+        if (!isSet(DRY_RUN_FLAG)) {
+          action->program = sys::Program::FindProgramByName(action->program.get());
+          if (action->program.is_empty())
+            throw "Can't find program '" + action->program.get() + "'";
+
+          // Invoke the program
+          return 0 == action->program.ExecuteAndWait(action->args);
         }
+        return true;
       }
-    } else if (finalPhase == PREPROCESSING) {
-      error(cd->langName + " does not support pre-processing");
-    } else if (action.isSet(REQUIRED_FLAG)) {
-      error(std::string("Don't know how to pre-process ") + 
-            cd->langName + " files");
-    }
 
-    // Short-circuit remaining actions if all they want is pre-processing
-    if (finalPhase == PREPROCESSING) { ++I; continue; };
+      /// 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.
+      llvm::sys::Path GetPathForLinkageItem(const std::string& link_item,
+                                            const sys::Path& dir) {
+        sys::Path fullpath(dir);
+        fullpath.append_file(link_item);
+        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");
+        if (fullpath.readable())
+          return fullpath;
+
+        // Didn't find one.
+        fullpath.clear();
+        return fullpath;
+      }
 
-    /// TRANSLATION PHASE
-    action = cd->Translator;
+      /// This method processes a linkage item. The item could be a
+      /// Bytecode file needing translation to native code and that is
+      /// dependent on other bytecode libraries, or a native code
+      /// library that should just be linked into the program.
+      bool ProcessLinkageItem(const llvm::sys::Path& link_item,
+                              SetVector<sys::Path>& set,
+                              std::string& err) {
+        // First, see if the unadorned file name is not readable. If so,
+        // 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
+          // 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;
+          }
 
-    // Get the translation action, if needed, or error if appropriate
-    if (!action.program.empty()) {
-      if (action.isSet(REQUIRED_FLAG) || finalPhase == TRANSLATION) {
-        if (finalPhase == TRANSLATION) 
-          actions.push_back(GetAction(cd,InFile,OutFile,TRANSLATION));
-        else {
-          actions.push_back(GetAction(cd,InFile,TempTranslatorOut,TRANSLATION));
-          InFile = TempTranslatorOut;
+          // 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()) {
+            err = std::string("Can't find linkage item '") + link_item.get() + "'";
+            return false;
+          }
+        } else {
+          fullpath = link_item;
         }
 
-        // ll -> bc Helper
-        if (action.isSet(OUTPUT_IS_ASM_FLAG)) {
-          /// The output of the translator is an LLVM Assembly program
-          /// We need to translate it to bytecode
-          Action* action = new Action();
-          action->program = "llvm-as";
-          action->args.push_back(InFile);
-          action->args.push_back("-o");
-          InFile += ".bc";
-          action->args.push_back(InFile);
-          actions.push_back(action);
+        // If we got here fullpath is the path to the file, and its readable.
+        set.insert(fullpath);
+
+        // If its an LLVM bytecode file ...
+        if (CheckMagic(fullpath.get(), "llvm")) {
+          // Process the dependent libraries recursively
+          Module::LibraryListType modlibs;
+          if (GetBytecodeDependentLibraries(fullpath.get(),modlibs)) {
+            // Traverse the dependent libraries list
+            Module::lib_iterator LI = modlibs.begin();
+            Module::lib_iterator LE = modlibs.end();
+            while ( LI != LE ) {
+              if (!ProcessLinkageItem(sys::Path(*LI),set,err)) {
+                if (err.empty()) {
+                  err = std::string("Library '") + *LI + 
+                        "' is not valid for linking but is required by file '" +
+                        fullpath.get() + "'";
+                } else {
+                  err += " which is required by file '" + fullpath.get() + "'";
+                }
+                return false;
+              }
+              ++LI;
+            }
+          } else if (err.empty()) {
+            err = std::string("The dependent libraries could not be extracted from '")
+                              + fullpath.get();
+            return false;
+          }
         }
+        return true;
       }
-    } else if (finalPhase == TRANSLATION) {
-      error(cd->langName + " does not support translation");
-    } else if (action.isSet(REQUIRED_FLAG)) {
-      error(std::string("Don't know how to translate ") + 
-            cd->langName + " files");
-    }
 
-    // Short-circuit remaining actions if all they want is translation
-    if (finalPhase == TRANSLATION) { ++I; continue; }
+    /// @}
+    /// @name Methods
+    /// @{
+    public:
+      virtual int execute(const InputList& InpList, const sys::Path& Output ) {
+        try {
+          // Echo the configuration of options if we're running verbose
+          if (isSet(DEBUG_FLAG)) {
+            std::cerr << "Compiler Driver Options:\n";
+            std::cerr << "DryRun = " << isSet(DRY_RUN_FLAG) << "\n";
+            std::cerr << "Verbose = " << isSet(VERBOSE_FLAG) << " \n";
+            std::cerr << "TimeActions = " << isSet(TIME_ACTIONS_FLAG) << "\n";
+            std::cerr << "TimePasses = " << isSet(TIME_PASSES_FLAG) << "\n";
+            std::cerr << "ShowStats = " << isSet(SHOW_STATS_FLAG) << "\n";
+            std::cerr << "EmitRawCode = " << isSet(EMIT_RAW_FLAG) << "\n";
+            std::cerr << "EmitNativeCode = " << isSet(EMIT_NATIVE_FLAG) << "\n";
+            std::cerr << "ForceOutput = " << isSet(FORCE_FLAG) << "\n";
+            std::cerr << "KeepTemps = " << isSet(KEEP_TEMPS_FLAG) << "\n";
+            std::cerr << "OutputMachine = " << machine << "\n";
+            InputList::const_iterator I = InpList.begin();
+            while ( I != InpList.end() ) {
+              std::cerr << "Input: " << I->first.get() << "(" << I->second << ")\n";
+              ++I;
+            }
+            std::cerr << "Output: " << Output.get() << "\n";
+          }
 
-    /// OPTIMIZATION PHASE
-    action = cd->Optimizer;
+          // If there's no input, we're done.
+          if (InpList.empty())
+            throw std::string("Nothing to compile.");
+
+          // 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())
+            throw std::string(
+              "An output file name must be specified for linker output");
+
+          // This vector holds all the resulting actions of the following loop.
+          std::vector<Action*> actions;
+
+          /// PRE-PROCESSING / TRANSLATION / OPTIMIZATION / ASSEMBLY phases
+          // for each input item
+          SetVector<sys::Path> LinkageItems;
+          sys::Path OutFile(Output);
+          InputList::const_iterator I = InpList.begin();
+          while ( I != InpList.end() ) {
+            // Get the suffix of the file name
+            const std::string& ftype = I->second;
+
+            // If its a library, bytecode file, or object file, save 
+            // it for linking below and short circuit the 
+            // pre-processing/translation/assembly phases
+            if (ftype.empty() ||  ftype == "o" || ftype == "bc") {
+              // We shouldn't get any of these types of files unless we're 
+              // later going to link. Enforce this limit now.
+              if (finalPhase != LINKING) {
+                throw std::string(
+                  "Pre-compiled objects found but linking not requested");
+              }
+              LinkageItems.insert(I->first);
+              ++I; continue; // short circuit remainder of loop
+            }
+
+            // At this point, we know its something we need to translate
+            // and/or optimize. See if we can get the configuration data
+            // for this kind of file.
+            ConfigData* cd = cdp->ProvideConfigData(I->second);
+            if (cd == 0)
+              throw std::string("Files of type '") + I->second + 
+                    "' are not recognized."; 
+            if (isSet(DEBUG_FLAG))
+              DumpConfigData(cd,I->second);
+
+            // Initialize the input file
+            sys::Path InFile(I->first);
+
+            // PRE-PROCESSING PHASE
+            Action& action = cd->PreProcessor;
+
+            // Get the preprocessing action, if needed, or error if appropriate
+            if (!action.program.is_empty()) {
+              if (action.isSet(REQUIRED_FLAG) || finalPhase == PREPROCESSING) {
+                if (finalPhase == PREPROCESSING)
+                  actions.push_back(GetAction(cd,InFile,OutFile,PREPROCESSING));
+                else {
+                  sys::Path TempFile(MakeTempFile(I->first.get(),"E"));
+                  actions.push_back(GetAction(cd,InFile,TempFile,PREPROCESSING));
+                  InFile = TempFile;
+                }
+              }
+            } else if (finalPhase == PREPROCESSING) {
+              throw cd->langName + " does not support pre-processing";
+            } else if (action.isSet(REQUIRED_FLAG)) {
+              throw std::string("Don't know how to pre-process ") + 
+                    cd->langName + " files";
+            }
+
+            // Short-circuit remaining actions if all they want is pre-processing
+            if (finalPhase == PREPROCESSING) { ++I; continue; };
+
+            /// TRANSLATION PHASE
+            action = cd->Translator;
+
+            // Get the translation action, if needed, or error if appropriate
+            if (!action.program.is_empty()) {
+              if (action.isSet(REQUIRED_FLAG) || finalPhase == TRANSLATION) {
+                if (finalPhase == TRANSLATION) 
+                  actions.push_back(GetAction(cd,InFile,OutFile,TRANSLATION));
+                else {
+                  sys::Path TempFile(MakeTempFile(I->first.get(),"trans")); 
+                  actions.push_back(GetAction(cd,InFile,TempFile,TRANSLATION));
+                  InFile = TempFile;
+                }
+
+                // ll -> bc Helper
+                if (action.isSet(OUTPUT_IS_ASM_FLAG)) {
+                  /// 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->args.push_back("-o");
+                  InFile.append_suffix("bc");
+                  action->args.push_back(InFile.get());
+                  actions.push_back(action);
+                }
+              }
+            } else if (finalPhase == TRANSLATION) {
+              throw cd->langName + " does not support translation";
+            } else if (action.isSet(REQUIRED_FLAG)) {
+              throw std::string("Don't know how to translate ") + 
+                    cd->langName + " files";
+            }
+
+            // Short-circuit remaining actions if all they want is translation
+            if (finalPhase == TRANSLATION) { ++I; 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.isSet(REQUIRED_FLAG) || finalPhase == OPTIMIZATION) {
+                  if (finalPhase == OPTIMIZATION)
+                    actions.push_back(GetAction(cd,InFile,OutFile,OPTIMIZATION));
+                  else {
+                    sys::Path TempFile(MakeTempFile(I->first.get(),"opt"));
+                    actions.push_back(GetAction(cd,InFile,TempFile,OPTIMIZATION));
+                    InFile = TempFile;
+                  }
+                  // ll -> bc Helper
+                  if (action.isSet(OUTPUT_IS_ASM_FLAG)) {
+                    /// 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->args.push_back("-f");
+                    action->args.push_back("-o");
+                    InFile.append_suffix("bc");
+                    action->args.push_back(InFile.get());
+                    actions.push_back(action);
+                  }
+                }
+              } else if (finalPhase == OPTIMIZATION) {
+                throw cd->langName + " does not support optimization";
+              } else if (action.isSet(REQUIRED_FLAG)) {
+                throw std::string("Don't know how to optimize ") + 
+                    cd->langName + " files";
+              }
+            }
+
+            // Short-circuit remaining actions if all they want is optimization
+            if (finalPhase == OPTIMIZATION) { ++I; continue; }
+
+            /// ASSEMBLY PHASE
+            action = cd->Assembler;
+
+            if (finalPhase == ASSEMBLY || isSet(EMIT_NATIVE_FLAG)) {
+              if (isSet(EMIT_NATIVE_FLAG)) {
+                if (action.program.is_empty()) {
+                  throw std::string("Native Assembler not specified for ") +
+                        cd->langName + " files";
+                } else if (finalPhase == ASSEMBLY) {
+                  actions.push_back(GetAction(cd,InFile,OutFile,ASSEMBLY));
+                } else {
+                  sys::Path TempFile(MakeTempFile(I->first.get(),"S"));
+                  actions.push_back(GetAction(cd,InFile,TempFile,ASSEMBLY));
+                  InFile = TempFile;
+                }
+              } 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->args.push_back("-f");
+                action->args.push_back("-o");
+                action->args.push_back(OutFile.get());
+                actions.push_back(action);
+              }
+            }
+
+            // Short-circuit remaining actions if all they want is assembly output
+            if (finalPhase == ASSEMBLY) { ++I; continue; }
+              
+            // Register the OutFile as a link candidate
+            LinkageItems.insert(InFile);
 
-    // Get the optimization action, if needed, or error if appropriate
-    if (!emitRawCode) {
-      if (!action.program.empty()) {
-        if (action.isSet(REQUIRED_FLAG) || finalPhase == OPTIMIZATION) {
-          if (finalPhase == OPTIMIZATION)
-            actions.push_back(GetAction(cd,InFile,OutFile,OPTIMIZATION));
-          else {
-            actions.push_back(GetAction(cd,InFile,TempOptimizerOut,OPTIMIZATION));
-            InFile = TempOptimizerOut;
+            // Go to next file to be processed
+            ++I;
           }
-          // ll -> bc Helper
-          if (action.isSet(OUTPUT_IS_ASM_FLAG)) {
-            /// The output of the translator is an LLVM Assembly program
-            /// We need to translate it to bytecode
-            Action* action = new Action();
-            action->program = "llvm-as";
-            action->args.push_back(InFile);
-            action->args.push_back("-f");
-            action->args.push_back("-o");
-            InFile += ".bc";
-            action->args.push_back(InFile);
-            actions.push_back(action);
-          }
-        }
-      } else if (finalPhase == OPTIMIZATION) {
-        error(cd->langName + " does not support optimization");
-      } else if (action.isSet(REQUIRED_FLAG)) {
-        error(std::string("Don't know how to optimize ") + 
-            cd->langName + " files");
-      }
-    }
 
-    // Short-circuit remaining actions if all they want is optimization
-    if (finalPhase == OPTIMIZATION) { ++I; continue; }
+          /// RUN THE COMPILATION ACTIONS
+          std::vector<Action*>::iterator AI = actions.begin();
+          std::vector<Action*>::iterator AE = actions.end();
+          while (AI != AE) {
+            if (!DoAction(*AI))
+              throw "Action failed";
+            AI++;
+          }
 
-    /// ASSEMBLY PHASE
-    action = cd->Assembler;
+          /// LINKING PHASE
+          actions.clear();
+          if (finalPhase == LINKING) {
+            if (isSet(EMIT_NATIVE_FLAG)) {
+              throw "llvmc doesn't know how to link native code yet";
+            } else {
+              // First, we need to examine the files to ensure that they all contain
+              // bytecode files. Since the final output is bytecode, we can only
+              // link bytecode.
+              SetVector<sys::Path>::const_iterator I = LinkageItems.begin();
+              SetVector<sys::Path>::const_iterator E = LinkageItems.end();
+              std::string errmsg;
+
+              while (I != E && ProcessLinkageItem(*I,LinkageItems,errmsg))
+                ++I;
+
+              if (!errmsg.empty())
+                throw errmsg;
+
+              // Insert the system libraries.
+              LibraryPaths.push_back(sys::Path::GetSystemLibraryPath1());
+              LibraryPaths.push_back(sys::Path::GetSystemLibraryPath2());
+
+              // We're emitting bytecode so let's build an llvm-link Action
+              Action* link = new Action();
+              link->program.set_file("llvm-link");
+              for (PathVector::const_iterator I=LinkageItems.begin(), 
+                   E=LinkageItems.end(); I != E; ++I )
+                link->args.push_back(I->get());
+              if (isSet(VERBOSE_FLAG))
+                link->args.push_back("-v");
+              link->args.push_back("-f");
+              link->args.push_back("-o");
+              link->args.push_back(OutFile.get());
+              if (isSet(TIME_PASSES_FLAG))
+                link->args.push_back("-time-passes");
+              if (isSet(SHOW_STATS_FLAG))
+                link->args.push_back("-stats");
+              actions.push_back(link);
+            }
+          }
 
-    if (finalPhase == ASSEMBLY || emitNativeCode) {
-      if (emitNativeCode) {
-        if (action.program.empty()) {
-          error(std::string("Native Assembler not specified for ") +
-                cd->langName + " files");
-        } else if (finalPhase == ASSEMBLY) {
-          actions.push_back(GetAction(cd,InFile,OutFile,ASSEMBLY));
-        } else {
-          actions.push_back(GetAction(cd,InFile,TempAssemblerOut,ASSEMBLY));
-          InFile = TempAssemblerOut;
+          /// RUN THE LINKING ACTIONS
+          AI = actions.begin();
+          AE = actions.end();
+          while (AI != AE) {
+            if (!DoAction(*AI))
+              throw std::string("Action failed");
+            AI++;
+          }
+        } catch (std::string& msg) {
+          cleanup();
+          throw;
+        } catch (...) {
+          cleanup();
+          throw std::string("Unspecified error");
         }
-      } else {
-        // Just convert back to llvm assembly with llvm-dis
-        Action* action = new Action();
-        action->program = "llvm-dis";
-        action->args.push_back(InFile);
-        action->args.push_back("-f");
-        action->args.push_back("-o");
-        action->args.push_back(OutFile);
-        actions.push_back(action);
+        cleanup();
+        return 0;
       }
-    }
-
-    // Short-circuit remaining actions if all they want is assembly output
-    if (finalPhase == ASSEMBLY) { ++I; continue; }
-      
-    // Register the OutFile as a link candidate
-    LinkageItems.push_back(InFile);
 
-    // Go to next file to be processed
-    ++I;
-  }
+    /// @}
+    /// @name Data
+    /// @{
+    private:
+      ConfigDataProvider* cdp;      ///< Where we get configuration data from
+      Phases finalPhase;            ///< The final phase of compilation
+      OptimizationLevels optLevel;  ///< The optimization level to apply
+      unsigned Flags;               ///< The driver flags
+      std::string machine;          ///< Target machine name
+      PathVector LibraryPaths;      ///< -L options
+      sys::Path TempDir;            ///< Name of the temporary directory.
+      StringTable AdditionalArgs;   ///< The -Txyz options
 
-  /// RUN THE COMPILATION ACTIONS
-  std::vector<Action*>::iterator aIter = actions.begin();
-  while (aIter != actions.end()) {
-    if (!DoAction(*aIter))
-      error("Action failed");
-    aIter++;
-  }
+    /// @}
+  };
+}
 
-  /// LINKING PHASE
-  if (finalPhase == LINKING) {
-    if (emitNativeCode) {
-      error("llvmc doesn't know how to link native code yet");
-    } else {
-      // First, we need to examine the files to ensure that they all contain
-      // bytecode files. Since the final output is bytecode, we can only
-      // link bytecode.
-      StringVector::const_iterator I = LinkageItems.begin();
-      StringVector::const_iterator E = LinkageItems.end();
-      SetVector<std::string> link_items;
-      std::string errmsg;
-      while (I != E && ProcessLinkageItem(*I,link_items,errmsg))
-        ++I;
-
-      if (!errmsg.empty())
-        error(errmsg);
-
-      // We're emitting bytecode so let's build an llvm-link Action
-      Action* link = new Action();
-      link->program = "llvm-link";
-      link->args = LinkageItems;
-      link->args.insert(link->args.end(), link_items.begin(), link_items.end());
-      link->args.push_back("-f");
-      link->args.push_back("-o");
-      link->args.push_back(OutFile);
-      if (timePasses)
-        link->args.push_back("-time-passes");
-      if (showStats)
-        link->args.push_back("-stats");
-      actions.push_back(link);
-    }
-  }
+CompilerDriver::~CompilerDriver() {
+}
 
-  if (!keepTemps) {
-    // Cleanup files
-    ::sys::CleanupTempFile(TempPreprocessorOut);
-    ::sys::CleanupTempFile(TempTranslatorOut);
-    ::sys::CleanupTempFile(TempOptimizerOut);
-
-    // Cleanup temporary directory we created
-    if (::sys::FileIsReadable(TempDir))
-      rmdir(TempDir.c_str());
-  }
+CompilerDriver*
+CompilerDriver::Get(ConfigDataProvider& CDP) {
+  return new CompilerDriverImpl(CDP);
+}
 
-  return 0;
+CompilerDriver::ConfigData::ConfigData()
+  : langName()
+  , PreProcessor()
+  , Translator()
+  , Optimizer()
+  , Assembler()
+  , Linker()
+{
+  StringVector emptyVec;
+  for (unsigned i = 0; i < NUM_PHASES; ++i)
+    opts.push_back(emptyVec);
 }
 
 // vim: sw=2 smartindent smarttab tw=80 autoindent expandtab


Index: llvm/tools/llvmc/CompilerDriver.h
diff -u llvm/tools/llvmc/CompilerDriver.h:1.9 llvm/tools/llvmc/CompilerDriver.h:1.10
--- llvm/tools/llvmc/CompilerDriver.h:1.9	Tue Aug 24 17:55:34 2004
+++ llvm/tools/llvmc/CompilerDriver.h	Sun Aug 29 14:26:56 2004
@@ -16,7 +16,7 @@
 
 #include <string>
 #include <vector>
-#include "Support/SetVector.h"
+#include "llvm/System/Program.h"
 
 namespace llvm {
   /// This class provides the high level interface to the LLVM Compiler Driver.
@@ -30,9 +30,12 @@
     /// @name Types
     /// @{
     public:
-      /// @brief A vector of strings, commonly used
+      /// @brief A vector of strings, used for argument lists
       typedef std::vector<std::string> StringVector;
 
+      /// @brief A vector of sys::Path, used for path lists
+      typedef std::vector<sys::Path> PathVector;
+
       /// @brief A table of strings, indexed typically by Phases
       typedef std::vector<StringVector> StringTable;
 
@@ -65,11 +68,26 @@
         FLAGS_MASK           = 0x000F, ///< Union of all flags
       };
 
+      /// @brief Driver specific flags
+      enum DriverFlags {
+        DRY_RUN_FLAG         = 0x0001, ///< Do everything but execute actions
+        FORCE_FLAG           = 0x0002, ///< Force overwrite of output files
+        VERBOSE_FLAG         = 0x0004, ///< Print each action
+        DEBUG_FLAG           = 0x0008, ///< Print debug information
+        TIME_PASSES_FLAG     = 0x0010, ///< Time the passes as they execute
+        TIME_ACTIONS_FLAG    = 0x0020, ///< Time the actions as they execute
+        SHOW_STATS_FLAG      = 0x0040, ///< Show pass statistics
+        EMIT_NATIVE_FLAG     = 0x0080, ///< Emit native code instead of bc
+        EMIT_RAW_FLAG        = 0x0100, ///< Emit raw, unoptimized bytecode
+        KEEP_TEMPS_FLAG      = 0x0200, ///< Don't delete temporary files
+        DRIVER_FLAGS_MASK    = 0x02FF, ///< Union of the above flags
+      };
+
       /// This type is the input list to the CompilerDriver. It provides
-      /// a vector of filename/filetype pairs. The filetype is used to look up
+      /// a vector of pathname/filetype pairs. The filetype is used to look up
       /// the configuration of the actions to be taken by the driver.
       /// @brief The Input Data to the execute method
-      typedef std::vector<std::pair<std::string,std::string> > InputList;
+      typedef std::vector<std::pair<sys::Path,std::string> > InputList;
 
       /// This type is read from configuration files or otherwise provided to
       /// the CompilerDriver through a "ConfigDataProvider". It serves as both
@@ -78,7 +96,7 @@
       /// language.
       struct Action {
         Action() : flags(0) {}
-        std::string program;   ///< The program to execve
+        sys::Program program;  ///< The program to execve
         StringVector args;     ///< Arguments to the program
         unsigned flags;        ///< Action specific flags
         void set(unsigned fl ) { flags |= fl; }
@@ -107,127 +125,49 @@
       class ConfigDataProvider {
       public:
         virtual ConfigData* ProvideConfigData(const std::string& filetype) = 0;
-        virtual void setConfigDir(const std::string& dirName) = 0;
+        virtual void setConfigDir(const sys::Path& dirName) = 0;
       };
 
     /// @}
     /// @name Constructors
     /// @{
     public:
-      CompilerDriver(ConfigDataProvider& cdp );
+      /// @brief Static Constructor
+      static CompilerDriver* Get(ConfigDataProvider& CDP);
+
+      /// @brief Virtual destructor
       virtual ~CompilerDriver();
 
     /// @}
     /// @name Methods
     /// @{
     public:
-      /// @brief Handle an error
-      virtual void error(const std::string& errmsg);
-
       /// @brief Execute the actions requested for the given input list.
-      virtual int execute(const InputList& list, const std::string& output);
+      virtual int execute(const InputList& list, const sys::Path& output) = 0;
 
-    /// @}
-    /// @name Mutators
-    /// @{
-    public:
       /// @brief Set the final phase at which compilation terminates
-      void setFinalPhase( Phases phase ) { finalPhase = phase; }
+      virtual void setFinalPhase(Phases phase) = 0;
 
       /// @brief Set the optimization level for the compilation
-      void setOptimization( OptimizationLevels level ) { optLevel = level; }
-
-      /// @brief Prevent the CompilerDriver from taking any actions
-      void setDryRun( bool TF ) { isDryRun = TF; }
-
-      /// @brief Cause the CompilerDriver to print to stderr all the
-      /// actions it is taking.
-      void setVerbose( bool TF ) { isVerbose = TF; }
-
-      /// @brief Cause the CompilerDriver to print to stderr very verbose
-      /// information that might be useful in debugging the driver's actions
-      void setDebug( bool TF ) { isDebug = TF; }
-
-      /// @brief Cause the CompilerDriver to print to stderr the 
-      /// execution time of each action taken.
-      void setTimeActions( bool TF ) { timeActions = TF; }
+      virtual void setOptimization(OptimizationLevels level) = 0;
 
-      /// @brief Cause the CompilerDriver to print timings for each pass.
-      void setTimePasses( bool TF ) { timePasses = TF; }
-
-      /// @brief Cause the CompilerDriver to show statistics gathered
-      void setShowStats( bool TF ) { showStats = TF; }
-
-      /// @brief Indicate that native code is to be generated instead
-      /// of LLVM bytecode.
-      void setEmitNativeCode( bool TF ) { emitNativeCode = TF; }
-
-      /// @brief Indicate that raw, unoptimized code is to be generated.
-      void setEmitRawCode(bool TF ) { emitRawCode = TF; }
-
-      void setKeepTemporaries(bool TF) { keepTemps = TF; }
+      /// @brief Set the driver flags.
+      virtual void setDriverFlags(unsigned flags) = 0;
 
       /// @brief Set the output machine name.
-      void setOutputMachine( const std::string& machineName ) {
-        machine = machineName;
-      }
+      virtual void setOutputMachine(const std::string& machineName) = 0;
 
       /// @brief Set Preprocessor specific options
-      void setPhaseArgs(Phases phase, const std::vector<std::string>& opts) {
-        assert(phase <= LINKING && phase >= PREPROCESSING);
-        AdditionalArgs[phase] = opts;
-      }
+      virtual void setPhaseArgs(Phases phase, const StringVector& opts) = 0; 
 
       /// @brief Set Library Paths
-      void setLibraryPaths(const std::vector<std::string>& paths) {
-        LibraryPaths = paths;
-      }
+      virtual void setLibraryPaths(const StringVector& paths) = 0;
 
       /// @brief Set the list of library paths to be searched for
       /// libraries.
-      void addLibraryPath( const std::string& libPath ) {
-        LibraryPaths.push_back(libPath);
-      }
+      virtual void addLibraryPath( const sys::Path& libPath )  = 0;
 
     /// @}
-    /// @name Functions
-    /// @{
-    private:
-      Action* GetAction(ConfigData* cd, const std::string& input, 
-                       const std::string& output, Phases phase );
-
-      bool DoAction(Action* a);
-
-      std::string GetPathForLinkageItem(const std::string& link_item,
-                                        const std::string& dir);
-
-      bool ProcessLinkageItem(const std::string& link_item,
-                              SetVector<std::string>& set,
-                              std::string& err);
-
-    /// @}
-    /// @name Data
-    /// @{
-    private:
-      ConfigDataProvider* cdp;      ///< Where we get configuration data from
-      Phases finalPhase;            ///< The final phase of compilation
-      OptimizationLevels optLevel;  ///< The optimization level to apply
-      bool isDryRun;                ///< Prevent actions ?
-      bool isVerbose;               ///< Print actions?
-      bool isDebug;                 ///< Print lotsa debug info?
-      bool timeActions;             ///< Time the actions executed ?
-      bool timePasses;              ///< Time each pass and print timing ?
-      bool showStats;               ///< Show gathered statistics ?
-      bool emitRawCode;             ///< Emit Raw (unoptimized) code?
-      bool emitNativeCode;          ///< Emit native code instead of bytecode?
-      bool keepTemps;               ///< Keep temporary files?
-      std::string machine;          ///< Target machine name
-      StringVector LibraryPaths;    ///< -L options
-      StringTable  AdditionalArgs;  ///< The -Txyz options
-      std::string TempDir;          ///< Name of the temporary directory.
-
-    /// @}
-
   };
 }
 


Index: llvm/tools/llvmc/ConfigLexer.h
diff -u llvm/tools/llvmc/ConfigLexer.h:1.5 llvm/tools/llvmc/ConfigLexer.h:1.6
--- llvm/tools/llvmc/ConfigLexer.h:1.5	Tue Aug 24 08:59:35 2004
+++ llvm/tools/llvmc/ConfigLexer.h	Sun Aug 29 14:26:56 2004
@@ -57,6 +57,7 @@
   COMMAND,      ///< The name "command" (and variants)
   EQUALS,       ///< The equals sign, =
   FALSETOK,     ///< A boolean false value (false/no/off)
+  FORCE_SUBST,  ///< The substitution item %force%
   IN_SUBST,     ///< The substitution item %in%
   INTEGER,      ///< An integer 
   LANG,         ///< The name "lang" (and variants)
@@ -85,6 +86,7 @@
   TRANSLATES,   ///< The name "translates" (and variants)
   TRANSLATOR,   ///< The name "translator" (and variants)
   TRUETOK,      ///< A boolean true value (true/yes/on)
+  VERBOSE_SUBST,///< The substitution item %verbose%
   VERSION,      ///< The name "version" (and variants)
 };
 


Index: llvm/tools/llvmc/ConfigLexer.l
diff -u llvm/tools/llvmc/ConfigLexer.l:1.6 llvm/tools/llvmc/ConfigLexer.l:1.7
--- llvm/tools/llvmc/ConfigLexer.l:1.6	Tue Aug 24 08:58:37 2004
+++ llvm/tools/llvmc/ConfigLexer.l	Sun Aug 29 14:26:56 2004
@@ -160,12 +160,14 @@
 {LINKER}        { return handleNameContext(LINKER); }
 
 %args%          { return handleSubstitution(ARGS_SUBST); }
+%force%         { return handleSubstitution(FORCE_SUBST); }
 %in%            { return handleSubstitution(IN_SUBST); }
+%opt%           { return handleSubstitution(OPT_SUBST); }
 %out%           { return handleSubstitution(OUT_SUBST); }
-%time%          { return handleSubstitution(TIME_SUBST); }
 %stats%         { return handleSubstitution(STATS_SUBST); }
-%opt%           { return handleSubstitution(OPT_SUBST); }
 %target%        { return handleSubstitution(TARGET_SUBST); }
+%time%          { return handleSubstitution(TIME_SUBST); }
+%verbose%       { return handleSubstitution(VERBOSE_SUBST); }
 {BadSubst}      { YY_FATAL_ERROR("Invalid substitution token"); }
 
 {Assembly}      { return handleValueContext(ASSEMBLY); }


Index: llvm/tools/llvmc/Configuration.cpp
diff -u llvm/tools/llvmc/Configuration.cpp:1.10 llvm/tools/llvmc/Configuration.cpp:1.11
--- llvm/tools/llvmc/Configuration.cpp:1.10	Tue Aug 24 09:03:23 2004
+++ llvm/tools/llvmc/Configuration.cpp	Sun Aug 29 14:26:56 2004
@@ -90,19 +90,19 @@
     InputProvider* provider;
     CompilerDriver::ConfigData* confDat;
 
-    int next() { 
+    inline int next() { 
       token = Configlex();
       if (DumpTokens) 
         std::cerr << token << "\n";
       return token;
     }
 
-    bool next_is_real() { 
+    inline bool next_is_real() { 
       next();
       return (token != EOLTOK) && (token != ERRORTOK) && (token != 0);
     }
 
-    void eatLineRemnant() {
+    inline void eatLineRemnant() {
       while (next_is_real()) ;
     }
 
@@ -162,6 +162,8 @@
         case STATS_SUBST:       optList.push_back("%stats%"); break;
         case OPT_SUBST:         optList.push_back("%opt%"); break;
         case TARGET_SUBST:      optList.push_back("%target%"); break;
+        case FORCE_SUBST:       optList.push_back("%force%"); break;
+        case VERBOSE_SUBST:     optList.push_back("%verbose%"); break;
         default:
           return false;
       }
@@ -229,7 +231,7 @@
           action.args.clear();
         } else {
           if (token == STRING || token == OPTION) {
-            action.program = ConfigLexerState.StringVal;
+            action.program.set_file(ConfigLexerState.StringVal);
           } else {
             error("Expecting a program name");
           }
@@ -415,42 +417,46 @@
 CompilerDriver::ConfigData*
 LLVMC_ConfigDataProvider::ReadConfigData(const std::string& ftype) {
   CompilerDriver::ConfigData* result = 0;
-  std::string dir_name;
-  if (configDir.empty()) {
+  sys::Path confFile;
+  if (configDir.is_empty()) {
     // Try the environment variable
     const char* conf = getenv("LLVM_CONFIG_DIR");
     if (conf) {
-      dir_name = conf;
-      dir_name += "/";
-      if (!::sys::FileIsReadable(dir_name + ftype))
+      confFile.set_directory(conf);
+      confFile.append_file(ftype);
+      if (!confFile.readable())
         throw "Configuration file for '" + ftype + "' is not available.";
     } else {
       // Try the user's home directory
-      const char* home = getenv("HOME");
-      if (home) {
-        dir_name = home;
-        dir_name += "/.llvm/etc/";
-        if (!::sys::FileIsReadable(dir_name + ftype)) {
-          // Okay, try the LLVM installation directory
-          dir_name = LLVM_ETCDIR;
-          dir_name += "/";
-          if (!::sys::FileIsReadable(dir_name + ftype)) {
-            // Okay, try the "standard" place
-            dir_name = "/etc/llvm/";
-            if (!::sys::FileIsReadable(dir_name + ftype)) {
-              throw "Configuration file for '" + ftype + "' is not available.";
-            }
+      confFile = sys::Path::GetUserHomeDirectory();
+      if (!confFile.is_empty()) {
+        confFile.append_directory(".llvm");
+        confFile.append_directory("etc");
+        confFile.append_file(ftype);
+        if (!confFile.readable())
+          confFile.clear();
+      }
+      if (!confFile.is_empty()) {
+        // Okay, try the LLVM installation directory
+        confFile = sys::Path::GetLLVMConfigDir();
+        confFile.append_file(ftype);
+        if (!confFile.readable()) {
+          // Okay, try the "standard" place
+          confFile = sys::Path::GetLLVMDefaultConfigDir();
+          confFile.append_file(ftype);
+          if (!confFile.readable()) {
+            throw "Configuration file for '" + ftype + "' is not available.";
           }
         }
       }
     }
   } else {
-    dir_name = configDir + "/";
-    if (!::sys::FileIsReadable(dir_name + ftype)) {
+    confFile = configDir;
+    confFile.append_file(ftype);
+    if (!confFile.readable())
       throw "Configuration file for '" + ftype + "' is not available.";
-    }
   }
-  FileInputProvider fip( dir_name + ftype );
+  FileInputProvider fip( confFile.get() );
   if (!fip.okay()) {
     throw "Configuration file for '" + ftype + "' is not available.";
   }
@@ -459,13 +465,6 @@
   return result;
 }
 
-LLVMC_ConfigDataProvider::LLVMC_ConfigDataProvider() 
-  : Configurations() 
-  , configDir() 
-{
-  Configurations.clear();
-}
-
 LLVMC_ConfigDataProvider::~LLVMC_ConfigDataProvider()
 {
   ConfigDataMap::iterator cIt = Configurations.begin();
@@ -491,7 +490,7 @@
     // The configuration data doesn't exist, we have to go read it.
     result = ReadConfigData(filetype);
     // If we got one, cache it
-    if ( result != 0 )
+    if (result != 0)
       Configurations.insert(std::make_pair(filetype,result));
   }
   return result; // Might return 0


Index: llvm/tools/llvmc/Configuration.h
diff -u llvm/tools/llvmc/Configuration.h:1.3 llvm/tools/llvmc/Configuration.h:1.4
--- llvm/tools/llvmc/Configuration.h:1.3	Thu Aug 19 16:17:53 2004
+++ llvm/tools/llvmc/Configuration.h	Sun Aug 29 14:26:56 2004
@@ -29,7 +29,6 @@
     /// @name Constructor
     /// @{
     public:
-      LLVMC_ConfigDataProvider();
       virtual ~LLVMC_ConfigDataProvider();
 
     /// @name Methods
@@ -40,7 +39,9 @@
         ProvideConfigData(const std::string& filetype);
 
       /// @brief Allow the configuration directory to be set
-      virtual void setConfigDir(const std::string& dirName) { configDir = dirName; }
+      virtual void setConfigDir(const sys::Path& dirName) { 
+        configDir = dirName; 
+      }
 
     private:
       CompilerDriver::ConfigData* ReadConfigData(const std::string& ftype);
@@ -53,7 +54,7 @@
       typedef hash_map<std::string,CompilerDriver::ConfigData*,
           hash<std::string>,std::equal_to<std::string> > ConfigDataMap;
       ConfigDataMap Configurations; ///< The cache of configurations
-      std::string configDir;
+      sys::Path configDir;
     /// @}
   };
 }


Index: llvm/tools/llvmc/Makefile
diff -u llvm/tools/llvmc/Makefile:1.5 llvm/tools/llvmc/Makefile:1.6
--- llvm/tools/llvmc/Makefile:1.5	Tue Aug 24 09:04:07 2004
+++ llvm/tools/llvmc/Makefile	Sun Aug 29 14:26:56 2004
@@ -8,7 +8,7 @@
 ##===----------------------------------------------------------------------===##
 LEVEL = ../..
 TOOLNAME = llvmc
-USEDLIBS = bcreader vmcore support.a
+USEDLIBS = bcreader vmcore support.a LLVMsystem.a
 CONFIG_FILES = st ll
 
 include $(LEVEL)/Makefile.common


Index: llvm/tools/llvmc/llvmc.cpp
diff -u llvm/tools/llvmc/llvmc.cpp:1.10 llvm/tools/llvmc/llvmc.cpp:1.11
--- llvm/tools/llvmc/llvmc.cpp:1.10	Tue Aug 24 17:53:13 2004
+++ llvm/tools/llvmc/llvmc.cpp	Sun Aug 29 14:26:56 2004
@@ -108,6 +108,9 @@
 cl::opt<std::string> OutputFilename("o", 
   cl::desc("Override output filename"), cl::value_desc("filename"));
 
+cl::opt<bool> ForceOutput("f", cl::Optional, cl::init(false),
+  cl::desc("Force output files to be overridden"));
+
 cl::opt<std::string> OutputMachine("m", cl::Prefix,
   cl::desc("Specify a target machine"), cl::value_desc("machine"));
                                                                                                                                             
@@ -156,7 +159,7 @@
 static cl::opt<bool> PipeCommands("pipe", cl::Optional,
   cl::desc("Invoke sub-commands by linking input/output with pipes"));
 
-static cl::opt<bool> KeepTemporaries("keep-temps", cl::Optional,
+static cl::opt<bool> KeepTemps("keep-temps", cl::Optional,
   cl::desc("Don't delete the temporary files created during compilation"));
 
 //===------------------------------------------------------------------------===
@@ -199,15 +202,16 @@
 
 /// @brief The main program for llvmc
 int main(int argc, char **argv) {
+  // Make sure we print stack trace if we get bad signals
+  sys::PrintStackTraceOnErrorSignal();
+
   try {
-    // Make sure we print stack trace if we get bad signals
-    PrintStackTraceOnErrorSignal();
 
     // Parse the command line options
     cl::ParseCommandLineOptions(argc, argv, 
-      " LLVM Compilation Driver (llvmc)\n\n"
+      " LLVM Compiler Driver (llvmc)\n\n"
       "  This program provides easy invocation of the LLVM tool set\n"
-      "  and source language compiler tools.\n"
+      "  and other compiler tools.\n"
     );
 
     // Deal with unimplemented options.
@@ -220,13 +224,12 @@
       else
         throw "An output file must be specified. Please use the -o option";
 
-
     // Construct the ConfigDataProvider object
     LLVMC_ConfigDataProvider Provider;
-    Provider.setConfigDir(ConfigDir);
+    Provider.setConfigDir(sys::Path(ConfigDir));
 
     // Construct the CompilerDriver object
-    CompilerDriver CD(Provider);
+    CompilerDriver* CD = CompilerDriver::Get(Provider);
 
     // If the LLVM_LIB_SEARCH_PATH environment variable is
     // set, append it to the list of places to search for libraries
@@ -234,30 +237,37 @@
     if (!srchPath.empty())
       LibPaths.push_back(srchPath);
 
-    // Configure the driver based on options
-    CD.setVerbose(Verbose);
-    CD.setDebug(Debug);
-    CD.setDryRun(DryRun);
-    CD.setFinalPhase(FinalPhase);
-    CD.setOptimization(OptLevel);
-    CD.setOutputMachine(OutputMachine);
-    CD.setEmitNativeCode(Native);
-    CD.setEmitRawCode(EmitRawCode);
-    CD.setTimeActions(TimeActions);
-    CD.setTimePasses(TimePassesIsEnabled);
-    CD.setShowStats(ShowStats);
-    CD.setKeepTemporaries(KeepTemporaries);
-    CD.setLibraryPaths(LibPaths);
+    // Set the driver flags based on command line options
+    unsigned flags = 0;
+    if (Verbose)        flags |= CompilerDriver::VERBOSE_FLAG;
+    if (Debug)          flags |= CompilerDriver::DEBUG_FLAG;
+    if (DryRun)         flags |= CompilerDriver::DRY_RUN_FLAG;
+    if (ForceOutput)    flags |= CompilerDriver::FORCE_FLAG;
+    if (Native)         flags |= CompilerDriver::EMIT_NATIVE_FLAG;
+    if (EmitRawCode)    flags |= CompilerDriver::EMIT_RAW_FLAG;
+    if (KeepTemps)      flags |= CompilerDriver::KEEP_TEMPS_FLAG;
+    if (ShowStats)      flags |= CompilerDriver::SHOW_STATS_FLAG;
+    if (TimeActions)    flags |= CompilerDriver::TIME_ACTIONS_FLAG;
+    if (TimePassesIsEnabled) flags |= CompilerDriver::TIME_PASSES_FLAG;
+    CD->setDriverFlags(flags);
+
+    // Specify requred parameters
+    CD->setFinalPhase(FinalPhase);
+    CD->setOptimization(OptLevel);
+    CD->setOutputMachine(OutputMachine);
+    CD->setLibraryPaths(LibPaths);
+
+    // Provide additional tool arguments
     if (!PreprocessorToolOpts.empty())
-        CD.setPhaseArgs(CompilerDriver::PREPROCESSING, PreprocessorToolOpts);
+        CD->setPhaseArgs(CompilerDriver::PREPROCESSING, PreprocessorToolOpts);
     if (!TranslatorToolOpts.empty())
-        CD.setPhaseArgs(CompilerDriver::TRANSLATION, TranslatorToolOpts);
+        CD->setPhaseArgs(CompilerDriver::TRANSLATION, TranslatorToolOpts);
     if (!OptimizerToolOpts.empty())
-        CD.setPhaseArgs(CompilerDriver::OPTIMIZATION, OptimizerToolOpts);
+        CD->setPhaseArgs(CompilerDriver::OPTIMIZATION, OptimizerToolOpts);
     if (!AssemblerToolOpts.empty())
-        CD.setPhaseArgs(CompilerDriver::ASSEMBLY,AssemblerToolOpts);
+        CD->setPhaseArgs(CompilerDriver::ASSEMBLY,AssemblerToolOpts);
     if (!LinkerToolOpts.empty())
-        CD.setPhaseArgs(CompilerDriver::LINKING, LinkerToolOpts);
+        CD->setPhaseArgs(CompilerDriver::LINKING, LinkerToolOpts);
 
     // Prepare the list of files to be compiled by the CompilerDriver.
     CompilerDriver::InputList InpList;
@@ -288,7 +298,7 @@
     }
 
     // Tell the driver to do its thing
-    int result = CD.execute(InpList,OutputFilename);
+    int result = CD->execute(InpList,sys::Path(OutputFilename));
     if (result != 0) {
       throw "Error executing actions. Terminated.\n";
       return result;


Index: llvm/tools/llvmc/st
diff -u llvm/tools/llvmc/st:1.5 llvm/tools/llvmc/st:1.6
--- llvm/tools/llvmc/st:1.5	Tue Aug 24 09:24:14 2004
+++ llvm/tools/llvmc/st	Sun Aug 29 14:26:56 2004
@@ -34,7 +34,7 @@
   # To compile stacker source, we just run the stacker
   # compiler with a default stack size of 2048 entries.
   translator.command=stkrc -s 2048 %in% -o %out% %time% \
-    %stats% %args%
+    %stats% %force% %args%
 
   # stkrc doesn't preprocess but we set this to true so
   # that we don't run the cp command by default.
@@ -52,7 +52,7 @@
   
   # For optimization, we use the LLVM "opt" program
   optimizer.command=opt %in% -o %out% %opt% %time% %stats% \
-    %args%
+    %force% %args%
 
   optimizer.required = true
 






More information about the llvm-commits mailing list