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

Reid Spencer reid at x10sys.com
Wed Aug 18 21:49:58 PDT 2004



Changes in directory llvm/tools/llvmc:

CompilerDriver.cpp updated: 1.5 -> 1.6
CompilerDriver.h updated: 1.5 -> 1.6
ConfigData.cpp updated: 1.3 -> 1.4
ConfigLexer.h updated: 1.2 -> 1.3
ConfigLexer.l updated: 1.2 -> 1.3
Makefile updated: 1.2 -> 1.3
ll updated: 1.2 -> 1.3
llvmc.cpp updated: 1.5 -> 1.6
st updated: 1.1 -> 1.2
---
Log message:

Implement many new features for llvmc. This is the first version that will
actually execute actions and it is been shown to optimize a Stacker program


---
Diffs of the changes:  (+655 -411)

Index: llvm/tools/llvmc/CompilerDriver.cpp
diff -u llvm/tools/llvmc/CompilerDriver.cpp:1.5 llvm/tools/llvmc/CompilerDriver.cpp:1.6
--- llvm/tools/llvmc/CompilerDriver.cpp:1.5	Mon Aug 16 02:06:38 2004
+++ llvm/tools/llvmc/CompilerDriver.cpp	Wed Aug 18 23:49:47 2004
@@ -14,6 +14,7 @@
 
 #include "CompilerDriver.h"
 #include "ConfigLexer.h"
+#include "Support/SystemUtils.h"
 #include <iostream>
 
 using namespace llvm;
@@ -33,27 +34,25 @@
 
   const char OutputSuffix[] = ".o";
 
-  void WriteAction(CompilerDriver::Action* a ) {
-    std::cerr << a->program;
-    std::vector<std::string>::iterator I = a->args.begin();
-    while (I != a->args.end()) {
+  void WriteAction(CompilerDriver::Action* action ) {
+    std::cerr << action->program;
+    std::vector<std::string>::iterator I = action->args.begin();
+    while (I != action->args.end()) {
       std::cerr << " " + *I;
       ++I;
     }
     std::cerr << "\n";
   }
 
-  void DumpAction(CompilerDriver::Action* a) {
-    std::cerr << "command = " << a->program;
-    std::vector<std::string>::iterator I = a->args.begin();
-    while (I != a->args.end()) {
+  void DumpAction(CompilerDriver::Action* action) {
+    std::cerr << "command = " << action->program;
+    std::vector<std::string>::iterator I = action->args.begin();
+    while (I != action->args.end()) {
       std::cerr << " " + *I;
       ++I;
     }
     std::cerr << "\n";
-    std::cerr << "flags = " << a->flags << "\n";
-    std::cerr << "inputAt = " << a->inputAt << "\n";
-    std::cerr << "outputAt = " << a->outputAt << "\n";
+    std::cerr << "flags = " << action->flags << "\n";
   }
 
   void DumpConfigData(CompilerDriver::ConfigData* cd, const std::string& type ){
@@ -79,11 +78,57 @@
   /// This specifies the passes to run for OPT_FAST_COMPILE (-O1)
   /// which should reduce the volume of code and make compilation
   /// faster. This is also safe on any llvm module. 
-  static const char* DefaultOptimizations[] = {
-    "-simplifycfg", "-mem2reg", "-mergereturn", "-instcombine",
+  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 {
+  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--;
+      }
+    }
+
+    // If we fell out, we ran out of directories in PATH to search, return failure
+    return "";
+  }
+}
+
 CompilerDriver::CompilerDriver(ConfigDataProvider& confDatProv )
   : cdp(&confDatProv)
   , finalPhase(LINKING)
@@ -94,46 +139,43 @@
   , timeActions(false)
   , emitRawCode(false)
   , emitNativeCode(false)
+  , keepTemps(false)
   , machine()
   , LibraryPaths()
-  , PreprocessorOptions()
-  , TranslatorOptions()
-  , OptimizerOptions()
-  , AssemblerOptions()
-  , LinkerOptions()
+  , 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);
 }
 
 CompilerDriver::~CompilerDriver() {
   cdp = 0;
   LibraryPaths.clear();
-  PreprocessorOptions.clear();
-  TranslatorOptions.clear();
-  OptimizerOptions.clear();
-  AssemblerOptions.clear();
-  LinkerOptions.clear();
+  AdditionalArgs.clear();
 }
 
-void CompilerDriver::error( const std::string& errmsg ) {
-  std::cerr << "Error: " << errmsg << ".\n";
-  exit(1);
+CompilerDriver::ConfigData::ConfigData()
+  : langName()
+  , PreProcessor()
+  , Translator()
+  , Optimizer()
+  , Assembler()
+  , Linker()
+{
+  StringVector emptyVec;
+  for (unsigned i = 0; i < NUM_PHASES; ++i)
+    opts.push_back(emptyVec);
 }
 
-inline std::string makeDashO(CompilerDriver::OptimizationLevels lev) {
-  if (lev == CompilerDriver::OPT_NONE) return "";
-  std::string result("-O");
-  switch (lev) {
-    case CompilerDriver::OPT_FAST_COMPILE :     result.append("1"); break;
-    case CompilerDriver::OPT_SIMPLE:            result.append("2"); break;
-    case CompilerDriver::OPT_AGGRESSIVE:        result.append("3"); break;
-    case CompilerDriver::OPT_LINK_TIME:         result.append("4"); break;
-    case CompilerDriver::OPT_AGGRESSIVE_LINK_TIME: result.append("5"); break;
-    default:                    assert(!"Invalid optimization level!");
-  }
-  return result;
+void CompilerDriver::error( const std::string& errmsg ) {
+  std::cerr << "llvmc: Error: " << errmsg << ".\n";
+  exit(1);
 }
 
 CompilerDriver::Action* CompilerDriver::GetAction(ConfigData* cd, 
@@ -141,7 +183,9 @@
                           const std::string& output,
                           Phases phase)
 {
-  Action* pat = 0;
+  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;
@@ -155,74 +199,93 @@
   }
   assert(pat != 0 && "Invalid command pattern");
 
-  // Create the resulting action
-  Action* a = new Action(*pat);
+  // 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 (pat->isSet(GROKS_DASH_O)) {
+            if (optLevel != OPT_NONE) {
+              std::string optArg("-O");
+              switch (optLevel) {
+                case OPT_FAST_COMPILE : optArg.append("1"); break;
+                case OPT_SIMPLE:        optArg.append("2"); break;
+                case OPT_AGGRESSIVE:    optArg.append("3"); break;
+                case OPT_LINK_TIME:     optArg.append("4"); break;
+                case OPT_AGGRESSIVE_LINK_TIME: optArg.append("5"); break;
+                default : 
+                  assert(!"Invalid optimization argument!");
+                  optArg.append("0"); 
+                  break;
+              }
+              action->args.push_back(optArg);
+            }
+          } else {
+            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("Invalid substitution name");
+      }
+    } else {
+      // Its not a substitution, just put it in the action
+      action->args.push_back(*PI);
+    }
+    PI++;
+  }
 
-  // Replace the substitution arguments
-  if (pat->inputAt < a->args.size())
-    a->args[pat->inputAt] = input;
-  if (pat->outputAt < a->args.size())
-    a->args[pat->outputAt] = output;
+  // Get specific options for each kind of action type
+  StringVector& args = AdditionalArgs[phase];
 
