aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.def4
-rw-r--r--include/clang/Basic/DiagnosticDriverKinds.td4
-rw-r--r--include/clang/Driver/Action.h45
-rw-r--r--lib/Driver/Action.cpp15
-rw-r--r--lib/Driver/Driver.cpp70
5 files changed, 136 insertions, 2 deletions
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 <cassert>
+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<Arg *> 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<Arg*>::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) {