aboutsummaryrefslogtreecommitdiff
path: root/lib/Driver/Driver.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Driver/Driver.cpp')
-rw-r--r--lib/Driver/Driver.cpp324
1 files changed, 186 insertions, 138 deletions
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 588e8dfb47ac..ef26bfacdd64 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -11,6 +11,7 @@
#include "InputInfo.h"
#include "ToolChains.h"
#include "clang/Basic/Version.h"
+#include "clang/Config/config.h"
#include "clang/Driver/Action.h"
#include "clang/Driver/Compilation.h"
#include "clang/Driver/DriverDiagnostic.h"
@@ -19,27 +20,25 @@
#include "clang/Driver/Tool.h"
#include "clang/Driver/ToolChain.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/OwningPtr.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringSet.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Option/OptSpecifier.h"
#include "llvm/Option/OptTable.h"
#include "llvm/Option/Option.h"
-#include "llvm/Option/OptSpecifier.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/PrettyStackTrace.h"
+#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
#include <map>
-
-// FIXME: It would prevent us from including llvm-config.h
-// if config.h were included before system_error.h.
-#include "clang/Config/config.h"
+#include <memory>
using namespace clang::driver;
using namespace clang;
@@ -47,15 +46,14 @@ using namespace llvm::opt;
Driver::Driver(StringRef ClangExecutable,
StringRef DefaultTargetTriple,
- StringRef DefaultImageName,
DiagnosticsEngine &Diags)
: Opts(createDriverOptTable()), Diags(Diags), Mode(GCCMode),
ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT),
UseStdLib(true), DefaultTargetTriple(DefaultTargetTriple),
- DefaultImageName(DefaultImageName),
+ DefaultImageName("a.out"),
DriverTitle("clang LLVM compiler"),
- CCPrintOptionsFilename(0), CCPrintHeadersFilename(0),
- CCLogDiagnosticsFilename(0),
+ CCPrintOptionsFilename(nullptr), CCPrintHeadersFilename(nullptr),
+ CCLogDiagnosticsFilename(nullptr),
CCCPrintBindings(false),
CCPrintHeaders(false), CCLogDiagnostics(false),
CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true),
@@ -77,10 +75,7 @@ Driver::Driver(StringRef ClangExecutable,
Driver::~Driver() {
delete Opts;
- for (llvm::StringMap<ToolChain *>::iterator I = ToolChains.begin(),
- E = ToolChains.end();
- I != E; ++I)
- delete I->second;
+ llvm::DeleteContainerSeconds(ToolChains);
}
void Driver::ParseDriverMode(ArrayRef<const char *> Args) {
@@ -112,7 +107,7 @@ InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) {
unsigned IncludedFlagsBitmask;
unsigned ExcludedFlagsBitmask;
- llvm::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
+ std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
getIncludeExcludeOptionFlagMasks();
unsigned MissingArgIndex, MissingArgCount;
@@ -156,18 +151,21 @@ InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) {
// option we used to determine the final phase.
phases::ID Driver::getFinalPhase(const DerivedArgList &DAL, Arg **FinalPhaseArg)
const {
- Arg *PhaseArg = 0;
+ Arg *PhaseArg = nullptr;
phases::ID FinalPhase;
- // -{E,M,MM} only run the preprocessor.
+ // -{E,EP,P,M,MM} only run the preprocessor.
if (CCCIsCPP() ||
(PhaseArg = DAL.getLastArg(options::OPT_E)) ||
- (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM))) {
+ (PhaseArg = DAL.getLastArg(options::OPT__SLASH_EP)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT__SLASH_P))) {
FinalPhase = phases::Preprocess;
// -{fsyntax-only,-analyze,emit-ast,S} only run up to the compiler.
} else if ((PhaseArg = DAL.getLastArg(options::OPT_fsyntax_only)) ||
(PhaseArg = DAL.getLastArg(options::OPT_module_file_info)) ||
+ (PhaseArg = DAL.getLastArg(options::OPT_verify_pch)) ||
(PhaseArg = DAL.getLastArg(options::OPT_rewrite_objc)) ||
(PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) ||
(PhaseArg = DAL.getLastArg(options::OPT__migrate)) ||
@@ -191,10 +189,11 @@ const {
return FinalPhase;
}
-static Arg* MakeInputArg(const DerivedArgList &Args, OptTable *Opts,
+static Arg* MakeInputArg(DerivedArgList &Args, OptTable *Opts,
StringRef Value) {
Arg *A = new Arg(Opts->getOption(options::OPT_INPUT), Value,
Args.getBaseArgs().MakeIndex(Value), Value.data());
+ Args.AddSynthesizedArg(A);
A->claim();
return A;
}
@@ -336,9 +335,10 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
// FIXME: DefaultTargetTriple is used by the target-prefixed calls to as/ld
// and getToolChain is const.
if (IsCLMode()) {
- // clang-cl targets Win32.
+ // clang-cl targets MSVC-style Win32.
llvm::Triple T(DefaultTargetTriple);
- T.setOSName(llvm::Triple::getOSTypeName(llvm::Triple::Win32));
+ T.setOS(llvm::Triple::Win32);
+ T.setEnvironment(llvm::Triple::MSVC);
DefaultTargetTriple = T.str();
}
if (const Arg *A = Args->getLastArg(options::OPT_target))
@@ -378,8 +378,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) {
BuildInputs(C->getDefaultToolChain(), *TranslatedArgs, Inputs);
// Construct the list of abstract actions to perform for this compilation. On
- // Darwin target OSes this uses the driver-driver and universal actions.
- if (TC.getTriple().isOSDarwin())
+ // MachO targets this uses the driver-driver and universal actions.
+ if (TC.getTriple().isOSBinFormatMachO())
BuildUniversalActions(C->getDefaultToolChain(), C->getArgs(),
Inputs, C->getActions());
else
@@ -419,7 +419,6 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
// Suppress driver output and emit preprocessor output to temp file.
Mode = CPPMode;
CCGenDiagnostics = true;
- C.getArgs().AddFlagArg(0, Opts->getOption(options::OPT_frewrite_includes));
// Save the original job command(s).
std::string Cmd;
@@ -447,13 +446,14 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
bool IgnoreInput = false;
// Ignore input from stdin or any inputs that cannot be preprocessed.
- if (!strcmp(it->second->getValue(), "-")) {
+ // Check type first as not all linker inputs have a value.
+ if (types::getPreprocessedType(it->first) == types::TY_INVALID) {
+ IgnoreInput = true;
+ } else if (!strcmp(it->second->getValue(), "-")) {
Diag(clang::diag::note_drv_command_failed_diag_msg)
<< "Error generating preprocessed source(s) - ignoring input from stdin"
".";
IgnoreInput = true;
- } else if (types::getPreprocessedType(it->first) == types::TY_INVALID) {
- IgnoreInput = true;
}
if (IgnoreInput) {
@@ -491,7 +491,7 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
// Construct the list of abstract actions to perform for this compilation. On
// Darwin OSes this uses the driver-driver and builds universal actions.
const ToolChain &TC = C.getDefaultToolChain();
- if (TC.getTriple().isOSDarwin())
+ if (TC.getTriple().isOSBinFormatMachO())
BuildUniversalActions(TC, C.getArgs(), Inputs, C.getActions());
else
BuildActions(TC, C.getArgs(), Inputs, C.getActions());
@@ -519,17 +519,25 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
for (ArgStringList::const_iterator it = Files.begin(), ie = Files.end();
it != ie; ++it) {
Diag(clang::diag::note_drv_command_failed_diag_msg) << *it;
+ std::string Script = StringRef(*it).rsplit('.').first;
+ // In some cases (modules) we'll dump extra data to help with reproducing
+ // the crash into a directory next to the output.
+ SmallString<128> VFS;
+ if (llvm::sys::fs::exists(Script + ".cache")) {
+ Diag(clang::diag::note_drv_command_failed_diag_msg)
+ << Script + ".cache";
+ VFS = llvm::sys::path::filename(Script + ".cache");
+ llvm::sys::path::append(VFS, "vfs", "vfs.yaml");
+ }
std::string Err;
- std::string Script = StringRef(*it).rsplit('.').first;
Script += ".sh";
- llvm::raw_fd_ostream ScriptOS(
- Script.c_str(), Err, llvm::sys::fs::F_Excl | llvm::sys::fs::F_Binary);
+ llvm::raw_fd_ostream ScriptOS(Script.c_str(), Err, llvm::sys::fs::F_Excl);
if (!Err.empty()) {
Diag(clang::diag::note_drv_command_failed_diag_msg)
<< "Error generating run script: " + Script + " " + Err;
} else {
- // Append the new filename with correct preprocessed suffix.
+ // Replace the original filename with the preprocessed one.
size_t I, E;
I = Cmd.find("-main-file-name ");
assert (I != std::string::npos && "Expected to find -main-file-name");
@@ -542,6 +550,11 @@ void Driver::generateCompilationDiagnostics(Compilation &C,
E = I + OldFilename.size();
I = Cmd.rfind(" ", I) + 1;
Cmd.replace(I, E - I, NewFilename.data(), NewFilename.size());
+ if (!VFS.empty()) {
+ // Add the VFS overlay to the reproduction script.
+ I += NewFilename.size();
+ Cmd.insert(I, std::string(" -ivfsoverlay ") + VFS.c_str());
+ }
ScriptOS << Cmd;
Diag(clang::diag::note_drv_command_failed_diag_msg) << Script;
}
@@ -599,7 +612,7 @@ int Driver::ExecuteCompilation(const Compilation &C,
// Print extra information about abnormal failures, if possible.
//
// This is ad-hoc, but we don't want to be excessively noisy. If the result
- // status was 1, assume the command failed normally. In particular, if it
+ // status was 1, assume the command failed normally. In particular, if it
// was the compiler then assume it gave a reasonable error code. Failures
// in other tools are less common, and they generally have worse
// diagnostics, so always print the diagnostic there.
@@ -621,7 +634,7 @@ int Driver::ExecuteCompilation(const Compilation &C,
void Driver::PrintHelp(bool ShowHidden) const {
unsigned IncludedFlagsBitmask;
unsigned ExcludedFlagsBitmask;
- llvm::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
+ std::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) =
getIncludeExcludeOptionFlagMasks();
ExcludedFlagsBitmask |= options::NoDriverOption;
@@ -746,54 +759,37 @@ bool Driver::HandleImmediateArgs(const Compilation &C) {
}
if (C.getArgs().hasArg(options::OPT_print_multi_lib)) {
- // FIXME: We need tool chain support for this.
- llvm::outs() << ".;\n";
-
- switch (C.getDefaultToolChain().getTriple().getArch()) {
- default:
- break;
-
- case llvm::Triple::x86_64:
- llvm::outs() << "x86_64;@m64" << "\n";
- break;
+ const MultilibSet &Multilibs = TC.getMultilibs();
- case llvm::Triple::ppc64:
- llvm::outs() << "ppc64;@m64" << "\n";
- break;
-
- case llvm::Triple::ppc64le:
- llvm::outs() << "ppc64le;@m64" << "\n";
- break;
+ for (MultilibSet::const_iterator I = Multilibs.begin(), E = Multilibs.end();
+ I != E; ++I) {
+ llvm::outs() << *I << "\n";
}
return false;
}
- // FIXME: What is the difference between print-multi-directory and
- // print-multi-os-directory?
- if (C.getArgs().hasArg(options::OPT_print_multi_directory) ||
- C.getArgs().hasArg(options::OPT_print_multi_os_directory)) {
- switch (C.getDefaultToolChain().getTriple().getArch()) {
- default:
- case llvm::Triple::x86:
- case llvm::Triple::ppc:
- llvm::outs() << "." << "\n";
- break;
-
- case llvm::Triple::x86_64:
- llvm::outs() << "x86_64" << "\n";
- break;
-
- case llvm::Triple::ppc64:
- llvm::outs() << "ppc64" << "\n";
- break;
-
- case llvm::Triple::ppc64le:
- llvm::outs() << "ppc64le" << "\n";
- break;
+ if (C.getArgs().hasArg(options::OPT_print_multi_directory)) {
+ const MultilibSet &Multilibs = TC.getMultilibs();
+ for (MultilibSet::const_iterator I = Multilibs.begin(), E = Multilibs.end();
+ I != E; ++I) {
+ if (I->gccSuffix().empty())
+ llvm::outs() << ".\n";
+ else {
+ StringRef Suffix(I->gccSuffix());
+ assert(Suffix.front() == '/');
+ llvm::outs() << Suffix.substr(1) << "\n";
+ }
}
return false;
}
+ if (C.getArgs().hasArg(options::OPT_print_multi_os_directory)) {
+ // FIXME: This should print out "lib/../lib", "lib/../lib64", or
+ // "lib/../lib32" as appropriate for the toolchain. For now, print
+ // nothing because it's not supported yet.
+ return false;
+ }
+
return true;
}
@@ -867,7 +863,7 @@ void Driver::BuildUniversalActions(const ToolChain &TC,
// Validate the option here; we don't save the type here because its
// particular spelling may participate in other driver choices.
llvm::Triple::ArchType Arch =
- tools::darwin::getArchTypeForDarwinArchName(A->getValue());
+ tools::darwin::getArchTypeForMachOArchName(A->getValue());
if (Arch == llvm::Triple::UnknownArch) {
Diag(clang::diag::err_drv_invalid_arch_name)
<< A->getAsString(Args);
@@ -934,13 +930,12 @@ void Driver::BuildUniversalActions(const ToolChain &TC,
Actions.push_back(new DsymutilJobAction(Inputs, types::TY_dSYM));
}
- // Verify the output (debug information only) if we passed '-verify'.
- if (Args.hasArg(options::OPT_verify)) {
- ActionList VerifyInputs;
- VerifyInputs.push_back(Actions.back());
+ // Verify the debug info output.
+ if (Args.hasArg(options::OPT_verify_debug_info)) {
+ Action *VerifyInput = Actions.back();
Actions.pop_back();
- Actions.push_back(new VerifyJobAction(VerifyInputs,
- types::TY_Nothing));
+ Actions.push_back(new VerifyDebugInfoJobAction(VerifyInput,
+ types::TY_Nothing));
}
}
}
@@ -948,7 +943,7 @@ void Driver::BuildUniversalActions(const ToolChain &TC,
/// \brief Check that the file referenced by Value exists. If it doesn't,
/// issue a diagnostic and return false.
-static bool DiagnoseInputExistance(const Driver &D, const DerivedArgList &Args,
+static bool DiagnoseInputExistence(const Driver &D, const DerivedArgList &Args,
StringRef Value) {
if (!D.getCheckInputsExist())
return true;
@@ -969,18 +964,21 @@ static bool DiagnoseInputExistance(const Driver &D, const DerivedArgList &Args,
if (llvm::sys::fs::exists(Twine(Path)))
return true;
+ if (D.IsCLMode() && llvm::sys::Process::FindInEnvPath("LIB", Value))
+ return true;
+
D.Diag(clang::diag::err_drv_no_such_file) << Path.str();
return false;
}
// Construct a the list of inputs and their types.
-void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args,
+void Driver::BuildInputs(const ToolChain &TC, DerivedArgList &Args,
InputList &Inputs) const {
// Track the current user specified (-x) input. We also explicitly track the
// argument used to set the type; we only want to claim the type when we
// actually use it, so we warn about unused -x arguments.
types::ID InputType = types::TY_Nothing;
- Arg *InputTypeArg = 0;
+ Arg *InputTypeArg = nullptr;
// The last /TC or /TP option sets the input type to C or C++ globally.
if (Arg *TCTP = Args.getLastArg(options::OPT__SLASH_TC,
@@ -1029,7 +1027,8 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args,
// Otherwise emit an error but still use a valid type to avoid
// spurious errors (e.g., no inputs).
if (!Args.hasArgNoClaim(options::OPT_E) && !CCCIsCPP())
- Diag(clang::diag::err_drv_unknown_stdin_type);
+ Diag(IsCLMode() ? clang::diag::err_drv_unknown_stdin_type_clang_cl
+ : clang::diag::err_drv_unknown_stdin_type);
Ty = types::TY_C;
} else {
// Otherwise lookup by extension.
@@ -1075,19 +1074,19 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args,
Ty = InputType;
}
- if (DiagnoseInputExistance(*this, Args, Value))
+ if (DiagnoseInputExistence(*this, Args, Value))
Inputs.push_back(std::make_pair(Ty, A));
} else if (A->getOption().matches(options::OPT__SLASH_Tc)) {
StringRef Value = A->getValue();
- if (DiagnoseInputExistance(*this, Args, Value)) {
+ if (DiagnoseInputExistence(*this, Args, Value)) {
Arg *InputArg = MakeInputArg(Args, Opts, A->getValue());
Inputs.push_back(std::make_pair(types::TY_C, InputArg));
}
A->claim();
} else if (A->getOption().matches(options::OPT__SLASH_Tp)) {
StringRef Value = A->getValue();
- if (DiagnoseInputExistance(*this, Args, Value)) {
+ if (DiagnoseInputExistence(*this, Args, Value)) {
Arg *InputArg = MakeInputArg(Args, Opts, A->getValue());
Inputs.push_back(std::make_pair(types::TY_CXX, InputArg));
}
@@ -1177,7 +1176,7 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
// Construct the actions to perform.
ActionList LinkerInputs;
- ActionList SplitInputs;
+
llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases> PL;
for (unsigned i = 0, e = Inputs.size(); i != e; ++i) {
types::ID InputType = Inputs[i].first;
@@ -1211,18 +1210,18 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
Diag(clang::diag::warn_drv_preprocessed_input_file_unused)
<< InputArg->getAsString(Args)
<< !!FinalPhaseArg
- << FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "";
+ << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
else
Diag(clang::diag::warn_drv_input_file_unused)
<< InputArg->getAsString(Args)
<< getPhaseName(InitialPhase)
<< !!FinalPhaseArg
- << FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "";
+ << (FinalPhaseArg ? FinalPhaseArg->getOption().getName() : "");
continue;
}
// Build the pipeline for this file.
- OwningPtr<Action> Current(new InputAction(*InputArg, InputType));
+ std::unique_ptr<Action> Current(new InputAction(*InputArg, InputType));
for (SmallVectorImpl<phases::ID>::iterator
i = PL.begin(), e = PL.end(); i != e; ++i) {
phases::ID Phase = *i;
@@ -1234,7 +1233,7 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
// Queue linker inputs.
if (Phase == phases::Link) {
assert((i + 1) == e && "linking must be final compilation step.");
- LinkerInputs.push_back(Current.take());
+ LinkerInputs.push_back(Current.release());
break;
}
@@ -1245,14 +1244,14 @@ void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args,
continue;
// Otherwise construct the appropriate action.
- Current.reset(ConstructPhaseAction(Args, Phase, Current.take()));
+ Current.reset(ConstructPhaseAction(Args, Phase, Current.release()));
if (Current->getType() == types::TY_Nothing)
break;
}
// If we ended with something, add to the output list.
if (Current)
- Actions.push_back(Current.take());
+ Actions.push_back(Current.release());
}
// Add a link action if necessary.
@@ -1284,7 +1283,8 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
} else {
OutputTy = Input->getType();
if (!Args.hasFlag(options::OPT_frewrite_includes,
- options::OPT_fno_rewrite_includes, false))
+ options::OPT_fno_rewrite_includes, false) &&
+ !CCGenDiagnostics)
OutputTy = types::getPreprocessedType(OutputTy);
assert(OutputTy != types::TY_INVALID &&
"Cannot preprocess this input type!");
@@ -1314,6 +1314,8 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase,
return new CompileJobAction(Input, types::TY_AST);
} else if (Args.hasArg(options::OPT_module_file_info)) {
return new CompileJobAction(Input, types::TY_ModuleFile);
+ } else if (Args.hasArg(options::OPT_verify_pch)) {
+ return new VerifyPCHJobAction(Input, types::TY_Nothing);
} else if (IsUsingLTO(Args)) {
types::ID Output =
Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC;
@@ -1356,13 +1358,13 @@ void Driver::BuildJobs(Compilation &C) const {
if (NumOutputs > 1) {
Diag(clang::diag::err_drv_output_argument_with_multiple_files);
- FinalOutput = 0;
+ FinalOutput = nullptr;
}
}
// Collect the list of architectures.
llvm::StringSet<> ArchNames;
- if (C.getDefaultToolChain().getTriple().isOSDarwin()) {
+ if (C.getDefaultToolChain().getTriple().isOSBinFormatMachO()) {
for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end();
it != ie; ++it) {
Arg *A = *it;
@@ -1381,7 +1383,7 @@ void Driver::BuildJobs(Compilation &C) const {
//
// FIXME: This is a hack; find a cleaner way to integrate this into the
// process.
- const char *LinkingOutput = 0;
+ const char *LinkingOutput = nullptr;
if (isa<LipoJobAction>(A)) {
if (FinalOutput)
LinkingOutput = FinalOutput->getValue();
@@ -1391,7 +1393,7 @@ void Driver::BuildJobs(Compilation &C) const {
InputInfo II;
BuildJobsForAction(C, A, &C.getDefaultToolChain(),
- /*BoundArch*/0,
+ /*BoundArch*/nullptr,
/*AtTopLevel*/ true,
/*MultipleArchs*/ ArchNames.size() > 1,
/*LinkingOutput*/ LinkingOutput,
@@ -1448,7 +1450,7 @@ void Driver::BuildJobs(Compilation &C) const {
static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC,
const JobAction *JA,
const ActionList *&Inputs) {
- const Tool *ToolForJob = 0;
+ const Tool *ToolForJob = nullptr;
// See if we should look for a compiler with an integrated assembler. We match
// bottom up, so what we are actually looking for is an assembler job with a
@@ -1456,6 +1458,7 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC,
if (TC->useIntegratedAs() &&
!C.getArgs().hasArg(options::OPT_save_temps) &&
+ !C.getArgs().hasArg(options::OPT_via_file_asm) &&
!C.getArgs().hasArg(options::OPT__SLASH_FA) &&
!C.getArgs().hasArg(options::OPT__SLASH_Fa) &&
isa<AssembleJobAction>(JA) &&
@@ -1463,7 +1466,7 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC,
const Tool *Compiler =
TC->SelectTool(cast<JobAction>(**Inputs->begin()));
if (!Compiler)
- return NULL;
+ return nullptr;
if (Compiler->hasIntegratedAssembler()) {
Inputs = &(*Inputs)[0]->getInputs();
ToolForJob = Compiler;
@@ -1587,7 +1590,7 @@ void Driver::BuildJobsForAction(Compilation &C,
static const char *MakeCLOutputFilename(const ArgList &Args, StringRef ArgValue,
StringRef BaseName, types::ID FileType) {
SmallString<128> Filename = ArgValue;
-
+
if (ArgValue.empty()) {
// If the argument is empty, output to BaseName in the current dir.
Filename = BaseName;
@@ -1626,6 +1629,17 @@ const char *Driver::GetNamedOutputPath(Compilation &C,
return C.addResultFile(FinalOutput->getValue(), &JA);
}
+ // For /P, preprocess to file named after BaseInput.
+ if (C.getArgs().hasArg(options::OPT__SLASH_P)) {
+ assert(AtTopLevel && isa<PreprocessJobAction>(JA));
+ StringRef BaseName = llvm::sys::path::filename(BaseInput);
+ StringRef NameArg;
+ if (Arg *A = C.getArgs().getLastArg(options::OPT__SLASH_Fi))
+ NameArg = A->getValue();
+ return C.addResultFile(MakeCLOutputFilename(C.getArgs(), NameArg, BaseName,
+ types::TY_PP_C), &JA);
+ }
+
// Default to writing to stdout?
if (AtTopLevel && !CCGenDiagnostics &&
(isa<PreprocessJobAction>(JA) || JA.getType() == types::TY_ModuleFile))
@@ -1831,8 +1845,7 @@ std::string Driver::GetProgramPath(const char *Name,
std::string Driver::GetTemporaryPath(StringRef Prefix, const char *Suffix)
const {
SmallString<128> Path;
- llvm::error_code EC =
- llvm::sys::fs::createTemporaryFile(Prefix, Suffix, Path);
+ std::error_code EC = llvm::sys::fs::createTemporaryFile(Prefix, Suffix, Path);
if (EC) {
Diag(clang::diag::err_unable_to_make_temp) << EC.message();
return "";
@@ -1854,36 +1867,43 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple,
llvm::Triple Target(llvm::Triple::normalize(DefaultTargetTriple));
- // Handle Darwin-specific options available here.
- if (Target.isOSDarwin()) {
+ // Handle Apple-specific options available here.
+ if (Target.isOSBinFormatMachO()) {
// If an explict Darwin arch name is given, that trumps all.
if (!DarwinArchName.empty()) {
- Target.setArch(
- tools::darwin::getArchTypeForDarwinArchName(DarwinArchName));
+ tools::darwin::setTripleTypeForMachOArchName(Target, DarwinArchName);
return Target;
}
// Handle the Darwin '-arch' flag.
if (Arg *A = Args.getLastArg(options::OPT_arch)) {
- llvm::Triple::ArchType DarwinArch
- = tools::darwin::getArchTypeForDarwinArchName(A->getValue());
- if (DarwinArch != llvm::Triple::UnknownArch)
- Target.setArch(DarwinArch);
+ StringRef ArchName = A->getValue();
+ tools::darwin::setTripleTypeForMachOArchName(Target, ArchName);
}
}
- // Handle pseudo-target flags '-EL' and '-EB'.
- if (Arg *A = Args.getLastArg(options::OPT_EL, options::OPT_EB)) {
- if (A->getOption().matches(options::OPT_EL)) {
+ // Handle pseudo-target flags '-mlittle-endian'/'-EL' and
+ // '-mbig-endian'/'-EB'.
+ if (Arg *A = Args.getLastArg(options::OPT_mlittle_endian,
+ options::OPT_mbig_endian)) {
+ if (A->getOption().matches(options::OPT_mlittle_endian)) {
if (Target.getArch() == llvm::Triple::mips)
Target.setArch(llvm::Triple::mipsel);
else if (Target.getArch() == llvm::Triple::mips64)
Target.setArch(llvm::Triple::mips64el);
+ else if (Target.getArch() == llvm::Triple::aarch64_be)
+ Target.setArch(llvm::Triple::aarch64);
+ else if (Target.getArch() == llvm::Triple::arm64_be)
+ Target.setArch(llvm::Triple::arm64);
} else {
if (Target.getArch() == llvm::Triple::mipsel)
Target.setArch(llvm::Triple::mips);
else if (Target.getArch() == llvm::Triple::mips64el)
Target.setArch(llvm::Triple::mips64);
+ else if (Target.getArch() == llvm::Triple::aarch64)
+ Target.setArch(llvm::Triple::aarch64_be);
+ else if (Target.getArch() == llvm::Triple::arm64)
+ Target.setArch(llvm::Triple::arm64_be);
}
}
@@ -1893,20 +1913,27 @@ static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple,
Target.getOS() == llvm::Triple::Minix)
return Target;
- // Handle pseudo-target flags '-m32' and '-m64'.
- // FIXME: Should this information be in llvm::Triple?
- if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) {
- if (A->getOption().matches(options::OPT_m32)) {
- if (Target.getArch() == llvm::Triple::x86_64)
- Target.setArch(llvm::Triple::x86);
- if (Target.getArch() == llvm::Triple::ppc64)
- Target.setArch(llvm::Triple::ppc);
- } else {
- if (Target.getArch() == llvm::Triple::x86)
- Target.setArch(llvm::Triple::x86_64);
- if (Target.getArch() == llvm::Triple::ppc)
- Target.setArch(llvm::Triple::ppc64);
+ // Handle pseudo-target flags '-m64', '-mx32', '-m32' and '-m16'.
+ if (Arg *A = Args.getLastArg(options::OPT_m64, options::OPT_mx32,
+ options::OPT_m32, options::OPT_m16)) {
+ llvm::Triple::ArchType AT = llvm::Triple::UnknownArch;
+
+ if (A->getOption().matches(options::OPT_m64))
+ AT = Target.get64BitArchVariant().getArch();
+ else if (A->getOption().matches(options::OPT_mx32) &&
+ Target.get64BitArchVariant().getArch() == llvm::Triple::x86_64) {
+ AT = llvm::Triple::x86_64;
+ Target.setEnvironment(llvm::Triple::GNUX32);
+ } else if (A->getOption().matches(options::OPT_m32))
+ AT = Target.get32BitArchVariant().getArch();
+ else if (A->getOption().matches(options::OPT_m16) &&
+ Target.get32BitArchVariant().getArch() == llvm::Triple::x86) {
+ AT = llvm::Triple::x86;
+ Target.setEnvironment(llvm::Triple::CODE16);
}
+
+ if (AT != llvm::Triple::UnknownArch)
+ Target.setArch(AT);
}
return Target;
@@ -1926,13 +1953,7 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
case llvm::Triple::Darwin:
case llvm::Triple::MacOSX:
case llvm::Triple::IOS:
- if (Target.getArch() == llvm::Triple::x86 ||
- Target.getArch() == llvm::Triple::x86_64 ||
- Target.getArch() == llvm::Triple::arm ||
- Target.getArch() == llvm::Triple::thumb)
- TC = new toolchains::DarwinClang(*this, Target, Args);
- else
- TC = new toolchains::Darwin_Generic_GCC(*this, Target, Args);
+ TC = new toolchains::DarwinClang(*this, Target, Args);
break;
case llvm::Triple::DragonFly:
TC = new toolchains::DragonFly(*this, Target, Args);
@@ -1962,10 +1983,29 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
TC = new toolchains::Solaris(*this, Target, Args);
break;
case llvm::Triple::Win32:
- TC = new toolchains::Windows(*this, Target, Args);
+ switch (Target.getEnvironment()) {
+ default:
+ if (Target.isOSBinFormatELF())
+ TC = new toolchains::Generic_ELF(*this, Target, Args);
+ else if (Target.isOSBinFormatMachO())
+ TC = new toolchains::MachO(*this, Target, Args);
+ else
+ TC = new toolchains::Generic_GCC(*this, Target, Args);
+ break;
+ case llvm::Triple::GNU:
+ // FIXME: We need a MinGW toolchain. Use the default Generic_GCC
+ // toolchain for now as the default case would below otherwise.
+ if (Target.isOSBinFormatELF())
+ TC = new toolchains::Generic_ELF(*this, Target, Args);
+ else
+ TC = new toolchains::Generic_GCC(*this, Target, Args);
+ break;
+ case llvm::Triple::MSVC:
+ case llvm::Triple::UnknownEnvironment:
+ TC = new toolchains::Windows(*this, Target, Args);
+ break;
+ }
break;
- case llvm::Triple::MinGW32:
- // FIXME: We need a MinGW toolchain. Fallthrough for now.
default:
// TCE is an OSless target
if (Target.getArchName() == "tce") {
@@ -1981,6 +2021,14 @@ const ToolChain &Driver::getToolChain(const ArgList &Args,
TC = new toolchains::XCore(*this, Target, Args);
break;
}
+ if (Target.isOSBinFormatELF()) {
+ TC = new toolchains::Generic_ELF(*this, Target, Args);
+ break;
+ }
+ if (Target.getObjectFormat() == llvm::Triple::MachO) {
+ TC = new toolchains::MachO(*this, Target, Args);
+ break;
+ }
TC = new toolchains::Generic_GCC(*this, Target, Args);
break;
}