diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver/Driver.cpp')
-rw-r--r-- | contrib/llvm/tools/clang/lib/Driver/Driver.cpp | 324 |
1 files changed, 186 insertions, 138 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp index 1c76509..ef26bfa 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp +++ b/contrib/llvm/tools/clang/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() << "." << "\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; } |