Additional functionality. This version handles option parsing and parameter
authorReid Spencer <rspencer@reidspencer.com>
Fri, 13 Aug 2004 20:22:43 +0000 (20:22 +0000)
committerReid Spencer <rspencer@reidspencer.com>
Fri, 13 Aug 2004 20:22:43 +0000 (20:22 +0000)
subsitution correctly for at least .ll and .st files. There's still a long
way to go (i.e. this isn't worth of review yet).

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@15728 91177308-0d34-0410-b5e6-96231b3b80d8

tools/llvmc/CompilerDriver.cpp [new file with mode: 0644]
tools/llvmc/CompilerDriver.h
tools/llvmc/llvmc.cpp

diff --git a/tools/llvmc/CompilerDriver.cpp b/tools/llvmc/CompilerDriver.cpp
new file mode 100644 (file)
index 0000000..7a639b3
--- /dev/null
@@ -0,0 +1,227 @@
+//===- DriverAction.cpp - Compile Driver Actions ----------------*- C++ -*-===//
+//
+// 
+//                     The LLVM Compiler Infrastructure
+//
+// This file was developed by Reid Spencer and is distributed under the 
+// University of Illinois Open Source License. See LICENSE.TXT for details.
+// 
+//===----------------------------------------------------------------------===//
+//
+// This file implements support for executable actions in the LLVM Compiler
+// Driver (llvmc).
+//
+//===------------------------------------------------------------------------===
+
+#include "CompilerDriver.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);
+  }
+
+  inline std::string GetSuffix(const std::string& fullName) {
+    size_t dotpos = fullName.rfind('.',fullName.size());
+    if ( dotpos = std::string::npos ) return "";
+    return fullName.substr(dotpos+1);
+  }
+  const char OutputSuffix[] = ".o";
+
+}
+
+
+CompilerDriver::CompilerDriver(ConfigDataProvider& confDatProv )
+  : cdp(&confDatProv)
+  , finalPhase(LINKING)
+  , optLevel(OPT_FAST_COMPILE) 
+  , isDryRun(false)
+  , isVerbose(false)
+  , isDebug(false)
+  , timeActions(false)
+  , emitRawCode(false)
+  , emitNativeCode(false)
+  , machine()
+  , libPaths()
+{
+  // FIXME: These libraries are platform specific
+  libPaths.push_back("/lib");
+  libPaths.push_back("/usr/lib");
+}
+
+CompilerDriver::~CompilerDriver() {
+  cdp = 0;
+  libPaths.clear();
+}
+
+void CompilerDriver::error( const std::string& errmsg ) {
+  std::cerr << "Error: " << errmsg << ".\n";
+  exit(1);
+}
+
+CompilerDriver::Action* CompilerDriver::GetAction(ConfigData* cd, 
+                          const std::string& input, 
+                          const std::string& output,
+                          Phases phase)
+{
+  Action* pat = 0;
+  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");
+  Action* a = new Action(*pat);
+  a->args[pat->inputAt] = input;
+  a->args[pat->outputAt] = output;
+  return a;
+}
+
+void CompilerDriver::WriteAction(Action* a) {
+  std::cerr << a->program;
+  std::vector<std::string>::iterator I = a->args.begin();
+  while (I != a->args.end()) {
+    std::cerr << " " + *I;
+    ++I;
+  }
+  std::cerr << "\n";
+}
+
+void CompilerDriver::DoAction(Action*a)
+{
+  if (isVerbose)
+    WriteAction(a);
+  if (!isDryRun) {
+    std::cerr << "execve(\"" << a->program << "\",[\n";
+    std::vector<std::string>::iterator I = a->args.begin();
+    while (I != a->args.end()) {
+      std::cerr << "  \"" << *I << "\",\n";
+      ++I;
+    }
+    std::cerr << "],ENV);\n";
+  }
+}
+
+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");
+
+  std::vector<Action*> actions;
+
+  /// PRE-PROCESSING / TRANSLATION / OPTIMIZATION / ASSEMBLY phases
+  // for each input item
+  std::vector<std::string> LinkageItems;
+  InputList::const_iterator I = InpList.begin();
+  while ( I != InpList.end() ) {
+    // Get the suffix of the file name
+    std::string suffix = GetSuffix(I->first);
+
+    // If its a library, bytecode file, or object file, save 
+    // it for linking below and short circuit the 
+    // pre-processing/translation/assembly phases
+    if (I->second.empty() || suffix == "o" || suffix == "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");
+      }
+      LinkageItems.push_back(I->first);
+      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." ); 
+
+    // We have valid configuration data, now figure out where the output
+    // of compilation should end up.
+    std::string OutFile;
+    if (finalPhase != LINKING) {
+      if (InpList.size() == 1 && !Output.empty()) 
+        OutFile = Output;
+      else
+        OutFile = RemoveSuffix(I->first) + OutputSuffix;
+    } else {
+      OutFile = Output;
+    }
+
+    /// PRE-PROCESSING PHASE
+    if (finalPhase == PREPROCESSING) {
+      if (cd->PreProcessor.program.empty())
+        error(cd->langName + " does not support pre-processing");
+      else
+        actions.push_back(GetAction(cd,I->first,OutFile,PREPROCESSING));
+    } else if (cd->PreprocessorNeeded && !cd->TranslatorPreprocesses) {
+      if (!cd->PreProcessor.program.empty()) {
+        actions.push_back(GetAction(cd,I->first,OutFile,PREPROCESSING));
+      }
+    }
+
+    // Short-circuit remaining actions if all they want is pre-processing
+    if (finalPhase == PREPROCESSING) { ++I; continue; };
+
+    /// TRANSLATION PHASE
+    actions.push_back(GetAction(cd,I->first,OutFile,TRANSLATION));
+    // Short-circuit remaining actions if all they want is translation
+    if (finalPhase == TRANSLATION) { ++I; continue; }
+
+    /// OPTIMIZATION PHASE
+    actions.push_back(GetAction(cd,I->first,OutFile,OPTIMIZATION));
+    // Short-circuit remaining actions if all they want is optimization
+    if (finalPhase == OPTIMIZATION) { ++I; continue; }
+
+    ++I;
+  }
+
+  /// LINKING PHASE
+
+  /// RUN THE ACTIONS
+  std::vector<Action*>::iterator aIter = actions.begin();
+  while (aIter != actions.end()) {
+    DoAction(*aIter);
+    aIter++;
+  }
+
+  return 0;
+}
+
+// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab
index d56c9b5b6b481920d998ca261fb54e0af407eb45..d6587b0aa92425b785410bd3afbc8de1a44a48ed 100644 (file)
@@ -1,4 +1,4 @@
-//===- CompilerDriver.h - Compiler Driver ---------------------------------===//
+//===- CompilerDriver.h - Compiler Driver -----------------------*- C++ -*-===//
 // 
 //                     The LLVM Compiler Infrastructure
 //
 // LLVM Compiler Driver program (llvmc).
 //
 //===------------------------------------------------------------------------===
