From 2fe63e6adac0b9e5f52bcc3100b545e379417e6e Mon Sep 17 00:00:00 2001 From: Daniel Dunbar Date: Thu, 12 Mar 2009 18:40:18 +0000 Subject: [PATCH] Driver: Add majority of driver-driver implementation. - Compare to driverdriver.c if bored; not completely fair since the driver gets a bit more code in other places to handle binding archs (for Xarch) but not completely unfair either. Fear not, extra Action classes will have a happy home for their vtables soon. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66817 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticDriverKinds.def | 4 ++ include/clang/Basic/DiagnosticDriverKinds.td | 4 ++ include/clang/Driver/Action.h | 45 ++++++++++++ lib/Driver/Action.cpp | 15 ++++ lib/Driver/Driver.cpp | 70 ++++++++++++++++++- 5 files changed, 136 insertions(+), 2 deletions(-) create mode 100644 lib/Driver/Action.cpp diff --git a/include/clang/Basic/DiagnosticDriverKinds.def b/include/clang/Basic/DiagnosticDriverKinds.def index 9cdc6e387b..47332b6d19 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.def +++ b/include/clang/Basic/DiagnosticDriverKinds.def @@ -20,3 +20,7 @@ DIAG(err_drv_unknown_stdin_type, ERROR, "-E or -x required when input is from standard input") DIAG(err_drv_unknown_language, ERROR, "language not recognized: '%0'") +DIAG(err_drv_invalid_opt_with_multiple_archs, ERROR, + "option '%0' cannot be used with multiple -arch options") +DIAG(err_drv_invalid_output_with_multiple_archs, ERROR, + "cannot use '%0' output with multiple -arch options") diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td index 6301b6fb32..29eb259001 100644 --- a/include/clang/Basic/DiagnosticDriverKinds.td +++ b/include/clang/Basic/DiagnosticDriverKinds.td @@ -14,5 +14,9 @@ def err_drv_unsupported_opt : Error<"unsupported option '%0'"> def err_drv_unknown_stdin_type : Error< "-E or -x required when input is from standard input"> def err_drv_unknown_language : Error<"language not recognized: '%0'"> +def err_drv_invalid_opt_with_multiple_archs : Error< + "option '%0' cannot be used with multiple -arch options"> +def err_drv_invalid_output_with_multiple_archs : Error< + "cannot use '%0' output with multiple -arch options"> } diff --git a/include/clang/Driver/Action.h b/include/clang/Driver/Action.h index 12ded40de9..1eb754be16 100644 --- a/include/clang/Driver/Action.h +++ b/include/clang/Driver/Action.h @@ -10,6 +10,11 @@ #ifndef CLANG_DRIVER_ACTION_H_ #define CLANG_DRIVER_ACTION_H_ +#include "llvm/ADT/SmallVector.h" + +#include "clang/Driver/Types.h" +#include "clang/Driver/Util.h" + namespace clang { namespace driver { @@ -17,9 +22,49 @@ namespace driver { /// /// An action represents an edge in the compilation graph; typically /// it is a job to transform an input using some tool. +/// +/// The current driver is hard wired to expect actions which produce a +/// single primary output, at least in terms of controlling the +/// compilation. Actions can produce auxiliary files, but can only +/// produce a single output to feed into subsequent actions. class Action { + /// The output type of this action. + types::ID Type; + + ActionList Inputs; + +protected: + Action(const ActionList &_Inputs, types::ID _Type) : Type(_Type), + Inputs(_Inputs) {} public: + virtual ~Action(); + types::ID getType() { return Type; } +}; + +class InputAction : public Action { +}; + +class BindArchAction : public Action { + const char *ArchName; + +public: + BindArchAction(Action *Input, const char *_ArchName) + : Action(ActionList(&Input, &Input + 1), Input->getType()), + ArchName(_ArchName) { + } +}; + +class JobAction : public Action { +protected: + JobAction(ActionList &Inputs, types::ID Type) + : Action(Inputs, Type) {} +}; + +class LipoJobAction : public JobAction { +public: + LipoJobAction(ActionList &Inputs, types::ID Type) + : JobAction(Inputs, Type) {} }; } // end namespace driver diff --git a/lib/Driver/Action.cpp b/lib/Driver/Action.cpp new file mode 100644 index 0000000000..d9bfce1ad3 --- /dev/null +++ b/lib/Driver/Action.cpp @@ -0,0 +1,15 @@ +//===--- Action.cpp - Abstract compilation steps ------------------------*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "clang/Driver/Action.h" + +#include +using namespace clang::driver; + +Action::~Action() {} diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp index 2b763c6ae5..4ceeb77c15 100644 --- a/lib/Driver/Driver.cpp +++ b/lib/Driver/Driver.cpp @@ -19,6 +19,7 @@ #include "clang/Driver/Options.h" #include "clang/Driver/Types.h" +#include "llvm/ADT/StringMap.h" #include "llvm/Support/raw_ostream.h" #include "llvm/System/Path.h" using namespace clang::driver; @@ -171,8 +172,73 @@ void Driver::PrintActions(const ActionList &Actions) const { } void Driver::BuildUniversalActions(ArgList &Args, ActionList &Actions) { - // FIXME: Implement - BuildActions(Args, Actions); + llvm::StringMap Archs; + for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); + it != ie; ++it) { + Arg *A = *it; + + if (A->getOption().getId() == options::OPT_arch) { + // FIXME: We need to handle canonicalization of the specified + // arch? + + Archs[A->getValue(Args)] = A; + } + } + + // When there is no explicit arch for this platform, get one from + // the host so that -Xarch_ is handled correctly. + if (!Archs.size()) { + const char *Arch = Host->getArchName().c_str(); + Archs[Arch] = Args.MakeSeparateArg(getOpts().getOption(options::OPT_arch), + Arch); + } + + // FIXME: We killed off some others but these aren't yet detected in + // a functional manner. If we added information to jobs about which + // "auxiliary" files they wrote then we could detect the conflict + // these cause downstream. + if (Archs.size() > 1) { + // No recovery needed, the point of this is just to prevent + // overwriting the same files. + if (const Arg *A = Args.getLastArg(options::OPT_M_Group)) + Diag(clang::diag::err_drv_invalid_opt_with_multiple_archs) + << A->getOption().getName(); + if (const Arg *A = Args.getLastArg(options::OPT_save_temps)) + Diag(clang::diag::err_drv_invalid_opt_with_multiple_archs) + << A->getOption().getName(); + } + + ActionList SingleActions; + BuildActions(Args, SingleActions); + + // Add in arch binding and lipo (if necessary) for every top level + // action. + for (unsigned i = 0, e = SingleActions.size(); i != e; ++i) { + Action *Act = SingleActions[i]; + + // Make sure we can lipo this kind of output. If not (and it is an + // actual output) then we disallow, since we can't create an + // output file with the right name without overwriting it. We + // could remove this oddity by just changing the output names to + // include the arch, which would also fix + // -save-temps. Compatibility wins for now. + + if (Archs.size() > 1 && types::canLipoType(Act->getType())) + Diag(clang::diag::err_drv_invalid_output_with_multiple_archs) + << types::getTypeName(Act->getType()); + + ActionList Inputs; + for (llvm::StringMap::iterator it = Archs.begin(), ie = Archs.end(); + it != ie; ++it) + Inputs.push_back(new BindArchAction(Act, it->second->getValue(Args))); + + // Lipo if necessary, We do it this way because we need to set the + // arch flag so that -Xarch_ gets overwritten. + if (Inputs.size() == 1 || Act->getType() == types::TY_Nothing) + Actions.append(Inputs.begin(), Inputs.end()); + else + Actions.push_back(new LipoJobAction(Inputs, Act->getType())); + } } void Driver::BuildActions(ArgList &Args, ActionList &Actions) { -- 2.40.0