-  // Insert specific options for each kind of action type
-  switch (phase) {
-    case PREPROCESSING:
-      a->args.insert(a->args.begin(), PreprocessorOptions.begin(), 
-                    PreprocessorOptions.end());
-      break;
-    case TRANSLATION:   
-      a->args.insert(a->args.begin(), TranslatorOptions.begin(), 
-                    TranslatorOptions.end());
-      if (a->isSet(GROKS_DASH_O_FLAG))
-        a->args.insert(a->args.begin(), makeDashO(optLevel));
-      else if (a->isSet(GROKS_O10N_FLAG))
-        a->args.insert(a->args.begin(), cd->opts[optLevel].begin(),
-            cd->opts[optLevel].end());
-      break;
-    case OPTIMIZATION:  
-      a->args.insert(a->args.begin(), OptimizerOptions.begin(), 
-                    OptimizerOptions.end());
-      if (a->isSet(GROKS_DASH_O_FLAG))
-        a->args.insert(a->args.begin(), makeDashO(optLevel));
-      else if (a->isSet(GROKS_O10N_FLAG))
-        a->args.insert(a->args.begin(), cd->opts[optLevel].begin(),
-            cd->opts[optLevel].end());
-      break;
-    case ASSEMBLY:      
-      a->args.insert(a->args.begin(), AssemblerOptions.begin(), 
-                    AssemblerOptions.end());
-      break;
-    case LINKING:       
-      a->args.insert(a->args.begin(), LinkerOptions.begin(), 
-                    LinkerOptions.end());
-      if (a->isSet(GROKS_DASH_O_FLAG))
-        a->args.insert(a->args.begin(), makeDashO(optLevel));
-      else if (a->isSet(GROKS_O10N_FLAG))
-        a->args.insert(a->args.begin(), cd->opts[optLevel].begin(),
-            cd->opts[optLevel].end());
-      break;
-    default:
-      assert(!"Invalid driver phase!");
-      break;
-  }
-  return a;
+  // Add specific options for each kind of action type
+  action->args.insert(action->args.end(), args.begin(), args.end());
+
+  // Finally, we're done
+  return action;
 }
 
-void CompilerDriver::DoAction(Action*a)
-{
+bool CompilerDriver::DoAction(Action*action) {
+  assert(action != 0 && "Invalid Action!");
   if (isVerbose)
-    WriteAction(a);
+    WriteAction(action);
   if (!isDryRun) {
-    std::cerr << "execve(\"" << a->program << "\",[\"";
-    std::vector<std::string>::iterator I = a->args.begin();
-    while (I != a->args.end()) {
-      std::cerr << *I;
-      ++I;
-      if (I != a->args.end())
-        std::cerr << "\",\"";
-    }
-    std::cerr << "\"],ENV);\n";
+    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;
 }
 
 int CompilerDriver::execute(const InputList& InpList, 
@@ -259,15 +322,11 @@
   std::vector<Action*> actions;
 
   // Create a temporary directory for our temporary files
-  char temp_name[64];
-  strcpy(temp_name,"/tmp/llvm_XXXXXX");
-  if (0 == mkdtemp(temp_name))
-      error("Can't create temporary directory");
-  std::string TempDir(temp_name);
-  std::string TempPreprocessorOut(TempDir + "/preproc.tmp");
-  std::string TempTranslatorOut(TempDir + "/trans.tmp");
-  std::string TempOptimizerOut(TempDir + "/opt.tmp");
-  std::string TempAssemblerOut(TempDir + "/asm.tmp");
+  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
@@ -312,76 +371,137 @@
       OutFile = Output;
     }
 
+    // Initialize the input file
+    std::string InFile(I->first);
+
     // PRE-PROCESSING PHASE
-    Action& a = cd->PreProcessor;
+    Action& action = cd->PreProcessor;
 
     // Get the preprocessing action, if needed, or error if appropriate
-    if (!a.program.empty()) {
-      if (a.isSet(REQUIRED_FLAG) || finalPhase == PREPROCESSING) {
-        actions.push_back(GetAction(cd,I->first,
-              TempPreprocessorOut,PREPROCESSING));
+    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;
+        }
       }
     } else if (finalPhase == PREPROCESSING) {
       error(cd->langName + " does not support pre-processing");
-    } else if (a.isSet(REQUIRED_FLAG)) {
+    } 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; };
 
     /// TRANSLATION PHASE
-    a = cd->Translator;
+    action = cd->Translator;
 
     // Get the translation action, if needed, or error if appropriate
-    if (!a.program.empty()) {
-      if (a.isSet(REQUIRED_FLAG) || finalPhase == TRANSLATION) {
-        actions.push_back(GetAction(cd,I->first,TempTranslatorOut,TRANSLATION));
+    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;
+        }
+
+        // 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);
+        }
       }
     } else if (finalPhase == TRANSLATION) {
       error(cd->langName + " does not support translation");
-    } else if (a.isSet(REQUIRED_FLAG)) {
+    } 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; }
 
     /// OPTIMIZATION PHASE
-    a = cd->Optimizer;
+    action = cd->Optimizer;
 
     // Get the optimization action, if needed, or error if appropriate
-    if (!a.program.empty()) {
-      actions.push_back(GetAction(cd,I->first,TempOptimizerOut,OPTIMIZATION));
+    if (!action.program.empty() && !emitRawCode) {
+      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;
+        }
+        // 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);
+        }
+      }
     } else if (finalPhase == OPTIMIZATION) {
       error(cd->langName + " does not support optimization");
-    } else if (a.isSet(REQUIRED_FLAG)) {
+    } 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; }
 
+    /// ASSEMBLY PHASE
+    if (emitNativeCode) {
+      // We must cause native code to be generated
+    } else {
+    }
+      
+    // Go to next file to be processed
     ++I;
   }
 
   /// LINKING PHASE
+  if (emitNativeCode) {
+  } else {
+  }
 
   /// RUN THE ACTIONS
   std::vector<Action*>::iterator aIter = actions.begin();
   while (aIter != actions.end()) {
-    DoAction(*aIter);
+    if (!DoAction(*aIter))
+      error("Action failed");
     aIter++;
   }
 
-  // Cleanup files
-  CleanupTempFile(TempPreprocessorOut.c_str());
-  CleanupTempFile(TempTranslatorOut.c_str());
-  CleanupTempFile(TempOptimizerOut.c_str());
-
-  // Cleanup temporary directory we created
-  if (0 == access(TempDir.c_str(), F_OK | W_OK))
-    rmdir(TempDir.c_str());
+  if (!keepTemps) {
+    // Cleanup files
+    CleanupTempFile(TempPreprocessorOut.c_str());
+    CleanupTempFile(TempTranslatorOut.c_str());
+    CleanupTempFile(TempOptimizerOut.c_str());
+
+    // Cleanup temporary directory we created
+    if (0 == access(TempDir.c_str(), F_OK | W_OK))
+      rmdir(TempDir.c_str());
+  }
 
   return 0;
 }


Index: llvm/tools/llvmc/CompilerDriver.h
diff -u llvm/tools/llvmc/CompilerDriver.h:1.5 llvm/tools/llvmc/CompilerDriver.h:1.6
--- llvm/tools/llvmc/CompilerDriver.h:1.5	Mon Aug 16 02:06:38 2004
+++ llvm/tools/llvmc/CompilerDriver.h	Wed Aug 18 23:49:47 2004
@@ -32,13 +32,17 @@
       /// @brief A vector of strings, commonly used
       typedef std::vector<std::string> StringVector;
 