+#ifndef LLVM_TOOLS_LLVMC_COMPILERDRIVER_H
+#define LLVM_TOOLS_LLVMC_COMPILERDRIVER_H
+
+#include <string>
+#include <vector>
 
 namespace llvm {
   /// This class provides the high level interface to the LLVM Compiler Driver.
@@ -24,7 +29,6 @@ namespace llvm {
     /// @name Types
     /// @{
     public:
-      typedef unsigned OptimizationLevel;
       enum Phases {
         PREPROCESSING, ///< Source language combining, filtering, substitution
         TRANSLATION,   ///< Translate source -> LLVM bytecode/assembly
@@ -34,42 +38,146 @@ namespace llvm {
       };
 
       enum OptimizationLevels {
-        OPT_NONE,
-        OPT_FAST_COMPILE,
-        OPT_SIMPLE,
-        OPT_AGGRESSIVE,
-        OPT_LINK_TIME,
-        OPT_AGGRESSIVE_LINK_TIME
+        OPT_NONE,                 ///< Zippo optimizations, nada, nil, none.
+        OPT_FAST_COMPILE,         ///< Optimize to make >compile< go faster
+        OPT_SIMPLE,               ///< Standard/simple optimizations
+        OPT_AGGRESSIVE,           ///< Aggressive optimizations
+        OPT_LINK_TIME,            ///< Aggressive + LinkTime optimizations
+        OPT_AGGRESSIVE_LINK_TIME  ///< Make it go way fast!
+      };
+
+      /// This type is the input list to the CompilerDriver. It provides
+      /// a vector of filename/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;
+
+      /// This type is read from configuration files or otherwise provided to
+      /// the CompilerDriver through a "ConfigDataProvider". It serves as both
+      /// the template of what to do and the actual Action to be executed.
+      /// @brief A structure to hold the action data for a given source
+      /// language.
+      struct Action {
+        std::string program;            ///< The program to execve
+        std::vector<std::string> args;  ///< Arguments to the program
+        size_t inputAt;                 ///< Argument index to insert input file
+        size_t outputAt;                ///< Argument index to insert output file
+      };
+
+      struct ConfigData {
+        std::string langName;       ///< The name of the source language 
+        bool TranslatorPreprocesses;///< Translator program will pre-process
+        bool TranslatorOptimizes;   ///< Translator program will optimize too
+        bool TranslatorGroksDashO;  ///< Translator understands -O arguments
+        bool PreprocessorNeeded;    ///< Preprocessor is needed for translation
+        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
+      /// CompilerDriver and other software that provides ConfigData objects to
+      /// it. The CompilerDriver must be configured to use an object of this
+      /// type so it can obtain the configuration data. 
+      /// @see setConfigDataProvider
+      /// @brief Configuration Data Provider interface
+      class ConfigDataProvider {
+      public:
+        virtual ConfigData* ProvideConfigData(const std::string& filetype) = 0;
+        virtual void setConfigDir(const std::string& dirName) = 0;
       };
 
     /// @}
     /// @name Constructors
     /// @{
     public:
-      CompilerDriver();
+      CompilerDriver(ConfigDataProvider& cdp );
+      virtual ~CompilerDriver();
 
     /// @}
-    /// @name Accessors
+    /// @name Methods
     /// @{
     public:
-      void execute(); ///< Execute the actions requested
+      /// @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);
 
     /// @}
     /// @name Mutators
     /// @{
     public:
+      /// @brief Set the final phase at which compilation terminates
+      void setFinalPhase( Phases phase ) { finalPhase = phase; }
+
       /// @brief Set the optimization level for the compilation
-      void setOptimization( OptimizationLevel level );
-      void setFinalPhase( Phases phase );
+      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; }
+
+      /// @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; }
+
+      /// @brief Set the output machine name.
+      void setOutputMachine( const std::string& machineName ) {
+        machine = machineName;
+      }
+
+      /// @brief Set the list of library paths to be searched for
+      /// libraries.
+      void addLibraryPath( const std::string& libPath ) {
+        libPaths.push_back(libPath);
+      }
+
+    /// @}
+    /// @name Functions
+    /// @{
+    private:
+      Action* GetAction(ConfigData* cd, const std::string& input, 
+                       const std::string& output, Phases phase );
+      void WriteAction(Action* a);
+      void DoAction(Action* a);
 
     /// @}
     /// @name Data
     /// @{
-    public:
-      Phases finalPhase;
-      OptimizationLevel optLevel;
+    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 emitRawCode;             ///< Emit Raw (unoptimized) code?
+      bool emitNativeCode;          ///< Emit native code instead of bytecode?
+      std::string machine;          ///< Target machine name
+      std::vector<std::string> libPaths; ///< list of dirs to find libraries
 
     /// @}
 
   };
 }
+
+// vim: sw=2 smartindent smarttab tw=80 autoindent expandtab
+#endif
index 75d37fb4f993736eafa9792119cd3669e8e6771f..878fb65e0c8732fa8ef0095cf23f9922d4a5cef7 100644 (file)
@@ -1,8 +1,8 @@
-//===--- llvmc.cpp - The LLVM Compiler Driver -----------------------------===//
+//===--- llvmc.cpp - The LLVM Compiler Driver -------------------*- C++ -*-===//
 // 
 //                     The LLVM Compiler Infrastructure
 //
-// This file was developed by Reid Spencerand is distributed under the
+// This file was developed by Reid Spencer and is distributed under the
 // University of Illinois Open Source License. See LICENSE.TXT for details.
 // 
 //===----------------------------------------------------------------------===//
 //===------------------------------------------------------------------------===
 
 #include "CompilerDriver.h"
+#include "ConfigData.h"
 #include "llvm/System/Signals.h"
 #include "Support/CommandLine.h"
 #include <iostream>
 
 using namespace llvm;
 
+namespace {
 //===------------------------------------------------------------------------===
 //===          PHASE OPTIONS
 //===------------------------------------------------------------------------===
 static cl::opt<CompilerDriver::Phases> FinalPhase(
   cl::desc("Choose final phase of compilation:"), 
+  cl::init(CompilerDriver::LINKING),
   cl::values(
     clEnumValN(CompilerDriver::PREPROCESSING,"E",
-      "Stop compilation after pre-processing"),
+      "Stop compilation after pre-processing phase"),
+    clEnumValN(CompilerDriver::TRANSLATION, "t",
+      "Stop compilation after translation phase"),
     clEnumValN(CompilerDriver::OPTIMIZATION,"c",
-      "Stop compilation after source code translation and optimization"),
+      "Stop compilation after optimization phase"),
     clEnumValN(CompilerDriver::ASSEMBLY,"S",
-      "Stop compilation after assembly"),
+      "Stop compilation after assembly phase"),
     clEnumValEnd
   )
 );
