diff options
author | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
---|---|---|
committer | dim <dim@FreeBSD.org> | 2014-03-21 17:53:59 +0000 |
commit | 9cedb8bb69b89b0f0c529937247a6a80cabdbaec (patch) | |
tree | c978f0e9ec1ab92dc8123783f30b08a7fd1e2a39 /contrib/llvm/tools/clang/lib/Driver/Driver.cpp | |
parent | 03fdc2934eb61c44c049a02b02aa974cfdd8a0eb (diff) | |
download | FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.zip FreeBSD-src-9cedb8bb69b89b0f0c529937247a6a80cabdbaec.tar.gz |
MFC 261991:
Upgrade our copy of llvm/clang to 3.4 release. This version supports
all of the features in the current working draft of the upcoming C++
standard, provisionally named C++1y.
The code generator's performance is greatly increased, and the loop
auto-vectorizer is now enabled at -Os and -O2 in addition to -O3. The
PowerPC backend has made several major improvements to code generation
quality and compile time, and the X86, SPARC, ARM32, Aarch64 and SystemZ
backends have all seen major feature work.
Release notes for llvm and clang can be found here:
<http://llvm.org/releases/3.4/docs/ReleaseNotes.html>
<http://llvm.org/releases/3.4/tools/clang/docs/ReleaseNotes.html>
MFC 262121 (by emaste):
Update lldb for clang/llvm 3.4 import
This commit largely restores the lldb source to the upstream r196259
snapshot with the addition of threaded inferior support and a few bug
fixes.
Specific upstream lldb revisions restored include:
SVN git
181387 779e6ac
181703 7bef4e2
182099 b31044e
182650 f2dcf35
182683 0d91b80
183862 15c1774
183929 99447a6
184177 0b2934b
184948 4dc3761
184954 007e7bc
186990 eebd175
Sponsored by: DARPA, AFRL
MFC 262186 (by emaste):
Fix mismerge in r262121
A break statement was lost in the merge. The error had no functional
impact, but restore it to reduce the diff against upstream.
MFC 262303:
Pull in r197521 from upstream clang trunk (by rdivacky):
Use the integrated assembler by default on FreeBSD/ppc and ppc64.
Requested by: jhibbits
MFC 262611:
Pull in r196874 from upstream llvm trunk:
Fix a crash that occurs when PWD is invalid.
MCJIT needs to be able to run in hostile environments, even when PWD
is invalid. There's no need to crash MCJIT in this case.
The obvious fix is to simply leave MCContext's CompilationDir empty
when PWD can't be determined. This way, MCJIT clients,
and other clients that link with LLVM don't need a valid working directory.
If we do want to guarantee valid CompilationDir, that should be done
only for clients of getCompilationDir(). This is as simple as checking
for an empty string.
The only current use of getCompilationDir is EmitGenDwarfInfo, which
won't conceivably run with an invalid working dir. However, in the
purely hypothetically and untestable case that this happens, the
AT_comp_dir will be omitted from the compilation_unit DIE.
This should help fix assertions occurring with ports-mgmt/tinderbox,
when it is using jails, and sometimes invalidates clang's current
working directory.
Reported by: decke
MFC 262809:
Pull in r203007 from upstream clang trunk:
Don't produce an alias between destructors with different calling conventions.
Fixes pr19007.
(Please note that is an LLVM PR identifier, not a FreeBSD one.)
This should fix Firefox and/or libxul crashes (due to problems with
regparm/stdcall calling conventions) on i386.
Reported by: multiple users on freebsd-current
PR: bin/187103
MFC 263048:
Repair recognition of "CC" as an alias for the C++ compiler, since it
was silently broken by upstream for a Windows-specific use-case.
Apparently some versions of CMake still rely on this archaic feature...
Reported by: rakuco
MFC 263049:
Garbage collect the old way of adding the libstdc++ include directories
in clang's InitHeaderSearch.cpp. This has been superseded by David
Chisnall's commit in r255321.
Moreover, if libc++ is used, the libstdc++ include directories should
not be in the search path at all. These directories are now only used
if you pass -stdlib=libstdc++.
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/Driver.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Driver.cpp | 512 |
1 files changed, 368 insertions, 144 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp index b541a55..49beb93 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp @@ -12,19 +12,22 @@ #include "ToolChains.h" #include "clang/Basic/Version.h" #include "clang/Driver/Action.h" -#include "clang/Driver/Arg.h" -#include "clang/Driver/ArgList.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Job.h" -#include "clang/Driver/OptTable.h" -#include "clang/Driver/Option.h" #include "clang/Driver/Options.h" #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/StringSet.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.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" @@ -40,20 +43,21 @@ using namespace clang::driver; using namespace clang; +using namespace llvm::opt; Driver::Driver(StringRef ClangExecutable, StringRef DefaultTargetTriple, StringRef DefaultImageName, DiagnosticsEngine &Diags) - : Opts(createDriverOptTable()), Diags(Diags), + : Opts(createDriverOptTable()), Diags(Diags), Mode(GCCMode), ClangExecutable(ClangExecutable), SysRoot(DEFAULT_SYSROOT), UseStdLib(true), DefaultTargetTriple(DefaultTargetTriple), DefaultImageName(DefaultImageName), DriverTitle("clang LLVM compiler"), CCPrintOptionsFilename(0), CCPrintHeadersFilename(0), - CCLogDiagnosticsFilename(0), CCCIsCXX(false), - CCCIsCPP(false),CCCEcho(false), CCCPrintBindings(false), - CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false), + CCLogDiagnosticsFilename(0), + CCCPrintBindings(false), + CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false), CCCGenericGCCName(""), CheckInputsExist(true), CCCUsePCH(true), SuppressMissingInputWarning(false) { @@ -79,11 +83,43 @@ Driver::~Driver() { delete I->second; } +void Driver::ParseDriverMode(ArrayRef<const char *> Args) { + const std::string OptName = + getOpts().getOption(options::OPT_driver_mode).getPrefixedName(); + + for (size_t I = 0, E = Args.size(); I != E; ++I) { + const StringRef Arg = Args[I]; + if (!Arg.startswith(OptName)) + continue; + + const StringRef Value = Arg.drop_front(OptName.size()); + const unsigned M = llvm::StringSwitch<unsigned>(Value) + .Case("gcc", GCCMode) + .Case("g++", GXXMode) + .Case("cpp", CPPMode) + .Case("cl", CLMode) + .Default(~0U); + + if (M != ~0U) + Mode = static_cast<DriverMode>(M); + else + Diag(diag::err_drv_unsupported_option_argument) << OptName << Value; + } +} + InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) { llvm::PrettyStackTraceString CrashInfo("Command line argument parsing"); + + unsigned IncludedFlagsBitmask; + unsigned ExcludedFlagsBitmask; + llvm::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) = + getIncludeExcludeOptionFlagMasks(); + unsigned MissingArgIndex, MissingArgCount; InputArgList *Args = getOpts().ParseArgs(ArgList.begin(), ArgList.end(), - MissingArgIndex, MissingArgCount); + MissingArgIndex, MissingArgCount, + IncludedFlagsBitmask, + ExcludedFlagsBitmask); // Check for missing argument error. if (MissingArgCount) @@ -107,6 +143,11 @@ InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) { } } + for (arg_iterator it = Args->filtered_begin(options::OPT_UNKNOWN), + ie = Args->filtered_end(); it != ie; ++it) { + Diags.Report(diag::err_drv_unknown_argument) << (*it) ->getAsString(*Args); + } + return Args; } @@ -119,7 +160,7 @@ const { phases::ID FinalPhase; // -{E,M,MM} only run the preprocessor. - if (CCCIsCPP || + if (CCCIsCPP() || (PhaseArg = DAL.getLastArg(options::OPT_E)) || (PhaseArg = DAL.getLastArg(options::OPT_M, options::OPT_MM))) { FinalPhase = phases::Preprocess; @@ -150,6 +191,14 @@ const { return FinalPhase; } +static Arg* MakeInputArg(const DerivedArgList &Args, OptTable *Opts, + StringRef Value) { + Arg *A = new Arg(Opts->getOption(options::OPT_INPUT), Value, + Args.getBaseArgs().MakeIndex(Value), Value.data()); + A->claim(); + return A; +} + DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { DerivedArgList *DAL = new DerivedArgList(Args); @@ -215,6 +264,14 @@ DerivedArgList *Driver::TranslateInputArgs(const InputArgList &Args) const { } } + // Pick up inputs via the -- option. + if (A->getOption().matches(options::OPT__DASH_DASH)) { + A->claim(); + for (unsigned i = 0, e = A->getNumValues(); i != e; ++i) + DAL->append(MakeInputArg(*DAL, Opts, A->getValue(i))); + continue; + } + DAL->append(*it); } @@ -241,16 +298,20 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { StringRef CompilerPath = env; while (!CompilerPath.empty()) { std::pair<StringRef, StringRef> Split - = CompilerPath.split(llvm::sys::PathSeparator); + = CompilerPath.split(llvm::sys::EnvPathSeparator); PrefixDirs.push_back(Split.first); CompilerPath = Split.second; } } + // We look for the driver mode option early, because the mode can affect + // how other options are parsed. + ParseDriverMode(ArgList.slice(1)); + // FIXME: What are we going to do with -V and -b? // FIXME: This stuff needs to go into the Compilation, not the driver. - bool CCCPrintOptions, CCCPrintActions; + bool CCCPrintActions; InputArgList *Args = ParseArgStrings(ArgList.slice(1)); @@ -266,17 +327,20 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { // should be outside in the client; the parts that aren't should have proper // options, either by introducing new ones or by overloading gcc ones like -V // or -b. - CCCPrintOptions = Args->hasArg(options::OPT_ccc_print_options); CCCPrintActions = Args->hasArg(options::OPT_ccc_print_phases); CCCPrintBindings = Args->hasArg(options::OPT_ccc_print_bindings); - CCCIsCXX = Args->hasArg(options::OPT_ccc_cxx) || CCCIsCXX; - CCCEcho = Args->hasArg(options::OPT_ccc_echo); if (const Arg *A = Args->getLastArg(options::OPT_ccc_gcc_name)) CCCGenericGCCName = A->getValue(); CCCUsePCH = Args->hasFlag(options::OPT_ccc_pch_is_pch, options::OPT_ccc_pch_is_pth); // FIXME: DefaultTargetTriple is used by the target-prefixed calls to as/ld // and getToolChain is const. + if (IsCLMode()) { + // clang-cl targets Win32. + llvm::Triple T(DefaultTargetTriple); + T.setOSName(llvm::Triple::getOSTypeName(llvm::Triple::Win32)); + DefaultTargetTriple = T.str(); + } if (const Arg *A = Args->getLastArg(options::OPT_target)) DefaultTargetTriple = A->getValue(); if (const Arg *A = Args->getLastArg(options::OPT_ccc_install_dir)) @@ -289,6 +353,8 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { } if (const Arg *A = Args->getLastArg(options::OPT__sysroot_EQ)) SysRoot = A->getValue(); + if (const Arg *A = Args->getLastArg(options::OPT__dyld_prefix_EQ)) + DyldPrefix = A->getValue(); if (Args->hasArg(options::OPT_nostdlib)) UseStdLib = false; @@ -304,18 +370,12 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { // The compilation takes ownership of Args. Compilation *C = new Compilation(*this, TC, Args, TranslatedArgs); - // FIXME: This behavior shouldn't be here. - if (CCCPrintOptions) { - PrintOptions(C->getInputArgs()); - return C; - } - if (!HandleImmediateArgs(*C)) return C; // Construct the list of inputs. InputList Inputs; - BuildInputs(C->getDefaultToolChain(), C->getArgs(), Inputs); + 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. @@ -357,7 +417,7 @@ void Driver::generateCompilationDiagnostics(Compilation &C, "crash backtrace, preprocessed source, and associated run script."; // Suppress driver output and emit preprocessor output to temp file. - CCCIsCPP = true; + Mode = CPPMode; CCGenDiagnostics = true; C.getArgs().AddFlagArg(0, Opts->getOption(options::OPT_frewrite_includes)); @@ -365,11 +425,11 @@ void Driver::generateCompilationDiagnostics(Compilation &C, std::string Cmd; llvm::raw_string_ostream OS(Cmd); if (FailingCommand) - C.PrintDiagnosticJob(OS, *FailingCommand); + FailingCommand->Print(OS, "\n", /*Quote*/ false, /*CrashReport*/ true); else // Crash triggered by FORCE_CLANG_DIAGNOSTICS_CRASH, which doesn't have an // associated FailingCommand, so just pass all jobs. - C.PrintDiagnosticJob(OS, C.getJobs()); + C.getJobs().Print(OS, "\n", /*Quote*/ false, /*CrashReport*/ true); OS.flush(); // Keep track of whether we produce any errors while trying to produce @@ -463,9 +523,8 @@ void Driver::generateCompilationDiagnostics(Compilation &C, std::string Err; std::string Script = StringRef(*it).rsplit('.').first; Script += ".sh"; - llvm::raw_fd_ostream ScriptOS(Script.c_str(), Err, - llvm::raw_fd_ostream::F_Excl | - llvm::raw_fd_ostream::F_Binary); + llvm::raw_fd_ostream ScriptOS( + Script.c_str(), Err, llvm::sys::fs::F_Excl | llvm::sys::fs::F_Binary); if (!Err.empty()) { Diag(clang::diag::note_drv_command_failed_diag_msg) << "Error generating run script: " + Script + " " + Err; @@ -503,7 +562,7 @@ int Driver::ExecuteCompilation(const Compilation &C, SmallVectorImpl< std::pair<int, const Command *> > &FailingCommands) const { // Just print if -### was present. if (C.getArgs().hasArg(options::OPT__HASH_HASH_HASH)) { - C.PrintJob(llvm::errs(), C.getJobs(), "\n", true); + C.getJobs().Print(llvm::errs(), "\n", true); return 0; } @@ -559,28 +618,18 @@ int Driver::ExecuteCompilation(const Compilation &C, return 0; } -void Driver::PrintOptions(const ArgList &Args) const { - unsigned i = 0; - for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); - it != ie; ++it, ++i) { - Arg *A = *it; - llvm::errs() << "Option " << i << " - " - << "Name: \"" << A->getOption().getPrefixedName() << "\", " - << "Values: {"; - for (unsigned j = 0; j < A->getNumValues(); ++j) { - if (j) - llvm::errs() << ", "; - llvm::errs() << '"' << A->getValue(j) << '"'; - } - llvm::errs() << "}\n"; - } -} - void Driver::PrintHelp(bool ShowHidden) const { + unsigned IncludedFlagsBitmask; + unsigned ExcludedFlagsBitmask; + llvm::tie(IncludedFlagsBitmask, ExcludedFlagsBitmask) = + getIncludeExcludeOptionFlagMasks(); + + ExcludedFlagsBitmask |= options::NoDriverOption; + if (!ShowHidden) + ExcludedFlagsBitmask |= HelpHidden; + getOpts().PrintHelp(llvm::outs(), Name.c_str(), DriverTitle.c_str(), - /*Include*/0, - /*Exclude*/options::NoDriverOption | - (ShowHidden ? 0 : options::HelpHidden)); + IncludedFlagsBitmask, ExcludedFlagsBitmask); } void Driver::PrintVersion(const Compilation &C, raw_ostream &OS) const { @@ -649,6 +698,10 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { } const ToolChain &TC = C.getDefaultToolChain(); + + if (C.getArgs().hasArg(options::OPT_v)) + TC.printVerboseInfo(llvm::errs()); + if (C.getArgs().hasArg(options::OPT_print_search_dirs)) { llvm::outs() << "programs: ="; for (ToolChain::path_list::const_iterator it = TC.getProgramPaths().begin(), @@ -707,6 +760,10 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { case llvm::Triple::ppc64: llvm::outs() << "ppc64;@m64" << "\n"; break; + + case llvm::Triple::ppc64le: + llvm::outs() << "ppc64le;@m64" << "\n"; + break; } return false; } @@ -729,6 +786,10 @@ bool Driver::HandleImmediateArgs(const Compilation &C) { case llvm::Triple::ppc64: llvm::outs() << "ppc64" << "\n"; break; + + case llvm::Triple::ppc64le: + llvm::outs() << "ppc64le" << "\n"; + break; } return false; } @@ -790,7 +851,7 @@ static bool ContainsCompileOrAssembleAction(const Action *A) { } void Driver::BuildUniversalActions(const ToolChain &TC, - const DerivedArgList &Args, + DerivedArgList &Args, const InputList &BAInputs, ActionList &Actions) const { llvm::PrettyStackTraceString CrashInfo("Building universal build actions"); @@ -885,6 +946,33 @@ 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, + StringRef Value) { + if (!D.getCheckInputsExist()) + return true; + + // stdin always exists. + if (Value == "-") + return true; + + SmallString<64> Path(Value); + if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory)) { + if (!llvm::sys::path::is_absolute(Path.str())) { + SmallString<64> Directory(WorkDir->getValue()); + llvm::sys::path::append(Directory, Value); + Path.assign(Directory); + } + } + + if (llvm::sys::fs::exists(Twine(Path))) + 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, InputList &Inputs) const { @@ -894,6 +982,31 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args, types::ID InputType = types::TY_Nothing; Arg *InputTypeArg = 0; + // The last /TC or /TP option sets the input type to C or C++ globally. + if (Arg *TCTP = Args.getLastArg(options::OPT__SLASH_TC, + options::OPT__SLASH_TP)) { + InputTypeArg = TCTP; + InputType = TCTP->getOption().matches(options::OPT__SLASH_TC) + ? types::TY_C : types::TY_CXX; + + arg_iterator it = Args.filtered_begin(options::OPT__SLASH_TC, + options::OPT__SLASH_TP); + const arg_iterator ie = Args.filtered_end(); + Arg *Previous = *it++; + bool ShowNote = false; + while (it != ie) { + Diag(clang::diag::warn_drv_overriding_flag_option) + << Previous->getSpelling() << (*it)->getSpelling(); + Previous = *it++; + ShowNote = true; + } + if (ShowNote) + Diag(clang::diag::note_drv_t_option_is_global); + + // No driver mode exposes -x and /TC or /TP; we don't support mixing them. + assert(!Args.hasArg(options::OPT_x) && "-x and /TC or /TP is not allowed"); + } + for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); it != ie; ++it) { Arg *A = *it; @@ -915,7 +1028,7 @@ 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) + if (!Args.hasArgNoClaim(options::OPT_E) && !CCCIsCPP()) Diag(clang::diag::err_drv_unknown_stdin_type); Ty = types::TY_C; } else { @@ -927,7 +1040,7 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args, Ty = TC.LookupTypeForExtension(Ext + 1); if (Ty == types::TY_INVALID) { - if (CCCIsCPP) + if (CCCIsCPP()) Ty = types::TY_C; else Ty = types::TY_Object; @@ -935,7 +1048,7 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args, // If the driver is invoked as C++ compiler (like clang++ or c++) it // should autodetect some input files as C++ for g++ compatibility. - if (CCCIsCXX) { + if (CCCIsCXX()) { types::ID OldTy = Ty; Ty = types::lookupCXXTypeForCType(Ty); @@ -962,25 +1075,23 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args, Ty = InputType; } - // Check that the file exists, if enabled. - if (CheckInputsExist && memcmp(Value, "-", 2) != 0) { - SmallString<64> Path(Value); - if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory)) { - if (!llvm::sys::path::is_absolute(Path.str())) { - SmallString<64> Directory(WorkDir->getValue()); - llvm::sys::path::append(Directory, Value); - Path.assign(Directory); - } - } - - bool exists = false; - if (llvm::sys::fs::exists(Path.c_str(), exists) || !exists) - Diag(clang::diag::err_drv_no_such_file) << Path.str(); - else - Inputs.push_back(std::make_pair(Ty, A)); - } else + if (DiagnoseInputExistance(*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)) { + 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)) { + Arg *InputArg = MakeInputArg(Args, Opts, A->getValue()); + Inputs.push_back(std::make_pair(types::TY_CXX, InputArg)); + } + A->claim(); } else if (A->getOption().hasFlag(options::LinkerInput)) { // Just treat as object type, we could make a special type for this if // necessary. @@ -1000,17 +1111,15 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args, } } } - if (CCCIsCPP && Inputs.empty()) { + if (CCCIsCPP() && Inputs.empty()) { // If called as standalone preprocessor, stdin is processed // if no other input is present. - unsigned Index = Args.getBaseArgs().MakeIndex("-"); - Arg *A = Opts->ParseOneArg(Args, Index); - A->claim(); + Arg *A = MakeInputArg(Args, Opts, "-"); Inputs.push_back(std::make_pair(types::TY_C, A)); } } -void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, +void Driver::BuildActions(const ToolChain &TC, DerivedArgList &Args, const InputList &Inputs, ActionList &Actions) const { llvm::PrettyStackTraceString CrashInfo("Building compilation actions"); @@ -1022,11 +1131,50 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, Arg *FinalPhaseArg; phases::ID FinalPhase = getFinalPhase(Args, &FinalPhaseArg); + if (FinalPhase == phases::Link && Args.hasArg(options::OPT_emit_llvm)) { + Diag(clang::diag::err_drv_emit_llvm_link); + } + // Reject -Z* at the top level, these options should never have been exposed // by gcc. if (Arg *A = Args.getLastArg(options::OPT_Z_Joined)) Diag(clang::diag::err_drv_use_of_Z_option) << A->getAsString(Args); + // Diagnose misuse of /Fo. + if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fo)) { + StringRef V = A->getValue(); + if (V.empty()) { + // It has to have a value. + Diag(clang::diag::err_drv_missing_argument) << A->getSpelling() << 1; + Args.eraseArg(options::OPT__SLASH_Fo); + } else if (Inputs.size() > 1 && !llvm::sys::path::is_separator(V.back())) { + // Check whether /Fo tries to name an output file for multiple inputs. + Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources) + << A->getSpelling() << V; + Args.eraseArg(options::OPT__SLASH_Fo); + } + } + + // Diagnose misuse of /Fa. + if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fa)) { + StringRef V = A->getValue(); + if (Inputs.size() > 1 && !llvm::sys::path::is_separator(V.back())) { + // Check whether /Fa tries to name an asm file for multiple inputs. + Diag(clang::diag::err_drv_out_file_argument_with_multiple_sources) + << A->getSpelling() << V; + Args.eraseArg(options::OPT__SLASH_Fa); + } + } + + // Diagnose misuse of /Fe. + if (Arg *A = Args.getLastArg(options::OPT__SLASH_Fe)) { + if (A->getValue()[0] == '\0') { + // It has to have a value. + Diag(clang::diag::err_drv_missing_argument) << A->getSpelling() << 1; + Args.eraseArg(options::OPT__SLASH_Fe); + } + } + // Construct the actions to perform. ActionList LinkerInputs; ActionList SplitInputs; @@ -1051,7 +1199,7 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, // Special case when final phase determined by binary name, rather than // by a command-line argument with a corresponding Arg. - if (CCCIsCPP) + if (CCCIsCPP()) Diag(clang::diag::warn_drv_input_file_unused_by_cpp) << InputArg->getAsString(Args) << getPhaseName(InitialPhase); @@ -1075,7 +1223,7 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, // Build the pipeline for this file. OwningPtr<Action> Current(new InputAction(*InputArg, InputType)); - for (llvm::SmallVector<phases::ID, phases::MaxNumberOfPhases>::iterator + for (SmallVectorImpl<phases::ID>::iterator i = PL.begin(), e = PL.end(); i != e; ++i) { phases::ID Phase = *i; @@ -1113,8 +1261,13 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, // If we are linking, claim any options which are obviously only used for // compilation. - if (FinalPhase == phases::Link && PL.size() == 1) + if (FinalPhase == phases::Link && PL.size() == 1) { Args.ClaimAllArgs(options::OPT_CompileOnly_Group); + Args.ClaimAllArgs(options::OPT_cl_compile_Group); + } + + // Claim ignored clang-cl options. + Args.ClaimAllArgs(options::OPT_cl_ignored_Group); } Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, @@ -1165,6 +1318,10 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, types::ID Output = Args.hasArg(options::OPT_S) ? types::TY_LTO_IR : types::TY_LTO_BC; return new CompileJobAction(Input, Output); + } else if (Args.hasArg(options::OPT_emit_llvm)) { + types::ID Output = + Args.hasArg(options::OPT_S) ? types::TY_LLVM_IR : types::TY_LLVM_BC; + return new CompileJobAction(Input, Output); } else { return new CompileJobAction(Input, types::TY_PP_Asm); } @@ -1177,15 +1334,9 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, } bool Driver::IsUsingLTO(const ArgList &Args) const { - // Check for -emit-llvm or -flto. - if (Args.hasArg(options::OPT_emit_llvm) || - Args.hasFlag(options::OPT_flto, options::OPT_fno_lto, false)) + if (Args.hasFlag(options::OPT_flto, options::OPT_fno_lto, false)) return true; - // Check for -O4. - if (const Arg *A = Args.getLastArg(options::OPT_O_Group)) - return A->getOption().matches(options::OPT_O4); - return false; } @@ -1256,6 +1407,9 @@ void Driver::BuildJobs(Compilation &C) const { // Claim -### here. (void) C.getArgs().hasArg(options::OPT__HASH_HASH_HASH); + // Claim --driver-mode, it was handled earlier. + (void) C.getArgs().hasArg(options::OPT_driver_mode); + for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end(); it != ie; ++it) { Arg *A = *it; @@ -1302,6 +1456,8 @@ static const Tool *SelectToolForJob(Compilation &C, const ToolChain *TC, if (TC->useIntegratedAs() && !C.getArgs().hasArg(options::OPT_save_temps) && + !C.getArgs().hasArg(options::OPT__SLASH_FA) && + !C.getArgs().hasArg(options::OPT__SLASH_Fa) && isa<AssembleJobAction>(JA) && Inputs->size() == 1 && isa<CompileJobAction>(*Inputs->begin())) { const Tool *Compiler = @@ -1424,6 +1580,38 @@ void Driver::BuildJobsForAction(Compilation &C, } } +/// \brief Create output filename based on ArgValue, which could either be a +/// full filename, filename without extension, or a directory. If ArgValue +/// does not provide a filename, then use BaseName, and use the extension +/// suitable for FileType. +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; + } else if (llvm::sys::path::is_separator(Filename.back())) { + // If the argument is a directory, output to BaseName in that dir. + llvm::sys::path::append(Filename, BaseName); + } + + if (!llvm::sys::path::has_extension(ArgValue)) { + // If the argument didn't provide an extension, then set it. + const char *Extension = types::getTypeTempSuffix(FileType, true); + + if (FileType == types::TY_Image && + Args.hasArg(options::OPT__SLASH_LD, options::OPT__SLASH_LDd)) { + // The output file is a dll. + Extension = "dll"; + } + + llvm::sys::path::replace_extension(Filename, Extension); + } + + return Args.MakeArgString(Filename.c_str()); +} + const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA, const char *BaseInput, @@ -1443,13 +1631,26 @@ const char *Driver::GetNamedOutputPath(Compilation &C, (isa<PreprocessJobAction>(JA) || JA.getType() == types::TY_ModuleFile)) return "-"; + // Is this the assembly listing for /FA? + if (JA.getType() == types::TY_PP_Asm && + (C.getArgs().hasArg(options::OPT__SLASH_FA) || + C.getArgs().hasArg(options::OPT__SLASH_Fa))) { + // Use /Fa and the input filename to determine the asm file name. + StringRef BaseName = llvm::sys::path::filename(BaseInput); + StringRef FaValue = C.getArgs().getLastArgValue(options::OPT__SLASH_Fa); + return C.addResultFile(MakeCLOutputFilename(C.getArgs(), FaValue, BaseName, + JA.getType()), &JA); + } + // Output to a temporary file? - if ((!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps)) || + if ((!AtTopLevel && !C.getArgs().hasArg(options::OPT_save_temps) && + !C.getArgs().hasArg(options::OPT__SLASH_Fo)) || CCGenDiagnostics) { StringRef Name = llvm::sys::path::filename(BaseInput); std::pair<StringRef, StringRef> Split = Name.split('.'); std::string TmpName = - GetTemporaryPath(Split.first, types::getTypeTempSuffix(JA.getType())); + GetTemporaryPath(Split.first, + types::getTypeTempSuffix(JA.getType(), IsCLMode())); return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str())); } @@ -1464,8 +1665,25 @@ const char *Driver::GetNamedOutputPath(Compilation &C, // Determine what the derived output name should be. const char *NamedOutput; - if (JA.getType() == types::TY_Image) { - if (MultipleArchs && BoundArch) { + + if (JA.getType() == types::TY_Object && + C.getArgs().hasArg(options::OPT__SLASH_Fo)) { + // The /Fo flag decides the object filename. + StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fo)->getValue(); + NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName, + types::TY_Object); + } else if (JA.getType() == types::TY_Image && + C.getArgs().hasArg(options::OPT__SLASH_Fe)) { + // The /Fe flag names the linked file. + StringRef Val = C.getArgs().getLastArg(options::OPT__SLASH_Fe)->getValue(); + NamedOutput = MakeCLOutputFilename(C.getArgs(), Val, BaseName, + types::TY_Image); + } else if (JA.getType() == types::TY_Image) { + if (IsCLMode()) { + // clang-cl uses BaseName for the executable name. + NamedOutput = MakeCLOutputFilename(C.getArgs(), "", BaseName, + types::TY_Image); + } else if (MultipleArchs && BoundArch) { SmallString<128> Output(DefaultImageName.c_str()); Output += "-"; Output.append(BoundArch); @@ -1473,7 +1691,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, } else NamedOutput = DefaultImageName.c_str(); } else { - const char *Suffix = types::getTypeTempSuffix(JA.getType()); + const char *Suffix = types::getTypeTempSuffix(JA.getType(), IsCLMode()); assert(Suffix && "All types used for output should have a suffix."); std::string::size_type End = std::string::npos; @@ -1504,7 +1722,8 @@ const char *Driver::GetNamedOutputPath(Compilation &C, StringRef Name = llvm::sys::path::filename(BaseInput); std::pair<StringRef, StringRef> Split = Name.split('.'); std::string TmpName = - GetTemporaryPath(Split.first, types::getTypeTempSuffix(JA.getType())); + GetTemporaryPath(Split.first, + types::getTypeTempSuffix(JA.getType(), IsCLMode())); return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str())); } } @@ -1532,17 +1751,15 @@ std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const { continue; if (Dir[0] == '=') Dir = SysRoot + Dir.substr(1); - llvm::sys::Path P(Dir); - P.appendComponent(Name); - bool Exists; - if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) + SmallString<128> P(Dir); + llvm::sys::path::append(P, Name); + if (llvm::sys::fs::exists(Twine(P))) return P.str(); } - llvm::sys::Path P(ResourceDir); - P.appendComponent(Name); - bool Exists; - if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) + SmallString<128> P(ResourceDir); + llvm::sys::path::append(P, Name); + if (llvm::sys::fs::exists(Twine(P))) return P.str(); const ToolChain::path_list &List = TC.getFilePaths(); @@ -1553,10 +1770,9 @@ std::string Driver::GetFilePath(const char *Name, const ToolChain &TC) const { continue; if (Dir[0] == '=') Dir = SysRoot + Dir.substr(1); - llvm::sys::Path P(Dir); - P.appendComponent(Name); - bool Exists; - if (!llvm::sys::fs::exists(P.str(), Exists) && Exists) + SmallString<128> P(Dir); + llvm::sys::path::append(P, Name); + if (llvm::sys::fs::exists(Twine(P))) return P.str(); } @@ -1571,69 +1787,58 @@ std::string Driver::GetProgramPath(const char *Name, // attempting to use this prefix when looking for program paths. for (Driver::prefix_list::const_iterator it = PrefixDirs.begin(), ie = PrefixDirs.end(); it != ie; ++it) { - bool IsDirectory; - if (!llvm::sys::fs::is_directory(*it, IsDirectory) && IsDirectory) { - llvm::sys::Path P(*it); - P.appendComponent(TargetSpecificExecutable); - if (P.canExecute()) return P.str(); - P.eraseComponent(); - P.appendComponent(Name); - if (P.canExecute()) return P.str(); + if (llvm::sys::fs::is_directory(*it)) { + SmallString<128> P(*it); + llvm::sys::path::append(P, TargetSpecificExecutable); + if (llvm::sys::fs::can_execute(Twine(P))) + return P.str(); + llvm::sys::path::remove_filename(P); + llvm::sys::path::append(P, Name); + if (llvm::sys::fs::can_execute(Twine(P))) + return P.str(); } else { - llvm::sys::Path P(*it + Name); - if (P.canExecute()) return P.str(); + SmallString<128> P(*it + Name); + if (llvm::sys::fs::can_execute(Twine(P))) + return P.str(); } } const ToolChain::path_list &List = TC.getProgramPaths(); for (ToolChain::path_list::const_iterator it = List.begin(), ie = List.end(); it != ie; ++it) { - llvm::sys::Path P(*it); - P.appendComponent(TargetSpecificExecutable); - if (P.canExecute()) return P.str(); - P.eraseComponent(); - P.appendComponent(Name); - if (P.canExecute()) return P.str(); + SmallString<128> P(*it); + llvm::sys::path::append(P, TargetSpecificExecutable); + if (llvm::sys::fs::can_execute(Twine(P))) + return P.str(); + llvm::sys::path::remove_filename(P); + llvm::sys::path::append(P, Name); + if (llvm::sys::fs::can_execute(Twine(P))) + return P.str(); } // If all else failed, search the path. - llvm::sys::Path - P(llvm::sys::Program::FindProgramByName(TargetSpecificExecutable)); + std::string P(llvm::sys::FindProgramByName(TargetSpecificExecutable)); if (!P.empty()) - return P.str(); + return P; - P = llvm::sys::Path(llvm::sys::Program::FindProgramByName(Name)); + P = llvm::sys::FindProgramByName(Name); if (!P.empty()) - return P.str(); + return P; return Name; } std::string Driver::GetTemporaryPath(StringRef Prefix, const char *Suffix) const { - // FIXME: This is lame; sys::Path should provide this function (in particular, - // it should know how to find the temporary files dir). - std::string Error; - const char *TmpDir = ::getenv("TMPDIR"); - if (!TmpDir) - TmpDir = ::getenv("TEMP"); - if (!TmpDir) - TmpDir = ::getenv("TMP"); - if (!TmpDir) - TmpDir = "/tmp"; - llvm::sys::Path P(TmpDir); - P.appendComponent(Prefix); - if (P.makeUnique(false, &Error)) { - Diag(clang::diag::err_unable_to_make_temp) << Error; + SmallString<128> Path; + llvm::error_code EC = + llvm::sys::fs::createTemporaryFile(Prefix, Suffix, Path); + if (EC) { + Diag(clang::diag::err_unable_to_make_temp) << EC.message(); return ""; } - // FIXME: Grumble, makeUnique sometimes leaves the file around!? PR3837. - P.eraseFromDisk(false, 0); - - if (Suffix) - P.appendSuffix(Suffix); - return P.str(); + return Path.str(); } /// \brief Compute target triple from args. @@ -1772,6 +1977,10 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, TC = new toolchains::Hexagon_TC(*this, Target, Args); break; } + if (Target.getArch() == llvm::Triple::xcore) { + TC = new toolchains::XCore(*this, Target, Args); + break; + } TC = new toolchains::Generic_GCC(*this, Target, Args); break; } @@ -1831,3 +2040,18 @@ bool Driver::GetReleaseVersion(const char *Str, unsigned &Major, HadExtra = true; return true; } + +std::pair<unsigned, unsigned> Driver::getIncludeExcludeOptionFlagMasks() const { + unsigned IncludedFlagsBitmask = 0; + unsigned ExcludedFlagsBitmask = options::NoDriverOption; + + if (Mode == CLMode) { + // Include CL and Core options. + IncludedFlagsBitmask |= options::CLOption; + IncludedFlagsBitmask |= options::CoreOption; + } else { + ExcludedFlagsBitmask |= options::CLOption; + } + + return std::make_pair(IncludedFlagsBitmask, ExcludedFlagsBitmask); +} |