+      /// @brief A table of strings, indexed typically by Phases
+      typedef std::vector<StringVector> StringTable;
+
       /// @brief The phases of processing that llvmc understands
       enum Phases {
         PREPROCESSING, ///< Source language combining, filtering, substitution
         TRANSLATION,   ///< Translate source -> LLVM bytecode/assembly
         OPTIMIZATION,  ///< Optimize translation result 
-        LINKING,       ///< Link bytecode and native code
         ASSEMBLY,      ///< Convert program to executable
+        LINKING,       ///< Link bytecode and native code
+        NUM_PHASES     ///< Always last!
       };
 
       /// @brief The levels of optimization llvmc understands
@@ -56,9 +60,10 @@
         REQUIRED_FLAG        = 0x0001, ///< Should the action always be run?
         GROKS_DASH_O_FLAG    = 0x0002, ///< Understands the -On options?
         PREPROCESSES_FLAG    = 0x0004, ///< Does this action preprocess?
-        OPTIMIZES_FLAG       = 0x0008, ///< Does this action optimize?
-        GROKS_O10N_FLAG      = 0x0010, ///< Understands optimization options?
-        FLAGS_MASK           = 0x001F, ///< Union of all flags
+        TRANSLATES_FLAG      = 0x0008, ///< Does this action translate?
+        OPTIMIZES_FLAG       = 0x0010, ///< Does this action optimize?
+        OUTPUT_IS_ASM_FLAG   = 0x0020, ///< Action produces .ll files?
+        FLAGS_MASK           = 0x003F, ///< Union of all flags
       };
 
       /// This type is the input list to the CompilerDriver. It provides
@@ -73,25 +78,24 @@
       /// @brief A structure to hold the action data for a given source
       /// language.
       struct Action {
-        Action() : inputAt(0) , outputAt(0), flags(0) {}
+        Action() : flags(0) {}
         std::string program;   ///< The program to execve
         StringVector args;     ///< Arguments to the program
-        size_t inputAt;        ///< Argument index to insert input file
-        size_t outputAt;       ///< Argument index to insert output file
         unsigned flags;        ///< Action specific flags
         void set(unsigned fl ) { flags |= fl; }
         void clear(unsigned fl) { flags &= (FLAGS_MASK ^ fl); }
-        bool isSet(unsigned fl) { return flags&fl != 0; }
+        bool isSet(unsigned fl) { return (flags&fl) != 0; }
       };
 
       struct ConfigData {
-        std::string langName;           ///< The name of the source language 
-        std::vector<StringVector> opts; ///< The o10n options for each level
-        Action PreProcessor;            ///< PreProcessor command line
-        Action Translator;              ///< Translator command line
-        Action Optimizer;               ///< Optimizer command line
-        Action Assembler;               ///< Assembler command line
-        Action Linker;                  ///< Linker command line
+        ConfigData();
+        std::string langName;   ///< The name of the source language 
+        StringTable opts;       ///< The o10n options for each level
+        Action PreProcessor;    ///< PreProcessor command line
+        Action Translator;      ///< Translator command line
+        Action Optimizer;       ///< Optimizer command line
+        Action Assembler;       ///< Assembler command line
+        Action Linker;          ///< Linker command line
       };
 
       /// This pure virtual interface class defines the interface between the
@@ -148,6 +152,12 @@
       /// execution time of each action taken.
       void setTimeActions( bool TF ) { timeActions = TF; }
 
+      /// @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; }
@@ -155,34 +165,17 @@
       /// @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 output machine name.
       void setOutputMachine( const std::string& machineName ) {
         machine = machineName;
       }
 
       /// @brief Set Preprocessor specific options