@@ -42,9 +47,10 @@ static cl::opt<CompilerDriver::Phases> FinalPhase(
 //===------------------------------------------------------------------------===
 static cl::opt<CompilerDriver::OptimizationLevels> OptLevel(
   cl::desc("Choose level of optimization to apply:"),
+  cl::init(CompilerDriver::OPT_FAST_COMPILE),
   cl::values(
     clEnumValN(CompilerDriver::OPT_FAST_COMPILE,"O0",
-      "Optimize for compilation speed, not execution speed."),
+      "An alias for the -O1 option."),
     clEnumValN(CompilerDriver::OPT_FAST_COMPILE,"O1",
       "Optimize for compilation speed, not execution speed."),
     clEnumValN(CompilerDriver::OPT_SIMPLE,"O2",
@@ -64,16 +70,20 @@ static cl::opt<CompilerDriver::OptimizationLevels> OptLevel(
 //===------------------------------------------------------------------------===
 
 static cl::opt<std::string> PPToolOpts("Tpp", cl::ZeroOrMore,
-  cl::desc("Pass specific options to the pre-processor"));
+  cl::desc("Pass specific options to the pre-processor"), 
+  cl::value_desc("option"));
 
 static cl::opt<std::string> AsmToolOpts("Tasm", cl::ZeroOrMore,
-  cl::desc("Pass specific options to the assembler"));
+  cl::desc("Pass specific options to the assembler"),
+  cl::value_desc("option"));
 
 static cl::opt<std::string> OptToolOpts("Topt", cl::ZeroOrMore,
-  cl::desc("Pass specific options to the optimizer"));
+  cl::desc("Pass specific options to the optimizer"),
+  cl::value_desc("option"));
 
 static cl::opt<std::string> LinkToolOpts("Tlink", cl::ZeroOrMore,
-  cl::desc("Pass specific options to the linker"));
+  cl::desc("Pass specific options to the linker"),
+  cl::value_desc("option"));
 
 //===------------------------------------------------------------------------===
 //===          INPUT OPTIONS
