gollvm: introduce new driver helper classes

Creates a set of new helper classes that will form the basis for a
revamped gollvm. These include Action, Artifact, Command, Compilation,
Driver, ToolChain, and Tool classes. This patch covers mainly the
class and method declarations; most of the interesting method
implementations are stubbed out (will appear in a forthcoming patch).

Change-Id: I62cd57e6b86dbf4a3f2b5b5076e7345803d801f3
Reviewed-on: https://go-review.googlesource.com/110617
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/driver-main/llvm-goc.cpp b/driver-main/llvm-goc.cpp
index 42d8f1e..8f7ada1 100644
--- a/driver-main/llvm-goc.cpp
+++ b/driver-main/llvm-goc.cpp
@@ -20,6 +20,12 @@
 #include "mpfr.h"
 #include "GollvmOptions.h"
 
+#include "Compilation.h"
+#include "Driver.h"
+#include "ToolChain.h"
+#include "Tool.h"
+
+
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/Triple.h"
 #include "llvm/Analysis/TargetLibraryInfo.h"
diff --git a/driver/Action.cpp b/driver/Action.cpp
new file mode 100644
index 0000000..2b9bb21
--- /dev/null
+++ b/driver/Action.cpp
@@ -0,0 +1,63 @@
+//===-- Action.cpp ------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Gollvm driver helper class Action methods.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Action.h"
+#include "Artifact.h"
+
+#include "llvm/Support/raw_ostream.h"
+
+namespace gollvm {
+namespace driver {
+
+const char *Action::getName() const
+{
+  switch (type_) {
+    case A_Input: return "inputfile";
+    case A_Compile: return "compile";
+    case A_Assemble: return "assemble";
+    case A_Link: return "link";
+    default:
+      assert(false);
+      return "<unknown action type>";
+  }
+  return nullptr;
+}
+
+const char *Action::resultFileSuffix() const
+{
+  switch (type_) {
+    case A_Input: return "i";
+    case A_Compile: return "s";
+    case A_Assemble: return "o";
+    case A_Link: return "e";
+    default:
+      assert(false);
+      return "x";
+  }
+  return nullptr;
+}
+
+void Action::dump()
+{
+  llvm::errs() << "Action " << getName() << " inputs:\n";
+  for (auto inp : inputs()) {
+    llvm::errs() << "  " << ((void*) inp) << " " << inp->getName() << " ";
+    InputAction *ia = inp->castToInputAction();
+    if (ia)
+      llvm::errs() << ia->input()->toString();
+    llvm::errs() << "\n";
+  }
+}
+
+} // end namespace driver
+} // end namespace gollvm
diff --git a/driver/Action.h b/driver/Action.h
new file mode 100644
index 0000000..78f5327
--- /dev/null
+++ b/driver/Action.h
@@ -0,0 +1,92 @@
+//===-- Action.h ----------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the Action class (helper for driver functionality).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GOLLVM_DRIVER_ACTION_H
+#define GOLLVM_DRIVER_ACTION_H
+
+#include "llvm/ADT/SmallVector.h"
+
+namespace gollvm {
+namespace driver {
+
+class Action;
+class Artifact;
+class InputAction;
+
+// Action lists contain pointers to actions owned by a Compilation.
+typedef llvm::SmallVector<Action*, 3> ActionList;
+
+// An abstract compilation action, such as "assemble this asm src
+// file" or "link this set of objects together into a new file".
+// Actions are assumed to have a single output. There is also a
+// pseudo-action InputAction that that corresponds to the action of
+// reading an file. An action consumes inputs from a set of other
+// actions.
+
+class Action {
+ public:
+
+  // Type of action
+  enum Type {
+    A_Input,
+    A_Compile,
+    A_Assemble,
+    A_Link
+  };
+
+  explicit Action(Type t) : type_(t) { }
+  Action(Type t, Action *input) : type_(t), inputs_(ActionList({input})){ }
+  Action(Type t, ActionList &il) : type_(t), inputs_(il) { }
+  virtual ~Action() = default;
+
+  const ActionList &inputs() const { return inputs_; }
+
+  Type type() const { return type_; }
+
+  inline InputAction *castToInputAction();
+  inline const InputAction *castToInputAction() const;
+
+  const char *getName() const;
+  const char *resultFileSuffix() const;
+
+  // debugging
+  void dump();
+
+ private:
+  Type type_;
+  ActionList inputs_;
+};
+
+// An input action corresponds to the reading of some input artifact.
+
+class InputAction : public Action {
+ public:
+  explicit InputAction(Artifact *input)
+      : Action(Action::A_Input),
+        input_(input) { }
+  Artifact *input() const { return input_; }
+ private:
+  Artifact *input_;
+};
+
+inline InputAction *Action::castToInputAction() {
+  return type_ == A_Input ? static_cast<InputAction*>(this) : nullptr;
+}
+inline const InputAction *Action::castToInputAction() const {
+  return type_ == A_Input ? static_cast<const InputAction*>(this) : nullptr;
+}
+
+} // end namespace driver
+} // end namespace gollvm
+
+#endif // GOLLVM_DRIVER_ACTION_H
diff --git a/driver/Artifact.cpp b/driver/Artifact.cpp
new file mode 100644
index 0000000..d9e00f8
--- /dev/null
+++ b/driver/Artifact.cpp
@@ -0,0 +1,48 @@
+//===-- Artifact.cpp ------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Gollvm driver helper class Artifact methods.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Artifact.h"
+#include "llvm/Option/Arg.h"
+
+#include "llvm/Support/raw_ostream.h"
+
+#include <sstream>
+
+namespace gollvm {
+namespace driver {
+
+const char *Artifact::file() const
+{
+  assert(type_ == A_Argument || type_ == A_TempFile);
+  return (type_ == A_Argument ?
+          u.arg->getValue() : u.file);
+}
+
+std::string Artifact::toString()
+{
+  std::stringstream ss;
+  ss << "Artifact ";
+  if (type_ == A_Argument)
+    ss << "arg(" << u.arg->getValue() << ")";
+  else
+    ss << "file(" << u.file << ")";
+  return ss.str();
+}
+
+void Artifact::dump()
+{
+  llvm::errs() << toString() << "\n";
+}
+
+} // end namespace driver
+} // end namespace gollvm
diff --git a/driver/Artifact.h b/driver/Artifact.h
new file mode 100644
index 0000000..094f831
--- /dev/null
+++ b/driver/Artifact.h
@@ -0,0 +1,76 @@
+//===-- Artifact.h --------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the Artifact class (helper for driver functionality).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GOLLVM_DRIVER_ARTIFACT_H
+#define GOLLVM_DRIVER_ARTIFACT_H
+
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+namespace opt {
+class Arg;
+}
+}
+
+namespace gollvm {
+namespace driver {
+
+// An artifact is a file produced or consumed by some compilation step.
+// Artifacts may correspond to user-specified files (command line arg
+// for example) or temporary files created by some intermediate phase
+// in the compilation.
+
+class Artifact {
+ public:
+  enum Type {
+    A_Argument,
+    A_TempFile,
+    A_Empty
+  };
+
+  // Empty artifact (unusable as is)
+  Artifact() : type_(A_Empty) { u.arg = nullptr; }
+
+  // Construct an artifact from a command line arg.
+  explicit Artifact(llvm::opt::Arg *arg)
+      : type_(A_Argument) { u.arg = arg; }
+
+  // Construct an artifact given a temp file path.
+  explicit Artifact(const char *tempfilepath)
+      : type_(A_TempFile) { u.file = tempfilepath; }
+
+  // Type of input
+  Type type() const { return type_; }
+
+  // File for input
+  const char *file() const;
+
+  // Debugging
+  std::string toString();
+  void dump();
+
+ private:
+  Type type_;
+  union {
+    llvm::opt::Arg *arg;
+    const char *file;
+  } u;
+};
+
+// A list of artifacts.
+typedef llvm::SmallVector<Artifact *, 3> ArtifactList;
+
+} // end namespace driver
+} // end namespace gollvm
+
+#endif // GOLLVM_DRIVER_ARTIFACT_H
diff --git a/driver/CMakeLists.txt b/driver/CMakeLists.txt
index c54b7fd..0ee3b9c 100644
--- a/driver/CMakeLists.txt
+++ b/driver/CMakeLists.txt
@@ -16,7 +16,14 @@
 
 # A library containing driver utility code.
 add_llvm_library(LLVMDriverUtils
+  Action.cpp
+  Artifact.cpp
+  Command.cpp
+  Compilation.cpp
+  Driver.cpp
   GollvmOptions.cpp
+  Tool.cpp
+  ToolChain.cpp
   DEPENDS
   GollvmDriverOptions
   )
