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