@@ -90,40 +100,47 @@ static cl::list<std::string> Libraries("l", cl::Prefix,
 //===          OUTPUT OPTIONS
 //===------------------------------------------------------------------------===
 
-static cl::opt<std::string> OutputFilename("o", cl::init("a.out"),
+static cl::opt<std::string> OutputFilename("o", 
   cl::desc("Override output filename"), cl::value_desc("filename"));
 
-static cl::opt<std::string> OutputMachne("m", cl::Prefix,
+static cl::opt<std::string> OutputMachine("m", cl::Prefix,
   cl::desc("Specify a target machine"), cl::value_desc("machine"));
                                                                                                                                             
-static cl::opt<bool> Native("native",
+static cl::opt<bool> Native("native", cl::init(false),
   cl::desc("Generative native object and executables instead of bytecode"));
 
 //===------------------------------------------------------------------------===
 //===          INFORMATION OPTIONS
 //===------------------------------------------------------------------------===
 
-static cl::opt<bool> NoOperation("no-operation", cl::Optional,
-  cl::desc("Do not perform actions"));
+static cl::opt<bool> DryRun("dry-run", cl::Optional, cl::init(false),
+  cl::desc("Do everything but perform the compilation actions"));
 
-static cl::alias NoOp("n", cl::Optional,
-  cl::desc("Alias for -no-operation"), cl::aliasopt(NoOperation));
+static cl::alias DryRunAlias("y", cl::Optional,
+  cl::desc("Alias for -dry-run"), cl::aliasopt(DryRun));
 
-static cl::opt<bool> Verbose("verbose", cl::Optional,
+static cl::opt<bool> Verbose("verbose", cl::Optional, cl::init(false),
   cl::desc("Print out each action taken"));
 
-static cl::alias VerboseAlias("v", cl::Optional,
+static cl::alias VerboseAlias("v", cl::Optional, 
   cl::desc("Alias for -verbose"), cl::aliasopt(Verbose));
 
-static cl::opt<bool> TimeActions("time-actions", cl::Optional,
+static 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::desc("Alias for -debug"), cl::aliasopt(Debug));
+
+static cl::opt<bool> TimeActions("time-actions", cl::Optional, cl::init(false),
   cl::desc("Print execution time for each action taken"));
 
 //===------------------------------------------------------------------------===
 //===          ADVANCED OPTIONS
 //===------------------------------------------------------------------------===
 
-static cl::list<std::string> ConfigFiles("config-dir", cl::Optional,
-  cl::desc("Specify a configuration directory to override defaults"));
+static cl::opt<std::string> ConfigDir("config-dir", cl::Optional,
+  cl::desc("Specify a configuration directory to override defaults"),
+  cl::value_desc("directory"));
 
 static cl::opt<bool> EmitRawCode("emit-raw-code", cl::Hidden,
   cl::desc("Emit raw, unoptimized code"));
@@ -133,7 +150,37 @@ static cl::opt<bool> EmitRawCode("emit-raw-code", cl::Hidden,
 //===------------------------------------------------------------------------===
 
 static cl::list<std::string> Files(cl::Positional, cl::OneOrMore,
-  cl::desc("Source and object files"));
+  cl::desc("[Sources/objects/libraries]"));
+
+static cl::list<std::string> Languages("x", cl::ZeroOrMore,
+  cl::desc("Specify the source language for subsequent files"),
+  cl::value_desc("language"));
+
+//===------------------------------------------------------------------------===
+//===          GetFileType - determine type of a file
+//===------------------------------------------------------------------------===
+const std::string GetFileType(const std::string& fname, unsigned pos ) {
+  static std::vector<std::string>::iterator langIt = Languages.begin();
+  static std::string CurrLang = "";
+
+  // If a -x LANG option has been specified ..
+  if ( langIt != Languages.end() )
+    // If the -x LANG option came before the current file on command line
+    if ( Languages.getPosition( langIt - Languages.begin() ) < pos ) {
+      // use that language
+      CurrLang = *langIt++;
+      return CurrLang;
+    }
+
+  // If there's a current language in effect
+  if (!CurrLang.empty())
+    return CurrLang; // use that language
+
+  // otherwise just determine lang from the filename's suffix
+  return fname.substr( fname.rfind('.',fname.size()) + 1 );
+}
+
+} // end anonymous namespace
 
 
 /// @brief The main program for llvmc
@@ -148,14 +195,66 @@ int main(int argc, char **argv) {
     "  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";
+
+  // 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;
+
   // Construct the CompilerDriver object
-  //CompilerDriver CD;
+  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);
+  std::vector<std::string>::iterator pathIt = LibPaths.begin();
+  while ( pathIt != LibPaths.end() ) {
+      CD.addLibraryPath( *pathIt++ );
+  }
 
-  // Set the options for the Compiler Driver
+  // 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
+  }
 
   // Tell the driver to do its thing
-  int result = 0;
-  // result = CD.execute();
+  int result = CD.execute(InpList,OutputFilename);
   if (result != 0) {
     std::cerr << argv[0] << ": Error executing actions. Terminated.\n";
     return result;
@@ -164,4 +263,3 @@ int main(int argc, char **argv) {
   // All is good, return success
   return 0;
 }
-