-      void setPreprocessorOptions(const std::vector<std::string>& opts) {
-        PreprocessorOptions = opts;
-      }
-
-      /// @brief Set Translator specific options
-      void setTranslatorOptions(const std::vector<std::string>& opts) {
-        TranslatorOptions = opts;
-      }
-
-      /// @brief Set Optimizer specific options
-      void setOptimizerOptions(const std::vector<std::string>& opts) {
-        OptimizerOptions = opts;
-      }
-
-      /// @brief Set Assembler specific options
-      void setAssemblerOptions(const std::vector<std::string>& opts) {
-        AssemblerOptions = opts;
-      }
-
-      /// @brief Set Linker specific options
-      void setLinkerOptions(const std::vector<std::string>& opts) {
-        LinkerOptions = opts;
+      void setPhaseArgs(Phases phase, const std::vector<std::string>& opts) {
+        assert(phase <= LINKING && phase >= PREPROCESSING);
+        AdditionalArgs[phase] = opts;
       }
 
       /// @brief Set Library Paths
@@ -202,7 +195,7 @@
     private:
       Action* GetAction(ConfigData* cd, const std::string& input, 
                        const std::string& output, Phases phase );
-      void DoAction(Action* a);
+      bool DoAction(Action* a);
 
     /// @}
     /// @name Data
@@ -215,15 +208,15 @@
       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
-      std::vector<std::string> LibraryPaths;
-      std::vector<std::string> PreprocessorOptions; 
-      std::vector<std::string> TranslatorOptions;
-      std::vector<std::string> OptimizerOptions;
-      std::vector<std::string> AssemblerOptions;
-      std::vector<std::string> LinkerOptions;
+      StringVector LibraryPaths;    ///< -L options
+      StringTable  AdditionalArgs;  ///< The -Txyz options
+      std::string TempDir;          ///< Name of the temporary directory.
 
     /// @}
 


Index: llvm/tools/llvmc/ConfigData.cpp
diff -u llvm/tools/llvmc/ConfigData.cpp:1.3 llvm/tools/llvmc/ConfigData.cpp:1.4
--- llvm/tools/llvmc/ConfigData.cpp:1.3	Sun Aug 15 03:19:46 2004
+++ llvm/tools/llvmc/ConfigData.cpp	Wed Aug 18 23:49:47 2004
@@ -15,21 +15,21 @@
 #include "ConfigData.h"
 #include "ConfigLexer.h"
 #include "CompilerDriver.h"
+#include "Support/CommandLine.h"
 #include "Support/StringExtras.h"
 #include <iostream>
 #include <fstream>
 
 using namespace llvm;
 
-extern int ::Configlineno;
-
 namespace llvm {
-  ConfigLexerInfo ConfigLexerData;
+  ConfigLexerInfo ConfigLexerState;
   InputProvider* ConfigLexerInput = 0;
 
   InputProvider::~InputProvider() {}
   void InputProvider::error(const std::string& msg) {
-    std::cerr << name << ":" << Configlineno << ": Error: " << msg << "\n";
+    std::cerr << name << ":" << ConfigLexerState.lineNum << ": Error: " << 
+      msg << "\n";
     errCount++;
   }
 
@@ -65,17 +65,34 @@
       std::ifstream F;
   };
 
+  cl::opt<bool> DumpTokens("dump-tokens", cl::Optional, cl::Hidden, cl::init(false),
+    cl::desc("Dump lexical tokens (debug use only)."));
+
   struct Parser
   {
+    Parser() {
+      token = EOFTOK;
+      provider = 0;
+      confDat = 0;
+      ConfigLexerState.lineNum = 1;
+      ConfigLexerState.in_value = false;
+      ConfigLexerState.StringVal.clear();
+      ConfigLexerState.IntegerVal = 0;
+    };
+
     ConfigLexerTokens token;
     InputProvider* provider;
     CompilerDriver::ConfigData* confDat;
-    CompilerDriver::Action* action;
 
-    int next() { return token = Configlex(); }
+    int next() { 
+      token = Configlex();
+      if (DumpTokens) 
+        std::cerr << token << "\n";
+      return token;
+    }
 
     bool next_is_real() { 
-      token = Configlex(); 
+      next();
       return (token != EOLTOK) && (token != ERRORTOK) && (token != 0);
     }
 
@@ -96,7 +113,7 @@
           switch (token ) {
             case STRING :
             case OPTION : 
-              result += ConfigLexerData.StringVal + " ";
+              result += ConfigLexerState.StringVal + " ";
               break;
             default:
               error("Invalid name");
@@ -130,15 +147,32 @@
       return result;
     }
 
+    bool parseSubstitution(CompilerDriver::StringVector& optList) {
+      switch (token) {
+        case IN_SUBST:          optList.push_back("@in@"); break;
+        case OUT_SUBST:         optList.push_back("@out@"); break;
+        case TIME_SUBST:        optList.push_back("@time@"); break;
+        case STATS_SUBST:       optList.push_back("@stats@"); break;
+        case OPT_SUBST:         optList.push_back("@opt@"); break;
+        case TARGET_SUBST:      optList.push_back("@target@"); break;
+        default:
+          return false;
+      }
+      return true;
+    }
+
     void parseOptionList(CompilerDriver::StringVector& optList ) {
-      while (next_is_real()) {
-        if (token == STRING || token == OPTION)
-          optList.push_back(ConfigLexerData.StringVal);
-        else {
-          error("Expecting a program option", false);
-          break;
+      if (next() == EQUALS) {
+        while (next_is_real()) {
+          if (token == STRING || token == OPTION)
+            optList.push_back(ConfigLexerState.StringVal);
+          else if (!parseSubstitution(optList)) {
+            error("Expecting a program argument or substitution", false);
+            break;
+          }
         }
-      }
+      } else
+        error("Expecting '='");
     }
 
     void parseLang() {
@@ -174,25 +208,17 @@
           // no value (valid)
           action.program.clear();
           action.args.clear();
-          action.inputAt = 0;
-          action.outputAt = 0;
         } else {
           if (token == STRING || token == OPTION) {
-            action.program = ConfigLexerData.StringVal;
+            action.program = ConfigLexerState.StringVal;
           } else {
             error("Expecting a program name");
           }
           while (next_is_real()) {
             if (token == STRING || token == OPTION) {
-              action.args.push_back(ConfigLexerData.StringVal);
-            } else if (token == IN_SUBST) {
-              action.inputAt = action.args.size();
-              action.args.push_back("@in@");
-            } else if (token == OUT_SUBST) {
-              action.outputAt = action.args.size();
-              action.args.push_back("@out@");
-            } else {
-              error("Expecting a program argument", false);
+              action.args.push_back(ConfigLexerState.StringVal);
+            } else if (!parseSubstitution(action.args)) {
+              error("Expecting a program argument or substitution", false);
               break;
             }
           }
@@ -246,12 +272,13 @@
           else
             confDat->Translator.clear(CompilerDriver::GROKS_DASH_O_FLAG);
           break;
-        case GROKS_O10N:
+        case OUTPUT_IS_ASM:
           if (parseBoolean())
-            confDat->Translator.set(CompilerDriver::GROKS_O10N_FLAG);
+            confDat->Translator.set(CompilerDriver::OUTPUT_IS_ASM_FLAG);
           else
-            confDat->Translator.clear(CompilerDriver::GROKS_O10N_FLAG);
+            confDat->Translator.clear(CompilerDriver::OUTPUT_IS_ASM_FLAG);
           break;
+
         default:
           error("Expecting 'command', 'required', 'preprocesses', "
                 "'groks_dash_O' or 'optimizes'");
@@ -264,17 +291,29 @@
         case COMMAND:
           parseCommand(confDat->Optimizer);
           break;
+        case PREPROCESSES:
+          if (parseBoolean())
+            confDat->Optimizer.set(CompilerDriver::PREPROCESSES_FLAG);
+          else
+            confDat->Optimizer.clear(CompilerDriver::PREPROCESSES_FLAG);
+          break;
+        case TRANSLATES:
+          if (parseBoolean())
+            confDat->Optimizer.set(CompilerDriver::TRANSLATES_FLAG);
+          else
+            confDat->Optimizer.clear(CompilerDriver::TRANSLATES_FLAG);
+          break;
         case GROKS_DASH_O:
           if (parseBoolean())
             confDat->Optimizer.set(CompilerDriver::GROKS_DASH_O_FLAG);
           else
             confDat->Optimizer.clear(CompilerDriver::GROKS_DASH_O_FLAG);
           break;
-        case GROKS_O10N:
+        case OUTPUT_IS_ASM:
           if (parseBoolean())
-            confDat->Optimizer.set(CompilerDriver::GROKS_O10N_FLAG);
+            confDat->Translator.set(CompilerDriver::OUTPUT_IS_ASM_FLAG);
           else
-            confDat->Optimizer.clear(CompilerDriver::GROKS_O10N_FLAG);
+            confDat->Translator.clear(CompilerDriver::OUTPUT_IS_ASM_FLAG);
           break;
         default:
           error("Expecting 'command' or 'groks_dash_O'");
@@ -304,12 +343,6 @@
           else
             confDat->Linker.clear(CompilerDriver::GROKS_DASH_O_FLAG);
           break;
-        case GROKS_O10N:
-          if (parseBoolean())
-            confDat->Linker.set(CompilerDriver::GROKS_O10N_FLAG);
-          else
-            confDat->Linker.clear(CompilerDriver::GROKS_O10N_FLAG);
-          break;
         default:
           error("Expecting 'command'");
           break;
@@ -349,7 +382,6 @@
     p.token = EOFTOK;
     p.provider = &provider;
     p.confDat = &confDat;
-    p.action = 0;
     p.parseFile();
   }
 }


Index: llvm/tools/llvmc/ConfigLexer.h
diff -u llvm/tools/llvmc/ConfigLexer.h:1.2 llvm/tools/llvmc/ConfigLexer.h:1.3
--- llvm/tools/llvmc/ConfigLexer.h:1.2	Sun Aug 15 03:19:46 2004
+++ llvm/tools/llvmc/ConfigLexer.h	Wed Aug 18 23:49:47 2004
@@ -22,9 +22,11 @@
 {
   int64_t     IntegerVal;
   std::string StringVal;
+  bool in_value;
+  unsigned lineNum;
 };
 
-extern ConfigLexerInfo ConfigLexerData;
+extern ConfigLexerInfo ConfigLexerState;
 
 class InputProvider {
   public:
@@ -57,6 +59,10 @@
   STRING,       ///< A quoted string
   IN_SUBST,     ///< The input substitution item @in@
   OUT_SUBST,    ///< The output substitution item @out@
+  STATS_SUBST,  ///< The stats substitution item @stats@
+  TIME_SUBST,   ///< The substitution item @time@
+  OPT_SUBST,    ///< The substitution item @opt@
+  TARGET_SUBST, ///< The substitition item @target@
   LANG,         ///< The item "lang" (and case variants)
   PREPROCESSOR, ///< The item "preprocessor" (and case variants)
   TRANSLATOR,   ///< The item "translator" (and case variants)
@@ -67,9 +73,10 @@
   REQUIRED,     ///< The item "required" (and case variants)
   COMMAND,      ///< The item "command" (and case variants)
   PREPROCESSES, ///< The item "preprocesses" (and case variants)
-  GROKS_DASH_O, ///< The item "groks_dash_O" (and case variants)
-  GROKS_O10N,   ///< The item "groks_optimization" (and case variants)
+  TRANSLATES,   ///< The item "translates" (and case variants)
   OPTIMIZES,    ///< The item "optimizes" (and case variants)
+  GROKS_DASH_O, ///< The item "groks_dash_O" (and case variants)
+  OUTPUT_IS_ASM,///< The item "outut_is_asm" (and case variants)
   OPT1,         ///< The item "opt1" (and case variants)
   OPT2,         ///< The item "opt2" (and case variants)
   OPT3,         ///< The item "opt3" (and case variants)


Index: llvm/tools/llvmc/ConfigLexer.l
diff -u llvm/tools/llvmc/ConfigLexer.l:1.2 llvm/tools/llvmc/ConfigLexer.l:1.3
--- llvm/tools/llvmc/ConfigLexer.l:1.2	Sun Aug 15 03:19:46 2004
+++ llvm/tools/llvmc/ConfigLexer.l	Wed Aug 18 23:49:47 2004
@@ -14,7 +14,6 @@
 
 
 %option prefix="Config"
-%option yylineno
 %option nostdinit
 %option never-interactive
 %option batch
@@ -23,9 +22,9 @@
 %option 8bit
 %option outfile="ConfigLexer.cpp"
 %option ecs
-%option noreject
 %option noyymore
-%array
+%option noreject
+%pointer
 
 %{
 
@@ -38,53 +37,73 @@
     if (result == 0 ) result = YY_NULL; \
   }
 
+#define YY_FATAL_ERROR(msg) \
+  { \
+    assert(ConfigLexerInput != 0 && "Oops"); \
+    ConfigLexerInput->error(msg); \
+  }
+
 #define YY_DECL ConfigLexerTokens llvm::Configlex()
 
 #define yyterminate() { return EOFTOK; }
 
 using namespace llvm;
 
-/* Conversion of text ints to binary */
-static int64_t IntToVal(const char *Buffer) {
-  int64_t Result = 0;
-  for (; *Buffer; Buffer++) {
-    int64_t OldRes = Result;
-    Result *= 10;
-    Result += *Buffer-'0';
+inline llvm::ConfigLexerTokens 
+handleContext(const char* tokenText, llvm::ConfigLexerTokens token) {
+  if (ConfigLexerState.in_value) {
+    ConfigLexerState.StringVal = tokenText;
+    return OPTION;
   }
-  return Result;
+  return token;
 }
 
-bool in_value = false;
+inline llvm::ConfigLexerTokens 
+handleSubstitution(llvm::ConfigLexerTokens token) {
+  if (ConfigLexerState.in_value) 
+    return token;
+  YY_FATAL_ERROR("Substitition tokens not allowed in names" ); 
+  return ERRORTOK;
+};
+
+inline llvm::ConfigLexerTokens handleBoolean(llvm::ConfigLexerTokens token) {
+  if (ConfigLexerState.in_value)
+    return token;
+  YY_FATAL_ERROR("Boolean values not allowed in names");
+  return ERRORTOK;
+}
 
 %}
 
-LANG            lang|Lang|LANG
-PREPROCESSOR    preprocessor|PreProcessor|PREPROCESSOR
-TRANSLATOR      translator|Translator|TRANSLATOR
-OPTIMIZER       optimizer|Optimizer|OPTIMIZER
 ASSEMBLER       assembler|Assembler|ASSEMBLER
-LINKER          linker|Linker|LINKER
-NAME            name|Name|NAME
-REQUIRED        required|Required|REQUIRED
+BadSubst        \@[^iots][a-zA-Z]\@
 COMMAND         command|Command|COMMAND
-PREPROCESSES    preprocesses|PreProcesses|PREPROCESSES
+Comment         \#[^\n]*\n
+NewLine         \n
+Eq              \=
+EscNewLine      \\\n
 GROKS_DASH_O    groks_dash_O|Groks_Dash_O|GROKS_DASH_O
-GROKS_O10N      groks_optimization|Groks_Optimization|GROKS_OPTIMIZATION
-OPTIMIZES       optimizes|Optimizes|OPTIMIZES
+LANG            lang|Lang|LANG
+LINKER          linker|Linker|LINKER
+NAME            name|Name|NAME
 OPT1            opt1|Opt1|OPT1
 OPT2            opt2|Opt2|OPT2
 OPT3            opt3|Opt3|OPT3
 OPT4            opt4|Opt4|OPT4
 OPT5            opt5|Opt5|OPT5
-Comment         \#[^\n]*
-NewLine         \n
-White           [ \t]*
-Option          [-A-Za-z0-9_:%+/\\|,]*
+OPTIMIZER       optimizer|Optimizer|OPTIMIZER
+OPTIMIZES       optimizes|Optimizes|OPTIMIZES
+Option          [-A-Za-z0-9_:%+/\\|,][-A-Za-z0-9_:%+/\\|,@]*
+OUTPUT_IS_ASM   output_is_asm|Output_Is_Asm|OUTPUT_IS_ASM
+PREPROCESSES    preprocesses|PreProcesses|PREPROCESSES
+PREPROCESSOR    preprocessor|PreProcessor|PREPROCESSOR
+REQUIRED        required|Required|REQUIRED
 Sep             \.
-Eq              \=
 String          \"[^\"]*\"
-Integer         [-+]?[0-9]+
+TRANSLATES      translates|Translates|TRANSLATES
+TRANSLATOR      translator|Translator|TRANSLATOR
+White           [ \t]*
+
 True            true|True|TRUE
 False           false|False|FALSE
 On              on|On|ON
@@ -94,64 +113,68 @@
 
 %%
 
-{NewLine}       { in_value = false; return EOLTOK; }
-{Eq}            { in_value = true; return EQUALS; }
-{Comment}       { /* Ignore comments */ }
 {White}         { /* Ignore whitespace */ }
 
-{LANG}          { if (in_value) { ConfigLexerData.StringVal = "lang"; 
-                    return OPTION;  } else return LANG; }
-{PREPROCESSOR}  { if (in_value) { ConfigLexerData.StringVal = "preprocessor";
-                    return OPTION; } else return PREPROCESSOR; }
-{TRANSLATOR}    { if (in_value) { ConfigLexerData.StringVal = "translator";
-                    return OPTION; } else return TRANSLATOR; }
-{OPTIMIZER}     { if (in_value) { ConfigLexerData.StringVal = "optimizer";
-                    return OPTION; } else return OPTIMIZER; }
-{ASSEMBLER}     { if (in_value) { ConfigLexerData.StringVal = "assembler";
-                    return OPTION; } else return ASSEMBLER; }
-{LINKER}        { if (in_value) { ConfigLexerData.StringVal = "linker";
-                    return OPTION; } else return LINKER; }
-{NAME}          { if (in_value) { ConfigLexerData.StringVal = "name";
-                    return OPTION; } else return NAME; }
-{REQUIRED}      { if (in_value) { ConfigLexerData.StringVal = "required";
-                    return OPTION; } else return REQUIRED; }
-{COMMAND}       { if (in_value) { ConfigLexerData.StringVal = "command";
-                    return OPTION; } else return COMMAND; }
-{PREPROCESSES}  { if (in_value) { ConfigLexerData.StringVal = "preprocesses";
-                    return OPTION; } else return PREPROCESSES; }
-{GROKS_DASH_O}  { if (in_value) { ConfigLexerData.StringVal = "groks_dash_O";
-                    return OPTION; } else return GROKS_DASH_O; }
-{GROKS_O10N}    { if (in_value) { ConfigLexerData.StringVal = 
-                    "groks_optimization"; return OPTION; } 
-                    else return GROKS_O10N; }
-{OPTIMIZES}     { if (in_value) { ConfigLexerData.StringVal = "optimizes";
-                    return OPTION; } else return OPTIMIZES; }
-{OPT1}          { if (in_value) { ConfigLexerData.StringVal = "opt1";
-                    return OPTION; } else return OPT1; }
-{OPT2}          { if (in_value) { ConfigLexerData.StringVal = "opt2";
-                    return OPTION; } else return OPT2; }
-{OPT3}          { if (in_value) { ConfigLexerData.StringVal = "opt3";
-                    return OPTION; } else return OPT3; }
-{OPT4}          { if (in_value) { ConfigLexerData.StringVal = "opt4";
-                    return OPTION; } else return OPT4; }
-{OPT5}          { if (in_value) { ConfigLexerData.StringVal = "opt5";
-                    return OPTION; } else return OPT5; }
- at in@            { if (in_value) return IN_SUBST; else return ERRORTOK;  }
- at out@           { if (in_value) return OUT_SUBST; else return ERRORTOK; }
-{True}          { if (in_value) return TRUETOK; else return ERRORTOK; }
-{On}            { if (in_value) return TRUETOK; else return ERRORTOK; }
-{Yes}           { if (in_value) return TRUETOK; else return ERRORTOK; }
-{False}         { if (in_value) return FALSETOK; else return ERRORTOK; }
-{Off}           { if (in_value) return FALSETOK; else return ERRORTOK; }
-{No}            { if (in_value) return FALSETOK; else return ERRORTOK; }
-
-{Option}        { ConfigLexerData.StringVal = yytext; return OPTION; }
-{Integer}       { ConfigLexerData.IntegerVal = IntToVal(yytext); return INTEGER; }
-{String}        { yytext[yyleng-1] = 0;          // nuke end quote
-                  ConfigLexerData.StringVal = yytext+1;  // Nuke start quote
+{Comment}       { /* Ignore comments */
+                  ConfigLexerState.in_value = false; 
+                  ConfigLexerState.lineNum++; 
+                  return EOLTOK; 
+                }
+
+{EscNewLine}    { ConfigLexerState.lineNum++; 
+                  /* Don't return EOLTOK! */
+                }
+
+{NewLine}       { ConfigLexerState.in_value = false; 
+                  ConfigLexerState.lineNum++; 
+                  return EOLTOK; 
+                }
+
+{Eq}            { ConfigLexerState.in_value = true; 
+                  return EQUALS; 
+                }
+
+{LANG}          { return handleContext("lang",LANG); }
+{PREPROCESSOR}  { return handleContext("preprocessor",PREPROCESSOR); }
+{TRANSLATOR}    { return handleContext("translator",TRANSLATOR); }
+{OPTIMIZER}     { return handleContext("optimizer",OPTIMIZER); }
+{ASSEMBLER}     { return handleContext("assembler",ASSEMBLER); }
+{LINKER}        { return handleContext("linker",LINKER); }
+{NAME}          { return handleContext("name",NAME); }
+{REQUIRED}      { return handleContext("required",REQUIRED); }
+{COMMAND}       { return handleContext("command",COMMAND); }
+{PREPROCESSES}  { return handleContext("preprocesses",PREPROCESSES); }
+{TRANSLATES}    { return handleContext("translates",TRANSLATES); }
+{OPTIMIZES}     { return handleContext("optimizes",OPTIMIZES); }
+{GROKS_DASH_O}  { return handleContext("groks_dash_O",GROKS_DASH_O); }
+{OUTPUT_IS_ASM} { return handleContext("output_ias_asm",OUTPUT_IS_ASM); }
+{OPT1}          { return handleContext("opt1",OPT1); }
+{OPT2}          { return handleContext("opt2",OPT2); }
+{OPT3}          { return handleContext("opt3",OPT3); }
+{OPT4}          { return handleContext("opt4",OPT4); }
+{OPT5}          { return handleContext("opt5",OPT5); }
+
+ at in@            { return handleSubstitution(IN_SUBST); }
+ at out@           { return handleSubstitution(OUT_SUBST); }
+ at time@          { return handleSubstitution(TIME_SUBST); }
+ at stats@         { return handleSubstitution(STATS_SUBST); }
+ at opt@           { return handleSubstitution(OPT_SUBST); }
+ at target@        { return handleSubstitution(TARGET_SUBST); }
+{BadSubst}      { YY_FATAL_ERROR("Invalid substitution token"); }
+{True}          { return handleBoolean(TRUETOK); }
+{On}            { return handleBoolean(TRUETOK); }
+{Yes}           { return handleBoolean(TRUETOK); }
+{False}         { return handleBoolean(FALSETOK); }
+{Off}           { return handleBoolean(FALSETOK); }
+{No}            { return handleBoolean(FALSETOK); }
+
+{Option}        { ConfigLexerState.StringVal = yytext; return OPTION; }
+{String}        { ConfigLexerState.StringVal = yytext+1;  // Nuke start quote
+                  ConfigLexerState.StringVal.erase(
+                  --ConfigLexerState.StringVal.end());
                   return STRING;
                 }
-{Sep}           { if (in_value) { ConfigLexerData.StringVal = yytext;
+{Sep}           { if (ConfigLexerState.in_value) { ConfigLexerState.StringVal = yytext;
                     return OPTION; } }
 
 


Index: llvm/tools/llvmc/Makefile
diff -u llvm/tools/llvmc/Makefile:1.2 llvm/tools/llvmc/Makefile:1.3
--- llvm/tools/llvmc/Makefile:1.2	Sun Aug 15 03:19:46 2004
+++ llvm/tools/llvmc/Makefile	Wed Aug 18 23:49:47 2004
@@ -8,6 +8,6 @@
 ##===----------------------------------------------------------------------===##
 LEVEL = ../..
 TOOLNAME = llvmc
-USEDLIBS = asmparser bcreader bcwriter vmcore support.a system.a
+USEDLIBS = support.a
 
 include $(LEVEL)/Makefile.common


Index: llvm/tools/llvmc/ll
diff -u llvm/tools/llvmc/ll:1.2 llvm/tools/llvmc/ll:1.3
--- llvm/tools/llvmc/ll:1.2	Mon Aug 16 02:06:13 2004
+++ llvm/tools/llvmc/ll	Wed Aug 18 23:49:47 2004
@@ -4,7 +4,6 @@
   preprocessor.required=false
   translator.command=llvm-as @in@ -o @out@
   translator.groks_dash_O=no
-  translator.groks_optimization=no
   translator.optimizes=no
   translator.preprocesses=true
   translator.required=TRUE


Index: llvm/tools/llvmc/llvmc.cpp
diff -u llvm/tools/llvmc/llvmc.cpp:1.5 llvm/tools/llvmc/llvmc.cpp:1.6
--- llvm/tools/llvmc/llvmc.cpp:1.5	Sun Aug 15 03:19:46 2004
+++ llvm/tools/llvmc/llvmc.cpp	Wed Aug 18 23:49:47 2004
@@ -26,7 +26,7 @@
 //===------------------------------------------------------------------------===
 //===          PHASE OPTIONS
 //===------------------------------------------------------------------------===
-static cl::opt<CompilerDriver::Phases> FinalPhase(
+cl::opt<CompilerDriver::Phases> FinalPhase(
   cl::desc("Choose final phase of compilation:"), 
   cl::init(CompilerDriver::LINKING),
   cl::values(
@@ -45,7 +45,7 @@
 //===------------------------------------------------------------------------===
 //===          OPTIMIZATION OPTIONS
 //===------------------------------------------------------------------------===
-static cl::opt<CompilerDriver::OptimizationLevels> OptLevel(
+cl::opt<CompilerDriver::OptimizationLevels> OptLevel(
   cl::desc("Choose level of optimization to apply:"),
   cl::init(CompilerDriver::OPT_FAST_COMPILE),
   cl::values(
@@ -69,23 +69,23 @@
 //===          TOOL OPTIONS
 //===------------------------------------------------------------------------===
 
-static cl::list<std::string> PreprocessorToolOpts("Tpre", cl::ZeroOrMore,
+cl::list<std::string> PreprocessorToolOpts("Tpre", cl::ZeroOrMore,
   cl::desc("Pass specific options to the pre-processor"), 
   cl::value_desc("option"));
 
-static cl::list<std::string> TranslatorToolOpts("Ttrn", cl::ZeroOrMore,
+cl::list<std::string> TranslatorToolOpts("Ttrn", cl::ZeroOrMore,
   cl::desc("Pass specific options to the assembler"),
   cl::value_desc("option"));
 
-static cl::list<std::string> AssemblerToolOpts("Tasm", cl::ZeroOrMore,
+cl::list<std::string> AssemblerToolOpts("Tasm", cl::ZeroOrMore,
   cl::desc("Pass specific options to the assembler"),
   cl::value_desc("option"));
 
-static cl::list<std::string> OptimizerToolOpts("Topt", cl::ZeroOrMore,
+cl::list<std::string> OptimizerToolOpts("Topt", cl::ZeroOrMore,
   cl::desc("Pass specific options to the optimizer"),
   cl::value_desc("option"));
 
-static cl::list<std::string> LinkerToolOpts("Tlnk", cl::ZeroOrMore,
+cl::list<std::string> LinkerToolOpts("Tlnk", cl::ZeroOrMore,
   cl::desc("Pass specific options to the linker"),
   cl::value_desc("option"));
 
@@ -93,10 +93,10 @@
 //===          INPUT OPTIONS
 //===------------------------------------------------------------------------===
 
-static cl::list<std::string> LibPaths("L", cl::Prefix,
+cl::list<std::string> LibPaths("L", cl::Prefix,
   cl::desc("Specify a library search path"), cl::value_desc("directory"));
                                                                                                                                             
-static cl::list<std::string> Libraries("l", cl::Prefix,
+cl::list<std::string> Libraries("l", cl::Prefix,
   cl::desc("Specify libraries to link to"), cl::value_desc("library prefix"));
 
 
@@ -104,40 +104,46 @@
 //===          OUTPUT OPTIONS
 //===------------------------------------------------------------------------===
 
-static cl::opt<std::string> OutputFilename("o", 
+cl::opt<std::string> OutputFilename("o", 
   cl::desc("Override output filename"), cl::value_desc("filename"));
 
-static cl::opt<std::string> OutputMachine("m", cl::Prefix,
+cl::opt<std::string> OutputMachine("m", cl::Prefix,
   cl::desc("Specify a target machine"), cl::value_desc("machine"));
                                                                                                                                             
-static cl::opt<bool> Native("native", cl::init(false),
+cl::opt<bool> Native("native", cl::init(false),
   cl::desc("Generative native object and executables instead of bytecode"));
 
 //===------------------------------------------------------------------------===
 //===          INFORMATION OPTIONS
 //===------------------------------------------------------------------------===
 
-static cl::opt<bool> DryRun("dry-run", cl::Optional, cl::init(false),
+cl::opt<bool> DryRun("dry-run", cl::Optional, cl::init(false),
   cl::desc("Do everything but perform the compilation actions"));
 
-static cl::alias DryRunAlias("y", cl::Optional,
+cl::alias DryRunAlias("y", cl::Optional,
   cl::desc("Alias for -dry-run"), cl::aliasopt(DryRun));
 
-static cl::opt<bool> Verbose("verbose", cl::Optional, cl::init(false),
+cl::opt<bool> Verbose("verbose", cl::Optional, cl::init(false),
   cl::desc("Print out each action taken"));
 
-static cl::alias VerboseAlias("v", cl::Optional, 
+cl::alias VerboseAlias("v", cl::Optional, 
   cl::desc("Alias for -verbose"), cl::aliasopt(Verbose));
 
-static cl::opt<bool> Debug("debug", cl::Optional, cl::init(false), 
+cl::opt<bool> Debug("debug", cl::Optional, cl::init(false), 
   cl::Hidden, cl::desc("Print out debugging information"));
 
-static cl::alias DebugAlias("d", cl::Optional,
+cl::alias DebugAlias("d", cl::Optional,
   cl::desc("Alias for -debug"), cl::aliasopt(Debug));
 
-static cl::opt<bool> TimeActions("time-actions", cl::Optional, cl::init(false),
+cl::opt<bool> TimeActions("time-actions", cl::Optional, cl::init(false),
   cl::desc("Print execution time for each action taken"));
 
+cl::opt<bool> TimePasses("time-passes", cl::Optional, cl::init(false),
+  cl::desc("Print execution time for each optimization pass"));
+
+cl::opt<bool> ShowStats("stats", cl::Optional, cl::init(false),
+  cl::desc("Print statistics accumulated during optimization"));
+
 //===------------------------------------------------------------------------===
 //===          ADVANCED OPTIONS
 //===------------------------------------------------------------------------===
@@ -152,6 +158,9 @@
 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,
+  cl::desc("Don't delete the temporary files created during compilation"));
+
 //===------------------------------------------------------------------------===
 //===          POSITIONAL OPTIONS
 //===------------------------------------------------------------------------===
@@ -192,86 +201,97 @@
 
 /// @brief The main program for llvmc
 int main(int argc, char **argv) {
-  // 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"
-    "  This program provides easy invocation of the LLVM tool set\n"
-    "  and source language compiler tools.\n"
-  );
-
-  // Deal with unimplemented options.
-  if (Native)
-    std::cerr << argv[0] << ": Not implemented yet: -native";
-  if (EmitRawCode)
-    std::cerr << argv[0] << ": Not implemented yet: -emit-raw-code";
-  if (PipeCommands)
-    std::cerr << argv[0] << ": Not implemented yet: -pipe";
-
-  // Default the output file, only if we're going to try to link
-  if (OutputFilename.empty() && OptLevel == CompilerDriver::LINKING)
-    OutputFilename = "a.out";
-
-  // Construct the ConfigDataProvider object
-  LLVMC_ConfigDataProvider Provider;
-  Provider.setConfigDir(ConfigDir);
-
-  // Construct the CompilerDriver object
-  CompilerDriver CD(Provider);
-
-  // 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.setLibraryPaths(LibPaths);
-  CD.setPreprocessorOptions(PreprocessorToolOpts);
-  CD.setTranslatorOptions(TranslatorToolOpts);
-  CD.setOptimizerOptions(OptimizerToolOpts);
-  CD.setAssemblerOptions(AssemblerToolOpts);
-  CD.setLinkerOptions(LinkerToolOpts);
-
-  // Prepare the list of files to be compiled by the CompilerDriver.
-  CompilerDriver::InputList InpList;
-  std::vector<std::string>::iterator fileIt = Files.begin();
-  std::vector<std::string>::iterator libIt  = Libraries.begin();
-  unsigned libPos = 0, filePos = 0;
-  while ( 1 ) {
-    if ( libIt != Libraries.end() )
-      libPos = Libraries.getPosition( libIt - Libraries.begin() );
-    else
-      libPos = 0;
-    if ( fileIt != Files.end() )
-      filePos = Files.getPosition( fileIt - Files.begin() );
-    else
-      filePos = 0;
-
-    if ( filePos != 0 && (libPos == 0 || filePos < libPos) ) {
-      // Add a source file
-      InpList.push_back( std::make_pair(*fileIt, GetFileType(*fileIt,filePos)));
-      ++fileIt;
+  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"
+      "  This program provides easy invocation of the LLVM tool set\n"
+      "  and source language compiler tools.\n"
+    );
+
+    // Deal with unimplemented options.
+    if (PipeCommands)
+      std::cerr << argv[0] << ": Not implemented yet: -pipe";
+
+    // Default the output file, only if we're going to try to link
+    if (OutputFilename.empty() && OptLevel == CompilerDriver::LINKING)
+      OutputFilename = "a.out";
+
+    // Construct the ConfigDataProvider object
+    LLVMC_ConfigDataProvider Provider;
+    Provider.setConfigDir(ConfigDir);
+
+    // Construct the CompilerDriver object
+    CompilerDriver CD(Provider);
+
+    // 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(TimePasses);
+    CD.setShowStats(ShowStats);
+    CD.setKeepTemporaries(KeepTemporaries);
+    CD.setLibraryPaths(LibPaths);
+    if (!PreprocessorToolOpts.empty())
+        CD.setPhaseArgs(CompilerDriver::PREPROCESSING, PreprocessorToolOpts);
+    if (!TranslatorToolOpts.empty())
+        CD.setPhaseArgs(CompilerDriver::TRANSLATION, TranslatorToolOpts);
+    if (!OptimizerToolOpts.empty())
+        CD.setPhaseArgs(CompilerDriver::OPTIMIZATION, OptimizerToolOpts);
+    if (!AssemblerToolOpts.empty())
+        CD.setPhaseArgs(CompilerDriver::ASSEMBLY,AssemblerToolOpts);
+    if (!LinkerToolOpts.empty())
+        CD.setPhaseArgs(CompilerDriver::LINKING, LinkerToolOpts);
+
+    // Prepare the list of files to be compiled by the CompilerDriver.
+    CompilerDriver::InputList InpList;
+    std::vector<std::string>::iterator fileIt = Files.begin();
+    std::vector<std::string>::iterator libIt  = Libraries.begin();
+    unsigned libPos = 0, filePos = 0;
+    while ( 1 ) {
+      if ( libIt != Libraries.end() )
+        libPos = Libraries.getPosition( libIt - Libraries.begin() );
+      else
+        libPos = 0;
+      if ( fileIt != Files.end() )
+        filePos = Files.getPosition( fileIt - Files.begin() );
+      else
+        filePos = 0;
+
+      if ( filePos != 0 && (libPos == 0 || filePos < libPos) ) {
+        // Add a source file
+        InpList.push_back( std::make_pair(*fileIt, GetFileType(*fileIt,filePos)));
+        ++fileIt;
+      }
+      else if ( libPos != 0 && (filePos == 0 || libPos < filePos) ) {
+        // Add a library
+        InpList.push_back( std::make_pair(*libIt++,""));
+      }
+      else
+        break; // we're done with the list
     }
-    else if ( libPos != 0 && (filePos == 0 || libPos < filePos) ) {
-      // Add a library
-      InpList.push_back( std::make_pair(*libIt++,""));
+
+    // Tell the driver to do its thing
+    int result = CD.execute(InpList,OutputFilename);
+    if (result != 0) {
+      std::cerr << argv[0] << ": Error executing actions. Terminated.\n";
+      return result;
     }
-    else
-      break; // we're done with the list
-  }
 
-  // Tell the driver to do its thing
-  int result = CD.execute(InpList,OutputFilename);
-  if (result != 0) {
-    std::cerr << argv[0] << ": Error executing actions. Terminated.\n";
-    return result;
+    // All is good, return success
+    return 0;
+  } catch (std::string& msg) {
+    std::cerr << msg << "\n";
+  } catch (...) {
+    std::cerr << "Unexpected unknown exception occurred.\n";
   }
-
-  // All is good, return success
-  return 0;
 }


Index: llvm/tools/llvmc/st
diff -u llvm/tools/llvmc/st:1.1 llvm/tools/llvmc/st:1.2
--- llvm/tools/llvmc/st:1.1	Sun Aug 15 03:16:12 2004
+++ llvm/tools/llvmc/st	Wed Aug 18 23:49:47 2004
@@ -1,22 +1,72 @@
-# Stacker CompilerDriver Configuration File
+# Stacker Configuration File For llvmc
 
+##########################################################
+# Language definitions
+##########################################################
   lang.name=Stacker 
+  lang.opt1=-simplifycfg -instcombine -mem2reg
+  lang.opt2=-simplifycfg -instcombine -mem2reg -scalarrepl -sccp
+  lang.opt3=-simplifycfg -instcombine -mem2reg -scalarrepl -sccp \
+  -branch-combine -adce -globaldce -inline -licm -pre
+  lang.opt4=-simplifycfg -instcombine -mem2reg -scalarrepl -sccp \
+  -ipconstprop -branch-combine -adce -globaldce -inline -licm -pre
+  lang.opt5=-simplifycfg -instcombine -mem2reg -scalarrepl -sccp \
+  -ipconstprop -branch-combine -adce -globaldce -inline -licm -pre \
+  -block-placement
+
+##########################################################
 # Pre-processor definitions
+##########################################################
+
+  # Stacker doesn't have a preprocessor but the following
+  # allows the -E option to be supported
   preprocessor.command=cp @in@ @out@
-  preprocessor.required=False
+  preprocessor.required=false
 
+##########################################################
 # Translator definitions
-  translator.command=stkrc -S 2048 @in@ -o @out@
-  translator.preprocesses=false
-  translator.optimizes=TRUE
-  translator.groks_dash_O=No
-  translator.required=no
+##########################################################
+
+  # 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@
+
+  # stkrc doesn't preprocess but we set this to true so
+  # that we don't run the cp command by default.
+  translator.preprocesses=true
+
+  # The translator is required to run.
+  translator.required=true
 
+  # stkrc doesn't do any optimization, it just translates
+  translator.optimizes=no
+
+  # stkrc doesn't handle the -On options
+  translator.groks_dash_O=no
+
+##########################################################
 # Optimizer definitions
-  optimizer.command=opt @in@ -o @out@
+##########################################################
+  
+  # For optimization, we use the LLVM "opt" program
+  optimizer.command=opt @in@ -o @out@ @opt@ @time@ @stats@
+
+  # opt doesn't (yet) grok -On
+  optimizer.groks_dash_O=no
+
+  # opt doesn't translate
+  optimizer.translates = no
+
+  # opt doesn't preprocess
+  optimizer.preprocesses=no
 
+##########################################################
 # Assembler definitions
-  assembler.command=llc @in@ -o @out@
+##########################################################
+  assembler.command=llc @in@ -o @out@ @target@ "-regalloc=linearscan" \
+  @time@ @stats@
 
+##########################################################
 # Linker definitions
-  linker.command=llvm-link @in@ -o @out@
+##########################################################
+  linker.command=gccld @in@ -o @out@ -lstkr_runtime






More information about the llvm-commits mailing list