diff --git a/driver/Command.cpp b/driver/Command.cpp
new file mode 100644
index 0000000..de67211
--- /dev/null
+++ b/driver/Command.cpp
@@ -0,0 +1,54 @@
+//===-- Command.cpp -------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Gollvm driver helper class Command methods.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Command.h"
+
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/Program.h"
+
+namespace gollvm {
+namespace driver {
+
+Command::Command(const Action &srcAction,
+                 const Tool &creator,
+                 const char *executable,
+                 llvm::opt::ArgStringList &args)
+    : action_(srcAction),
+      creator_(creator),
+      executable_(executable),
+      arguments_(args)
+{
+}
+
+int Command::execute(std::string *errMsg)
+{
+  return llvm::sys::ExecuteAndWait(executable_,
+                                   arguments_.data(),
+                                   /*env=*/nullptr,
+                                   /*Redirects*/{},
+                                   /*secondsToWait=*/0,
+                                   /*memoryLimit=*/0,
+                                   errMsg);
+}
+
+void Command::print(llvm::raw_ostream &os)
+{
+  os << executable_;
+  for (auto arg : arguments_)
+    if (arg != nullptr)
+      os << " "  << arg;
+  os << "\n";
+}
+
+} // end namespace driver
+} // end namespace gollvm
diff --git a/driver/Command.h b/driver/Command.h
new file mode 100644
index 0000000..d51b0e9
--- /dev/null
+++ b/driver/Command.h
@@ -0,0 +1,67 @@
+//===-- Command.h ----------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the Command class (helper for driver functionality).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GOLLVM_DRIVER_COMMAND_H
+#define GOLLVM_DRIVER_COMMAND_H
+
+#include <string>
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Option/ArgList.h"
+
+namespace llvm {
+class raw_ostream;
+}
+
+namespace gollvm {
+namespace driver {
+
+class Command;
+class Action;
+class Tool;
+
+// A CommandList contains pointers to Command objects owned by a Compilation.
+typedef llvm::SmallVector<Command*, 3> CommandList;
+
+// A Command is a container for the specific command line to be used
+// for invoking an external tool to carry out an Action (a specific
+// compilation step (for example, the exact set of strings needed to
+// exec the assembler). Commands are created by Tools; Commands are
+// stored in and owned by a Compilation.
+
+class Command {
+ public:
+  Command(const Action &srcAction,
+          const Tool &creator,
+          const char *executable,
+          llvm::opt::ArgStringList &args);
+
+  // Execute the command. Returns 0 on success, non-zero on error.
+  int execute(std::string *errMsg);
+
+  // Print to string
+  void print(llvm::raw_ostream &OS);
+
+  // Print for debugging
+  void dbgPrint();
+
+ private:
+  const Action &action_;
+  const Tool &creator_;
+  const char *executable_;
+  llvm::opt::ArgStringList arguments_;
+};
+
+} // end namespace driver
+} // end namespace gollvm
+
+#endif // GOLLVM_DRIVER_COMMAND_H
diff --git a/driver/Compilation.cpp b/driver/Compilation.cpp
new file mode 100644
index 0000000..04c1d29
--- /dev/null
+++ b/driver/Compilation.cpp
@@ -0,0 +1,112 @@
+//===-- Compilation.cpp ---------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Gollvm driver helper class Compilation methods.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Signals.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include "Compilation.h"
+
+#include "Artifact.h"
+#include "Command.h"
+#include "Driver.h"
+
+namespace gollvm {
+namespace driver {
+
+Compilation::Compilation(Driver &driver,
+                         ToolChain &toolchain)
+    : driver_(driver),
+      toolchain_(toolchain)
+{
+}
+
+Compilation::~Compilation()
+{
+  // Clean temp files unless -save-temps is in effect
+  if (driver_.args().hasArg(gollvm::options::OPT_save_temps))
+    return;
+  for (auto tf : tempFileNames_)
+    llvm::sys::fs::remove(tf);
+}
+
+llvm::opt::OptTable &Compilation::opts() {
+  return driver_.opts();
+}
+
+llvm::opt::InputArgList &Compilation::args()
+{
+  return driver_.args();
+}
+
+std::string Compilation::firstFileBase()
+{
+  for (llvm::opt::Arg *arg : driver_.args()) {
+    if (arg->getOption().getKind() == llvm::opt::Option::InputClass) {
+      if (!strcmp(arg->getValue(), "-"))
+        return "-";
+      std::string firstFile(arg->getValue());
+      size_t dotindex = firstFile.find_last_of(".");
+      if (dotindex == std::string::npos)
+        continue;
+      return firstFile.substr(0, dotindex);
+    }
+  }
+  assert(false);
+  return "internal_error";
+}
+
+Artifact *Compilation::newArgArtifact(llvm::opt::Arg *arg)
+{
+  // to be implemented in a later patch
+  return nullptr;
+}
+
+Artifact *Compilation::newFileArtifact(const char *tempfilename)
+{
+  // to be implemented in a later patch
+  return nullptr;
+}
+
+Artifact *Compilation::createOutputFileArtifact(Action *act)
+{
+  // to be implemented in a later patch
+  return nullptr;
+}
+
+llvm::Optional<Artifact*> Compilation::createTemporaryFileArtifact(Action *act)
+{
+  // to be implemented in a later patch
+  return llvm::None;
+}
+
+void Compilation::addCommand(const Action &srcAction,
+                             const Tool &creatingTool,
+                             const char *executable,
+                             llvm::opt::ArgStringList &args)
+{
+  ownedCommands_.push_back(llvm::make_unique<Command>(srcAction,
+                                                      creatingTool,
+                                                      executable,
+                                                      args));
+  commands_.push_back(ownedCommands_.back().get());
+}
+
+bool Compilation::executeCommands()
+{
+  // to be implemented in a later patch
+  return false;
+}
+
+} // end namespace driver
+} // end namespace gollvm
diff --git a/driver/Compilation.h b/driver/Compilation.h
new file mode 100644
index 0000000..aff398e
--- /dev/null
+++ b/driver/Compilation.h
@@ -0,0 +1,110 @@
+//===-- Compilation.h -----------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the Compilation class (helper for driver functionality).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GOLLVM_DRIVER_COMPILATION_H
+#define GOLLVM_DRIVER_COMPILATION_H
+
+#include <string>
+#include "Action.h"
+#include "Command.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Option/ArgList.h"
+
+namespace gollvm {
+namespace driver {
+
+class Command;
+class Driver;
+class Tool;
+class ToolChain;
+
+// Compilation class: this is primarily a container for state
+// related to the compilation: driver, toolchain, list of actions,
+// list of commands, temporary files, etc.
+
+class Compilation {
+ public:
+  Compilation(Driver &driver,
+              ToolChain &toolChain);
+  ~Compilation();
+
+  // Execute queued commands to invoke external tools.
+  // Return is true for success, false for error;
+  bool executeCommands();
+
+  // Create a temp file and return as artifact.
+  llvm::Optional<Artifact*> createTemporaryFileArtifact(Action *act);
+
+  // Return an artifact corresponding to the proper output file (depends
+  // on action plus command line flags).
+  Artifact* createOutputFileArtifact(Action *act);
+
+  // Toolchain, driver
+  ToolChain &toolchain() { return toolchain_; }
+  Driver &driver() { return driver_; }
+
+  // Table of options
+  llvm::opt::OptTable &opts();
+
+  // Command line arguments
+  llvm::opt::InputArgList &args();
+
+  // First input file basename.
+  std::string firstFileBase();
+
+  // Compilation actions (built up by driver)
+  ActionList &actions() { return actions_; }
+
+  // Commands to carry out compilation
+  CommandList &commands();
+
+  // Create new input artifact based on arg.
+  Artifact *newArgArtifact(llvm::opt::Arg *arg);
+
+  // Push this action onto the owned actions list.
+  template <typename T> void recordAction(T *act) {
+    assert(act != nullptr);
+    ownedActions_.push_back(std::unique_ptr<Action>(act));
+  }
+
+  // Schedule this action as part of the compilation.
+  void addAction(Action *act) {
+    actions_.push_back(act);
+  }
+
+  // Create a new command and add to the commands list.
+  void addCommand(const Action &srcAction,
+                  const Tool &creatingTool,
+                  const char *executable,
+                  llvm::opt::ArgStringList &args);
+
+ private:
+  Driver &driver_;
+  ToolChain &toolchain_;
+  ActionList actions_;
+  CommandList commands_;
+  std::string outFileName_;
+  llvm::SmallVector<std::unique_ptr<Action>, 8> ownedActions_;
+  llvm::SmallVector<std::unique_ptr<Artifact>, 8> ownedArtifacts_;
+  llvm::SmallVector<std::unique_ptr<Command>, 8> ownedCommands_;
+  llvm::SmallVector<std::string, 8> tempFileNames_;
+
+  // Create new artifact based on temp file.
+  Artifact *newFileArtifact(const char *tempfilename);
+};
+
+} // end namespace driver
+} // end namespace gollvm
+
+#endif // GOLLVM_DRIVER_COMPILATION_H
diff --git a/driver/Driver.cpp b/driver/Driver.cpp
new file mode 100644
index 0000000..00b0d63
--- /dev/null
+++ b/driver/Driver.cpp
@@ -0,0 +1,183 @@
+//===-- Driver.cpp --------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Gollvm driver helper class Driver methods.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
+
+#include "Action.h"
+#include "Driver.h"
+#include "Compilation.h"
+#include "ToolChain.h"
+
+using namespace llvm;
+
+namespace gollvm {
+namespace driver {
+
+Driver::Driver(opt::InputArgList &args,
+               opt::OptTable *optTable,
+               const char *argv0)
+    : args_(args),
+      opts_(optTable),
+      progname_(argv0)
+{
+  if (const opt::Arg *arg = args.getLastArg(gollvm::options::OPT_sysroot_EQ))
+    sysroot_ = arg->getValue();
+}
+
+Driver::~Driver()
+{
+}
+
+std::string Driver::getFilePath(llvm::StringRef name,
+                                ToolChain &toolchain)
+{
+  // to be implemented in a later patch
+  assert(false);
+  return "";
+}
+
+std::string Driver::getProgramPath(llvm::StringRef name,
+                                   ToolChain &toolchain)
+{
+  // to be implemented in a later patch
+  assert(false);
+  return "";
+}
+
+// FIXME: some  platforms have PIE enabled by default; we don't
+// yet support auto-detection of such platforms.
+
+bool Driver::isPIE()
+{
+  // Treat these options as trumping -pie.
+  // FIXME: also handle -r here when supported
+  if (args_.hasArg(gollvm::options::OPT_shared) ||
+      args_.hasArg(gollvm::options::OPT_static))
+    return false;
+
+  opt::Arg *arg = args_.getLastArg(gollvm::options::OPT_pie,
+                                   gollvm::options::OPT_no_pie,
+                                   gollvm::options::OPT_nopie);
+  return (arg ? arg->getOption().matches(options::OPT_pie) : false);
+}
+
+// Return any settings from the -fPIC/-fpic options, if present. The
+// intent of the code below is to support "rightmost on the command
+// line wins" (compatible with clang and other compilers), so if you
+// specify "-fPIC -fpic" you get small PIC, whereas "-fPIC -fpic
+// -fPIC" this will give you large PIC.
+PICLevel::Level Driver::getPicLevel()
+{
+  opt::Arg *arg = args_.getLastArg(gollvm::options::OPT_fpic,
+                                   gollvm::options::OPT_fno_pic,
+                                   gollvm::options::OPT_fPIC,
+                                   gollvm::options::OPT_fno_PIC);
+  if (arg == nullptr)
+    return PICLevel::NotPIC;
+  if (arg->getOption().matches(gollvm::options::OPT_fpic))
+    return PICLevel::SmallPIC;
+  else if (arg->getOption().matches(gollvm::options::OPT_fPIC))
+    return PICLevel::BigPIC;
+  return PICLevel::NotPIC;
+}
+
+// Given a pair of llvm::opt options (presumably corresponding to
+// -fXXX and -fno-XXX boolean flags), select the correct value for the
+// option depending on the relative position of the options on the
+// command line (rightmost wins). For example, given -fblah -fno-blah
+// -fblah, we want the same semantics as a single -fblah.
+
+bool
+Driver::reconcileOptionPair(gollvm::options::ID yesOption,
+                            gollvm::options::ID noOption,
+                            bool defaultVal)
+{
+  opt::Arg *arg = args_.getLastArg(yesOption, noOption);
+  if (arg == nullptr)
+    return defaultVal;
+  if (arg->getOption().matches(yesOption))
+    return true;
+  assert(arg->getOption().matches(noOption));
+  return false;
+}
+
+Optional<Reloc::Model>
+Driver::reconcileRelocModel()
+{
+  auto picLevel = getPicLevel();
+  if (picLevel != PICLevel::NotPIC) {
+    Reloc::Model R = Reloc::PIC_;
+    return R;
+  }
+  return None;
+}
+
+Optional<FPOpFusion::FPOpFusionMode>
+Driver::getFPOpFusionMode()
+{
+  opt::Arg *arg = args_.getLastArg(gollvm::options::OPT_ffp_contract_EQ);
+  FPOpFusion::FPOpFusionMode res = FPOpFusion::Standard;
+  if (arg != nullptr) {
+    std::string val(arg->getValue());
+    if (val == "off")
+      res = FPOpFusion::Strict;
+    else if (val == "on")
+      res = FPOpFusion::Standard;
+    else if (val == "fast")
+      res = FPOpFusion::Fast;
+    else {
+      errs() << progname_ << ": invalid argument '"
+             << arg->getValue() << "' to '"
+             << arg->getAsString(args_) << "' option\n";
+      return None;
+    }
+  }
+  return res;
+}
+
+std::unique_ptr<Compilation> Driver::buildCompilation(ToolChain &tc)
+{
+  return std::unique_ptr<Compilation>(new Compilation(*this, tc));
+}
+
+ToolChain *Driver::setup()
+{
+  // to be implemented in a later patch
+  return nullptr;
+}
+
+ActionList Driver::createInputActions(const inarglist &ifargs,
+                                      Compilation &compilation)
+{
+  // to be implemented in a later patch
+  return ActionList();
+}
+
+bool Driver::buildActions(Compilation &compilation)
+{
+  // to be implemented in a later patch
+  assert(false);
+  return false;
+}
+
+bool Driver::processActions(Compilation &compilation)
+{
+  // to be implemented in a later patch
+  assert(false);
+  return false;
+}
+
+} // end namespace driver
+} // end namespace gollvm
diff --git a/driver/Driver.h b/driver/Driver.h
new file mode 100644
index 0000000..efa2ad5
--- /dev/null
+++ b/driver/Driver.h
@@ -0,0 +1,137 @@
+//===-- Driver.h ----------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the Driver class (helper for driver functionality).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GOLLVM_DRIVER_DRIVER_H
+#define GOLLVM_DRIVER_DRIVER_H
+
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptTable.h"
+#include "llvm/Support/CodeGen.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetOptions.h"
+
+#include "Action.h"
+#include "Artifact.h"
+#include "GollvmOptions.h"
+
+#include <unordered_map>
+
+namespace gollvm {
+namespace driver {
+
+class Compilation;
+class ToolChain;
+
+// Driver class. Drives the process of translating a given command
+// line into a series of compilation actions, then into commands to
+// carry out those actions.
+
+class Driver {
+ public:
+  Driver(llvm::opt::InputArgList &args,
+         llvm::opt::OptTable *optTable,
+         const char *argv0);
+  ~Driver();
+
+  // Set up target and select toolchain. Returns nullptr on error.
+  ToolChain *setup();
+
+  // Create compilation object
+  std::unique_ptr<Compilation> buildCompilation(ToolChain &tc);
+
+  // Build actions for compilation. Returns false if error.
+  bool buildActions(Compilation &compilation);
+
+  // Process the action list. This means:
+  // - execute any non-dependent actions that don't require the
+  //   invocation of an external tool, and
+  // - generate generate a list of commands for invoking external tools.
+  // Return is true for success, false for error;
+  bool processActions(Compilation &compilation);
+
+  // Locate an object file needed for linking (ex: crt0.o)
+  std::string getFilePath(llvm::StringRef name, ToolChain &toolchain);
+
+  // Locate an external tool (ex: "as"). Returns a full path if a hit
+  // is found, otherwise just returns its name argument.
+  std::string getProgramPath(llvm::StringRef name, ToolChain &toolchain);
+
+  // For constructing default output file with -c, -S, etc.
+  std::string firstFileBase();
+
+  // Getters
+  const llvm::Triple &triple() const { return triple_; }
+  llvm::opt::InputArgList &args() { return args_; }
+  llvm::opt::OptTable &opts() { return *opts_; }
+  const char *progname() const { return progname_; }
+
+  // Name of driver (program invoked)
+  std::string name();
+
+  // Sysroot (or empty string if not present)
+  std::string sysRoot() { return sysroot_; }
+
+  // Helpers related to command line options.
+  llvm::PICLevel::Level getPicLevel();
+  bool isPIE();
+  template<typename IT>
+  llvm::Optional<IT> getLastArgAsInteger(gollvm::options::ID id,
+                                         IT defaultValue);
+  llvm::Optional<llvm::Reloc::Model> reconcileRelocModel();
+  bool reconcileOptionPair(gollvm::options::ID yesOption,
+                           gollvm::options::ID noOption,
+                           bool defaultVal);
+  llvm::Optional<llvm::FPOpFusion::FPOpFusionMode> getFPOpFusionMode();
+  typedef llvm::SmallVector<llvm::opt::Arg *, 8> inarglist;
+  ActionList createInputActions(const inarglist &infiles,
+                                Compilation &compilation);
+
+ private:
+  llvm::Triple triple_;
+  llvm::opt::InputArgList &args_;
+  llvm::opt::OptTable *opts_;
+  const char *progname_;
+  std::string sysroot_;
+  // maps target to toolchain for that target
+  llvm::StringMap<std::unique_ptr<ToolChain>> toolchains_;
+  // Maps non-input actions to output artifacts.
+  std::unordered_map<Action *, Artifact*> artmap_;
+};
+
+template<typename IT>
+llvm::Optional<IT>
+Driver::getLastArgAsInteger(gollvm::options::ID id,
+                            IT defaultValue)
+{
+  IT result = defaultValue;
+  llvm::opt::Arg *arg = args_.getLastArg(id);
+  if (arg != nullptr) {
+    if (llvm::StringRef(arg->getValue()).getAsInteger(10, result)) {
+      llvm::errs() << progname_ << ": invalid argument '"
+                   << arg->getValue() << "' to '"
+                   << arg->getAsString(args_) << "' option\n";
+      return llvm::None;
+    }
+  }
+  return result;
+}
+
+} // end namespace driver
+} // end namespace gollvm
+
+#endif // GOLLVM_DRIVER_DRIVER_H
diff --git a/driver/Tool.cpp b/driver/Tool.cpp
new file mode 100644
index 0000000..3a286c1
--- /dev/null
+++ b/driver/Tool.cpp
@@ -0,0 +1,47 @@
+//===-- Tool.cpp ----------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Gollvm driver helper class Tool methods.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Tool.h"
+
+namespace gollvm {
+namespace driver {
+
+Tool::Tool(const char *name, ToolChain &tc, ToolClass klass)
+    : name_(name), toolchain_(tc), klass_(klass)
+{
+}
+
+Tool::~Tool()
+{
+}
+
+InternalTool::InternalTool(const char *name, ToolChain &tc)
+      : Tool(name, tc, Tool::Internal)
+{
+}
+
+InternalTool::~InternalTool()
+{
+}
+
+ExternalTool::ExternalTool(const char *name, ToolChain &tc)
+      : Tool(name, tc, Tool::External)
+{
+}
+
+ExternalTool::~ExternalTool()
+{
+}
+
+} // end namespace driver
+} // end namespace gollvm
diff --git a/driver/Tool.h b/driver/Tool.h
new file mode 100644
index 0000000..1f0ea09
--- /dev/null
+++ b/driver/Tool.h
@@ -0,0 +1,114 @@
+//===-- Tool.h ----------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the Tool class (helper for driver functionality).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GOLLVM_DRIVER_TOOL_H
+#define GOLLVM_DRIVER_TOOL_H
+
+#include "llvm/ADT/SmallVector.h"
+#include "Artifact.h"
+
+namespace gollvm {
+namespace driver {
+
+class Action;
+class Compilation;
+class ExternalTool;
+class InternalTool;
+class ToolChain;
+
+// Abstract class representing a compilation helper "tool", such as an
+// assembler or linker. A tool reads a set of file inputs and produces
+// an output file. Tool objects are either "external" or "internal"; for
+// the latter the tool itself is capable or performing an action,
+// for the former the tool works by constructing a command line for some
+// external program to carry out the action.
+
+class Tool {
+ public:
+  enum ToolClass { External, Internal };
+  Tool(const char *name, ToolChain &tc, ToolClass klass);
+  virtual ~Tool();
+
+  ToolChain &toolchain() { return toolchain_; }
+  const char *name() const { return name_; }
+
+  inline InternalTool *castToInternalTool();
+  inline const InternalTool *castToInternalTool() const;
+  inline ExternalTool *castToExternalTool();
+  inline const ExternalTool *castToExternalTool() const;
+
+ private:
+  const char *name_;
+  ToolChain &toolchain_;
+  ToolClass klass_;
+};
+
+// An "internal" tool -- carries out the steps needs to perform some
+// action (such as compilation or assembly) within the driver itself
+// (as opposed to via invocation of an external program).
+
+class InternalTool : public Tool {
+ public:
+  InternalTool(const char *name, ToolChain &tc);
+  virtual ~InternalTool();
+
+  // Given a specific action, perform the action now (as opposed to
+  // invoking an external program to perform the action). Return value
+  // is true for success, false otherwise.
+  virtual bool performAction(Compilation &compilation,
+                             const Action &jobAction,
+                             const ArtifactList &inputArtifacts,
+                             const Artifact &output) = 0;
+ private:
+};
+
+// An "external" tool -- carries out the steps needs to perform
+// an action via invocation of a program external to the driver.
+
+class ExternalTool : public Tool {
+ public:
+  ExternalTool(const char *name, ToolChain &tc);
+  virtual ~ExternalTool();
+
+  // Given a specific action, add a new Command to 'compilation' to
+  // carry out that action via the invocation of an external program
+  // (such as a linker or assembler). Return value is true for
+  // success, false otherwise.
+  virtual bool constructCommand(Compilation &compilation,
+                                const Action &jobAction,
+                                const ArtifactList &inputArtifacts,
+                                const Artifact &output) = 0;
+
+ private:
+};
+
+inline InternalTool *Tool::castToInternalTool() {
+  return klass_ == Internal ? static_cast<InternalTool*>(this) : nullptr;
+}
+
+inline const InternalTool *Tool::castToInternalTool() const {
+  return klass_ == Internal ? static_cast<const InternalTool*>(this) : nullptr;
+}
+
+inline ExternalTool *Tool::castToExternalTool() {
+  return klass_ == External ? static_cast<ExternalTool*>(this) : nullptr;
+}
+
+inline const ExternalTool *Tool::castToExternalTool() const {
+  return klass_ == External ? static_cast<const ExternalTool*>(this) : nullptr;
+}
+
+} // end namespace driver
+} // end namespace gollvm
+
+#endif // GOLLVM_DRIVER_TOOL_H
diff --git a/driver/ToolChain.cpp b/driver/ToolChain.cpp
new file mode 100644
index 0000000..ba8e805
--- /dev/null
+++ b/driver/ToolChain.cpp
@@ -0,0 +1,84 @@
+//===-- ToolChain.cpp -----------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Gollvm driver helper class ToolChain methods.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/raw_ostream.h"
+
+#include "Action.h"
+#include "Driver.h"
+#include "Tool.h"
+#include "ToolChain.h"
+
+namespace gollvm {
+namespace driver {
+
+ToolChain::ToolChain(Driver &driver,
+                     const llvm::Triple &targetTriple)
+    : driver_(driver),
+      triple_(targetTriple)
+{
+}
+
+ToolChain::~ToolChain()
+{
+}
+
+Tool *ToolChain::getCompiler()
+{
+  if (compiler_.get() == nullptr)
+    compiler_.reset(buildCompiler());
+  return compiler_.get();
+}
+
+Tool *ToolChain::getAssembler()
+{
+  if (assembler_.get() == nullptr)
+    assembler_.reset(buildAssembler());
+  return assembler_.get();
+}
+
+Tool *ToolChain::getLinker()
+{
+  if (linker_.get() == nullptr)
+    linker_.reset(buildLinker());
+  return linker_.get();
+}
+
+Tool *ToolChain::getTool(Action *act)
+{
+  assert(act != nullptr);
+  switch(act->type()) {
+    case Action::A_Compile:
+      return getCompiler();
+    case Action::A_Assemble:
+      return getAssembler();
+    case Action::A_Link:
+      return getLinker();
+    default:
+      assert(false);
+      return nullptr;
+  }
+  return nullptr;
+}
+
+std::string ToolChain::getFilePath(const char *afile)
+{
+  return driver_.getFilePath(afile, thisToolChain());
+}
+
+std::string ToolChain::getProgramPath(const char *atool)
+{
+  return driver_.getProgramPath(atool, thisToolChain());
+}
+
+} // end namespace driver
+} // end namespace gollvm
diff --git a/driver/ToolChain.h b/driver/ToolChain.h
new file mode 100644
index 0000000..962b9bc
--- /dev/null
+++ b/driver/ToolChain.h
@@ -0,0 +1,94 @@
+//===-- ToolChain.h -------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Defines the ToolChain class (helper for driver functionality).
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GOLLVM_DRIVER_TOOLCHAIN_H
+#define GOLLVM_DRIVER_TOOLCHAIN_H
+
+#include <string>
+#include "llvm/ADT/Triple.h"
+
+#include "Action.h"
+#include "Tool.h"
+
+namespace gollvm {
+namespace driver {
+
+class Tool;
+class Driver;
+
+typedef llvm::SmallVector<std::string, 8> pathlist;
+
+// Abstract class for a collection of compiler tools. A given toolchain
+// will create Tool objects for use in carrying out specific actions.
+
+class ToolChain {
+ public:
+  // Return compiler, assembler, linker tools
+  Tool *getCompiler();
+  Tool *getAssembler();
+  Tool *getLinker();
+
+  // Ask for correct tool based on action type
+  Tool *getTool(Action *act);
+
+  // Locate a given file within the file search path.
+  std::string getFilePath(const char *afile);
+
+  // Locate a program (tool) within the program search path.
+  std::string getProgramPath(const char *atool);
+
+  // Return filepath and programpath lists.
+  pathlist &programPaths() {
+    return programPaths_;
+  }
+  pathlist &filePaths() {
+    return filePaths_;
+  }
+
+  // Return driver.
+  Driver &driver() const { return driver_; }
+
+  virtual ~ToolChain();
+
+ protected:
+  ToolChain(Driver &driver,
+            const llvm::Triple &targetTriple);
+
+  // Build new tool of the appropriate type
+  virtual Tool *buildCompiler() = 0;
+  virtual Tool *buildAssembler() = 0;
+  virtual Tool *buildLinker() = 0;
+
+ private:
+  Driver &driver_;
+  llvm::Triple triple_;
+  std::unique_ptr<Tool> compiler_;
+  std::unique_ptr<Tool> assembler_;
+  std::unique_ptr<Tool> linker_;
+
+  // List of places to look for tools (ld, as, etc)
+  pathlist programPaths_;
+
+  // List of places to look for object files (ex: crt0.o)
+  pathlist filePaths_;
+
+  ToolChain &thisToolChain() {
+    ToolChain *tc = const_cast<ToolChain*>(this);
+    return *tc;
+  }
+};
+
+} // end namespace driver
+} // end namespace gollvm
+
+#endif // GOLLVM_DRIVER_TOOLCHAIN_H