diff options
Diffstat (limited to 'contrib/llvm/tools/clang/lib/Driver')
18 files changed, 3038 insertions, 2243 deletions
diff --git a/contrib/llvm/tools/clang/lib/Driver/Action.cpp b/contrib/llvm/tools/clang/lib/Driver/Action.cpp index 52c0dbb..d7b4bc7 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Action.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Action.cpp @@ -27,6 +27,7 @@ const char *Action::getClassName(ActionClass AC) { case PreprocessJobClass: return "preprocessor"; case PrecompileJobClass: return "precompiler"; case AnalyzeJobClass: return "analyzer"; + case MigrateJobClass: return "migrator"; case CompileJobClass: return "compiler"; case AssembleJobClass: return "assembler"; case LinkJobClass: return "linker"; @@ -38,14 +39,20 @@ const char *Action::getClassName(ActionClass AC) { llvm_unreachable("invalid class"); } +void InputAction::anchor() {} + InputAction::InputAction(const Arg &_Input, types::ID _Type) : Action(InputClass, _Type), Input(_Input) { } +void BindArchAction::anchor() {} + BindArchAction::BindArchAction(Action *Input, const char *_ArchName) : Action(BindArchClass, Input, Input->getType()), ArchName(_ArchName) { } +void JobAction::anchor() {} + JobAction::JobAction(ActionClass Kind, Action *Input, types::ID Type) : Action(Kind, Input, Type) { } @@ -54,38 +61,62 @@ JobAction::JobAction(ActionClass Kind, const ActionList &Inputs, types::ID Type) : Action(Kind, Inputs, Type) { } +void PreprocessJobAction::anchor() {} + PreprocessJobAction::PreprocessJobAction(Action *Input, types::ID OutputType) : JobAction(PreprocessJobClass, Input, OutputType) { } +void PrecompileJobAction::anchor() {} + PrecompileJobAction::PrecompileJobAction(Action *Input, types::ID OutputType) : JobAction(PrecompileJobClass, Input, OutputType) { } +void AnalyzeJobAction::anchor() {} + AnalyzeJobAction::AnalyzeJobAction(Action *Input, types::ID OutputType) : JobAction(AnalyzeJobClass, Input, OutputType) { } +void MigrateJobAction::anchor() {} + +MigrateJobAction::MigrateJobAction(Action *Input, types::ID OutputType) + : JobAction(MigrateJobClass, Input, OutputType) { +} + +void CompileJobAction::anchor() {} + CompileJobAction::CompileJobAction(Action *Input, types::ID OutputType) : JobAction(CompileJobClass, Input, OutputType) { } +void AssembleJobAction::anchor() {} + AssembleJobAction::AssembleJobAction(Action *Input, types::ID OutputType) : JobAction(AssembleJobClass, Input, OutputType) { } +void LinkJobAction::anchor() {} + LinkJobAction::LinkJobAction(ActionList &Inputs, types::ID Type) : JobAction(LinkJobClass, Inputs, Type) { } +void LipoJobAction::anchor() {} + LipoJobAction::LipoJobAction(ActionList &Inputs, types::ID Type) : JobAction(LipoJobClass, Inputs, Type) { } +void DsymutilJobAction::anchor() {} + DsymutilJobAction::DsymutilJobAction(ActionList &Inputs, types::ID Type) : JobAction(DsymutilJobClass, Inputs, Type) { } +void VerifyJobAction::anchor() {} + VerifyJobAction::VerifyJobAction(ActionList &Inputs, types::ID Type) : JobAction(VerifyJobClass, Inputs, Type) { } diff --git a/contrib/llvm/tools/clang/lib/Driver/Arg.cpp b/contrib/llvm/tools/clang/lib/Driver/Arg.cpp index 39b7e55..c0a2a50 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Arg.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Arg.cpp @@ -61,7 +61,7 @@ void Arg::dump() const { } std::string Arg::getAsString(const ArgList &Args) const { - llvm::SmallString<256> Res; + SmallString<256> Res; llvm::raw_svector_ostream OS(Res); ArgStringList ASL; @@ -94,7 +94,7 @@ void Arg::render(const ArgList &Args, ArgStringList &Output) const { break; case Option::RenderCommaJoinedStyle: { - llvm::SmallString<256> Res; + SmallString<256> Res; llvm::raw_svector_ostream OS(Res); OS << getOption().getName(); for (unsigned i = 0, e = getNumValues(); i != e; ++i) { diff --git a/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp b/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp index ca9b944..55a0ddf 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ArgList.cpp @@ -122,6 +122,24 @@ Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, return Res; } +Arg *ArgList::getLastArg(OptSpecifier Id0, OptSpecifier Id1, + OptSpecifier Id2, OptSpecifier Id3, + OptSpecifier Id4) const { + Arg *Res = 0; + for (const_iterator it = begin(), ie = end(); it != ie; ++it) { + if ((*it)->getOption().matches(Id0) || + (*it)->getOption().matches(Id1) || + (*it)->getOption().matches(Id2) || + (*it)->getOption().matches(Id3) || + (*it)->getOption().matches(Id4)) { + Res = *it; + Res->claim(); + } + } + + return Res; +} + bool ArgList::hasFlag(OptSpecifier Pos, OptSpecifier Neg, bool Default) const { if (Arg *A = getLastArg(Pos, Neg)) return A->getOption().matches(Pos); @@ -136,13 +154,15 @@ StringRef ArgList::getLastArgValue(OptSpecifier Id, } int ArgList::getLastArgIntValue(OptSpecifier Id, int Default, - clang::DiagnosticsEngine &Diags) const { + clang::DiagnosticsEngine *Diags) const { int Res = Default; if (Arg *A = getLastArg(Id)) { - if (StringRef(A->getValue(*this)).getAsInteger(10, Res)) - Diags.Report(diag::err_drv_invalid_int_value) - << A->getAsString(*this) << A->getValue(*this); + if (StringRef(A->getValue(*this)).getAsInteger(10, Res)) { + if (Diags) + Diags->Report(diag::err_drv_invalid_int_value) + << A->getAsString(*this) << A->getValue(*this); + } } return Res; @@ -210,7 +230,7 @@ void ArgList::ClaimAllArgs() const { } const char *ArgList::MakeArgString(const Twine &T) const { - llvm::SmallString<256> Str; + SmallString<256> Str; T.toVector(Str); return MakeArgString(Str.str()); } diff --git a/contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp b/contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp index 90c69ff..ea80f5a 100644 --- a/contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/CC1AsOptions.cpp @@ -18,7 +18,7 @@ using namespace clang::driver::cc1asoptions; static const OptTable::Info CC1AsInfoTable[] = { #define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ HELPTEXT, METAVAR) \ - { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \ + { NAME, HELPTEXT, METAVAR, Option::KIND##Class, PARAM, FLAGS, \ OPT_##GROUP, OPT_##ALIAS }, #include "clang/Driver/CC1AsOptions.inc" }; diff --git a/contrib/llvm/tools/clang/lib/Driver/CC1Options.cpp b/contrib/llvm/tools/clang/lib/Driver/CC1Options.cpp index 14cf090..884b363 100644 --- a/contrib/llvm/tools/clang/lib/Driver/CC1Options.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/CC1Options.cpp @@ -18,7 +18,7 @@ using namespace clang::driver::cc1options; static const OptTable::Info CC1InfoTable[] = { #define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ HELPTEXT, METAVAR) \ - { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \ + { NAME, HELPTEXT, METAVAR, Option::KIND##Class, PARAM, FLAGS, \ OPT_##GROUP, OPT_##ALIAS }, #include "clang/Driver/CC1Options.inc" }; diff --git a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp index d02da95..42c8449 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Compilation.cpp @@ -217,8 +217,12 @@ void Compilation::initCompilationForDiagnostics(void) { // Remove any user specified output. Claim any unclaimed arguments, so as // to avoid emitting warnings about unused args. - if (TranslatedArgs->hasArg(options::OPT_o)) - TranslatedArgs->eraseArg(options::OPT_o); + OptSpecifier OutputOpts[] = { options::OPT_o, options::OPT_MD, + options::OPT_MMD }; + for (unsigned i = 0; i != sizeof(OutputOpts)/sizeof(OutputOpts[0]); ++i) { + if (TranslatedArgs->hasArg(OutputOpts[i])) + TranslatedArgs->eraseArg(OutputOpts[i]); + } TranslatedArgs->ClaimAllArgs(); // Redirect stdout/stderr to /dev/null. diff --git a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp index 4e2d7b6..40e0c00 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Driver.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Driver.cpp @@ -7,10 +7,6 @@ // //===----------------------------------------------------------------------===// -#ifdef HAVE_CLANG_CONFIG_H -# include "clang/Config/config.h" -#endif - #include "clang/Driver/Driver.h" #include "clang/Driver/Action.h" @@ -18,7 +14,6 @@ #include "clang/Driver/ArgList.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/DriverDiagnostic.h" -#include "clang/Driver/HostInfo.h" #include "clang/Driver/Job.h" #include "clang/Driver/OptTable.h" #include "clang/Driver/Option.h" @@ -28,7 +23,6 @@ #include "clang/Basic/Version.h" -#include "llvm/Config/config.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringSet.h" #include "llvm/ADT/OwningPtr.h" @@ -40,22 +34,25 @@ #include "llvm/Support/Program.h" #include "InputInfo.h" +#include "ToolChains.h" #include <map> +#include "clang/Config/config.h" + using namespace clang::driver; using namespace clang; Driver::Driver(StringRef ClangExecutable, - StringRef DefaultHostTriple, + StringRef DefaultTargetTriple, StringRef DefaultImageName, bool IsProduction, DiagnosticsEngine &Diags) : Opts(createDriverOptTable()), Diags(Diags), ClangExecutable(ClangExecutable), UseStdLib(true), - DefaultHostTriple(DefaultHostTriple), DefaultImageName(DefaultImageName), + DefaultTargetTriple(DefaultTargetTriple), + DefaultImageName(DefaultImageName), DriverTitle("clang \"gcc-compatible\" driver"), - Host(0), CCPrintOptionsFilename(0), CCPrintHeadersFilename(0), CCLogDiagnosticsFilename(0), CCCIsCXX(false), CCCIsCPP(false),CCCEcho(false), CCCPrintBindings(false), @@ -65,7 +62,7 @@ Driver::Driver(StringRef ClangExecutable, CCCUsePCH(true), SuppressMissingInputWarning(false) { if (IsProduction) { // In a "production" build, only use clang on architectures we expect to - // work, and don't use clang C++. + // work. // // During development its more convenient to always have the driver use // clang, but we don't want users to be confused when things don't work, or @@ -80,7 +77,7 @@ Driver::Driver(StringRef ClangExecutable, // Compute the path to the resource directory. StringRef ClangResourceDir(CLANG_RESOURCE_DIR); - llvm::SmallString<128> P(Dir); + SmallString<128> P(Dir); if (ClangResourceDir != "") llvm::sys::path::append(P, ClangResourceDir); else @@ -90,7 +87,11 @@ Driver::Driver(StringRef ClangExecutable, Driver::~Driver() { delete Opts; - delete Host; + + for (llvm::StringMap<ToolChain *>::iterator I = ToolChains.begin(), + E = ToolChains.end(); + I != E; ++I) + delete I->second; } InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) { @@ -112,6 +113,12 @@ InputArgList *Driver::ParseArgStrings(ArrayRef<const char *> ArgList) { Diag(clang::diag::err_drv_unsupported_opt) << A->getAsString(*Args); continue; } + + // Warn about -mcpu= without an argument. + if (A->getOption().matches(options::OPT_mcpu_EQ) && + A->containsValue("")) { + Diag(clang::diag::warn_drv_empty_joined_argument) << A->getAsString(*Args); + } } return Args; @@ -134,8 +141,10 @@ const { // -{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_rewrite_objc)) || + (PhaseArg = DAL.getLastArg(options::OPT_rewrite_legacy_objc)) || + (PhaseArg = DAL.getLastArg(options::OPT__migrate)) || (PhaseArg = DAL.getLastArg(options::OPT__analyze, - options::OPT__analyze_auto)) || + options::OPT__analyze_auto)) || (PhaseArg = DAL.getLastArg(options::OPT_emit_ast)) || (PhaseArg = DAL.getLastArg(options::OPT_S))) { FinalPhase = phases::Compile; @@ -239,7 +248,7 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { llvm::PrettyStackTraceString CrashInfo("Compilation construction"); // FIXME: Handle environment options which affect driver behavior, somewhere - // (client?). GCC_EXEC_PREFIX, LIBRARY_PATH, LPATH, CC_PRINT_OPTIONS. + // (client?). GCC_EXEC_PREFIX, LPATH, CC_PRINT_OPTIONS. if (char *env = ::getenv("COMPILER_PATH")) { StringRef CompilerPath = env; @@ -303,10 +312,10 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { Cur = Split.second; } } - // FIXME: We shouldn't overwrite the default host triple here, but we have - // nowhere else to put this currently. - if (const Arg *A = Args->getLastArg(options::OPT_ccc_host_triple)) - DefaultHostTriple = A->getValue(*Args); + // FIXME: DefaultTargetTriple is used by the target-prefixed calls to as/ld + // and getToolChain is const. + if (const Arg *A = Args->getLastArg(options::OPT_target)) + DefaultTargetTriple = A->getValue(*Args); if (const Arg *A = Args->getLastArg(options::OPT_ccc_install_dir)) Dir = InstalledDir = A->getValue(*Args); for (arg_iterator it = Args->filtered_begin(options::OPT_B), @@ -320,14 +329,14 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { if (Args->hasArg(options::OPT_nostdlib)) UseStdLib = false; - Host = GetHostInfo(DefaultHostTriple.c_str()); - // Perform the default argument translations. DerivedArgList *TranslatedArgs = TranslateInputArgs(*Args); + // Owned by the host. + const ToolChain &TC = getToolChain(*Args); + // The compilation takes ownership of Args. - Compilation *C = new Compilation(*this, *Host->CreateToolChain(*Args), Args, - TranslatedArgs); + Compilation *C = new Compilation(*this, TC, Args, TranslatedArgs); // FIXME: This behavior shouldn't be here. if (CCCPrintOptions) { @@ -342,8 +351,9 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { InputList Inputs; BuildInputs(C->getDefaultToolChain(), C->getArgs(), Inputs); - // Construct the list of abstract actions to perform for this compilation. - if (Host->useDriverDriver()) + // 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()) BuildUniversalActions(C->getDefaultToolChain(), C->getArgs(), Inputs, C->getActions()); else @@ -365,6 +375,13 @@ Compilation *Driver::BuildCompilation(ArrayRef<const char *> ArgList) { // diagnostic information to a bug report. void Driver::generateCompilationDiagnostics(Compilation &C, const Command *FailingCommand) { + if (C.getArgs().hasArg(options::OPT_fno_crash_diagnostics)) + return; + + // Don't try to generate diagnostics for link jobs. + if (FailingCommand->getCreator().isLinkJob()) + return; + Diag(clang::diag::note_drv_command_failed_diag_msg) << "Please submit a bug report to " BUG_REPORT_URL " and include command" " line arguments and all diagnostic information."; @@ -373,6 +390,12 @@ void Driver::generateCompilationDiagnostics(Compilation &C, CCCIsCPP = true; CCGenDiagnostics = true; + // Save the original job command(s). + std::string Cmd; + llvm::raw_string_ostream OS(Cmd); + C.PrintJob(OS, C.getJobs(), "\n", false); + OS.flush(); + // Clear stale state and suppress tool output. C.initCompilationForDiagnostics(); Diags.Reset(); @@ -403,21 +426,22 @@ void Driver::generateCompilationDiagnostics(Compilation &C, } // Don't attempt to generate preprocessed files if multiple -arch options are - // used. - int Archs = 0; + // used, unless they're all duplicates. + llvm::StringSet<> ArchNames; for (ArgList::const_iterator it = C.getArgs().begin(), ie = C.getArgs().end(); it != ie; ++it) { Arg *A = *it; if (A->getOption().matches(options::OPT_arch)) { - Archs++; - if (Archs > 1) { - Diag(clang::diag::note_drv_command_failed_diag_msg) - << "Error generating preprocessed source(s) - cannot generate " - "preprocessed source with multiple -arch options."; - return; - } + StringRef ArchName = A->getValue(C.getArgs()); + ArchNames.insert(ArchName); } } + if (ArchNames.size() > 1) { + Diag(clang::diag::note_drv_command_failed_diag_msg) + << "Error generating preprocessed source(s) - cannot generate " + "preprocessed source with multiple -arch options."; + return; + } if (Inputs.empty()) { Diag(clang::diag::note_drv_command_failed_diag_msg) @@ -425,13 +449,13 @@ void Driver::generateCompilationDiagnostics(Compilation &C, return; } - // Construct the list of abstract actions to perform for this compilation. - if (Host->useDriverDriver()) - BuildUniversalActions(C.getDefaultToolChain(), C.getArgs(), - Inputs, C.getActions()); + // 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()) + BuildUniversalActions(TC, C.getArgs(), Inputs, C.getActions()); else - BuildActions(C.getDefaultToolChain(), C.getArgs(), Inputs, - C.getActions()); + BuildActions(TC, C.getArgs(), Inputs, C.getActions()); BuildJobs(C); @@ -449,11 +473,26 @@ void Driver::generateCompilationDiagnostics(Compilation &C, // If the command succeeded, we are done. if (Res == 0) { Diag(clang::diag::note_drv_command_failed_diag_msg) - << "Preprocessed source(s) are located at:"; + << "Preprocessed source(s) and associated run script(s) are located at:"; ArgStringList Files = C.getTempFiles(); for (ArgStringList::const_iterator it = Files.begin(), ie = Files.end(); - it != ie; ++it) + it != ie; ++it) { Diag(clang::diag::note_drv_command_failed_diag_msg) << *it; + + 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); + if (!Err.empty()) { + Diag(clang::diag::note_drv_command_failed_diag_msg) + << "Error generating run script: " + Script + " " + Err; + } else { + ScriptOS << Cmd; + Diag(clang::diag::note_drv_command_failed_diag_msg) << Script; + } + } } else { // Failure, remove preprocessed files. if (!C.getArgs().hasArg(options::OPT_save_temps)) @@ -486,9 +525,20 @@ int Driver::ExecuteCompilation(const Compilation &C, return Res; // Otherwise, remove result files as well. - if (!C.getArgs().hasArg(options::OPT_save_temps)) + if (!C.getArgs().hasArg(options::OPT_save_temps)) { C.CleanupFileList(C.getResultFiles(), true); + // Failure result files are valid unless we crashed. + if (Res < 0) { + C.CleanupFileList(C.getFailureResultFiles(), true); +#ifdef _WIN32 + // Exit status should not be negative on Win32, + // unless abnormal termination. + Res = 1; +#endif + } + } + // Print extra information about abnormal failures, if possible. // // This is ad-hoc, but we don't want to be excessively noisy. If the result @@ -502,7 +552,7 @@ int Driver::ExecuteCompilation(const Compilation &C, // FIXME: See FIXME above regarding result code interpretation. if (Res < 0) Diag(clang::diag::err_drv_command_signalled) - << FailingTool.getShortName() << -Res; + << FailingTool.getShortName(); else Diag(clang::diag::err_drv_command_failed) << FailingTool.getShortName() << Res; @@ -820,35 +870,32 @@ void Driver::BuildUniversalActions(const ToolChain &TC, else Actions.push_back(new LipoJobAction(Inputs, Act->getType())); - // Add a 'dsymutil' step if necessary, when debug info is enabled and we - // have a compile input. We need to run 'dsymutil' ourselves in such cases - // because the debug info will refer to a temporary object file which is - // will be removed at the end of the compilation process. - if (Act->getType() == types::TY_Image) { - Arg *A = Args.getLastArg(options::OPT_g_Group); + // Handle debug info queries. + Arg *A = Args.getLastArg(options::OPT_g_Group); if (A && !A->getOption().matches(options::OPT_g0) && !A->getOption().matches(options::OPT_gstabs) && ContainsCompileOrAssembleAction(Actions.back())) { - ActionList Inputs; - Inputs.push_back(Actions.back()); - Actions.pop_back(); - - Actions.push_back(new DsymutilJobAction(Inputs, types::TY_dSYM)); - - // Verify the debug output if we're in assert mode. - // TODO: The verifier is noisy by default so put this under an - // option for now. - #ifndef NDEBUG - if (Args.hasArg(options::OPT_verify)) { - ActionList VerifyInputs; + + // Add a 'dsymutil' step if necessary, when debug info is enabled and we + // have a compile input. We need to run 'dsymutil' ourselves in such cases + // because the debug info will refer to a temporary object file which is + // will be removed at the end of the compilation process. + if (Act->getType() == types::TY_Image) { + ActionList Inputs; + Inputs.push_back(Actions.back()); + Actions.pop_back(); + 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()); Actions.pop_back(); Actions.push_back(new VerifyJobAction(VerifyInputs, types::TY_Nothing)); } - #endif } - } } } @@ -931,15 +978,17 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args, // Check that the file exists, if enabled. if (CheckInputsExist && memcmp(Value, "-", 2) != 0) { - llvm::SmallString<64> Path(Value); - if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory)) - if (llvm::sys::path::is_absolute(Path.str())) { - Path = WorkDir->getValue(Args); - llvm::sys::path::append(Path, Value); + SmallString<64> Path(Value); + if (Arg *WorkDir = Args.getLastArg(options::OPT_working_directory)) { + SmallString<64> Directory(WorkDir->getValue(Args)); + if (llvm::sys::path::is_absolute(Directory.str())) { + llvm::sys::path::append(Directory, Value); + Path.assign(Directory); } + } bool exists = false; - if (/*error_code ec =*/llvm::sys::fs::exists(Value, exists) || !exists) + 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)); @@ -954,6 +1003,7 @@ void Driver::BuildInputs(const ToolChain &TC, const DerivedArgList &Args, } else if (A->getOption().matches(options::OPT_x)) { InputTypeArg = A; InputType = types::lookupTypeForTypeSpecifier(A->getValue(Args)); + A->claim(); // Follow gcc behavior and treat as linker input for invalid -x // options. Its not clear why we shouldn't just revert to unknown; but @@ -993,11 +1043,12 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, // Construct the actions to perform. ActionList LinkerInputs; + unsigned NumSteps = 0; for (unsigned i = 0, e = Inputs.size(); i != e; ++i) { types::ID InputType = Inputs[i].first; const Arg *InputArg = Inputs[i].second; - unsigned NumSteps = types::getNumCompilationPhases(InputType); + NumSteps = types::getNumCompilationPhases(InputType); assert(NumSteps && "Invalid number of steps!"); // If the first step comes after the final phase we are doing as part of @@ -1027,7 +1078,7 @@ void Driver::BuildActions(const ToolChain &TC, const DerivedArgList &Args, } // Build the pipeline for this file. - llvm::OwningPtr<Action> Current(new InputAction(*InputArg, InputType)); + OwningPtr<Action> Current(new InputAction(*InputArg, InputType)); for (unsigned i = 0; i != NumSteps; ++i) { phases::ID Phase = types::getCompilationPhase(InputType, i); @@ -1065,7 +1116,7 @@ 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) + if (FinalPhase == phases::Link && (NumSteps == 1)) Args.ClaimAllArgs(options::OPT_CompileOnly_Group); } @@ -1094,8 +1145,12 @@ Action *Driver::ConstructPhaseAction(const ArgList &Args, phases::ID Phase, return new CompileJobAction(Input, types::TY_Nothing); } else if (Args.hasArg(options::OPT_rewrite_objc)) { return new CompileJobAction(Input, types::TY_RewrittenObjC); + } else if (Args.hasArg(options::OPT_rewrite_legacy_objc)) { + return new CompileJobAction(Input, types::TY_RewrittenLegacyObjC); } else if (Args.hasArg(options::OPT__analyze, options::OPT__analyze_auto)) { return new AnalyzeJobAction(Input, types::TY_Plist); + } else if (Args.hasArg(options::OPT__migrate)) { + return new MigrateJobAction(Input, types::TY_Remap); } else if (Args.hasArg(options::OPT_emit_ast)) { return new CompileJobAction(Input, types::TY_AST); } else if (IsUsingLTO(Args)) { @@ -1225,17 +1280,9 @@ static const Tool &SelectToolForJob(Compilation &C, const ToolChain *TC, // bottom up, so what we are actually looking for is an assembler job with a // compiler input. - // FIXME: This doesn't belong here, but ideally we will support static soon - // anyway. - bool HasStatic = (C.getArgs().hasArg(options::OPT_mkernel) || - C.getArgs().hasArg(options::OPT_static) || - C.getArgs().hasArg(options::OPT_fapple_kext)); - bool IsDarwin = TC->getTriple().isOSDarwin(); - bool IsIADefault = TC->IsIntegratedAssemblerDefault() && - !(HasStatic && IsDarwin); if (C.getArgs().hasFlag(options::OPT_integrated_as, - options::OPT_no_integrated_as, - IsIADefault) && + options::OPT_no_integrated_as, + TC->IsIntegratedAssemblerDefault()) && !C.getArgs().hasArg(options::OPT_save_temps) && isa<AssembleJobAction>(JA) && Inputs->size() == 1 && isa<CompileJobAction>(*Inputs->begin())) { @@ -1289,9 +1336,8 @@ void Driver::BuildJobsForAction(Compilation &C, if (const BindArchAction *BAA = dyn_cast<BindArchAction>(A)) { const ToolChain *TC = &C.getDefaultToolChain(); - std::string Arch; if (BAA->getArchName()) - TC = Host->CreateToolChain(C.getArgs(), BAA->getArchName()); + TC = &getToolChain(C.getArgs(), BAA->getArchName()); BuildJobsForAction(C, *BAA->begin(), TC, BAA->getArchName(), AtTopLevel, LinkingOutput, Result); @@ -1383,7 +1429,7 @@ const char *Driver::GetNamedOutputPath(Compilation &C, return C.addTempFile(C.getArgs().MakeArgString(TmpName.c_str())); } - llvm::SmallString<128> BasePath(BaseInput); + SmallString<128> BasePath(BaseInput); StringRef BaseName; // Dsymutil actions should use the full path. @@ -1482,7 +1528,8 @@ static bool isPathExecutable(llvm::sys::Path &P, bool WantFile) { std::string Driver::GetProgramPath(const char *Name, const ToolChain &TC, bool WantFile) const { - std::string TargetSpecificExecutable(DefaultHostTriple + "-" + Name); + // FIXME: Needs a better variable than DefaultTargetTriple + std::string TargetSpecificExecutable(DefaultTargetTriple + "-" + Name); // Respect a limited subset of the '-Bprefix' functionality in GCC by // attempting to use this prefix when lokup up program paths. for (Driver::prefix_list::const_iterator it = PrefixDirs.begin(), @@ -1545,40 +1592,125 @@ std::string Driver::GetTemporaryPath(StringRef Prefix, const char *Suffix) return P.str(); } -const HostInfo *Driver::GetHostInfo(const char *TripleStr) const { - llvm::PrettyStackTraceString CrashInfo("Constructing host"); - llvm::Triple Triple(llvm::Triple::normalize(TripleStr).c_str()); - - // TCE is an osless target - if (Triple.getArchName() == "tce") - return createTCEHostInfo(*this, Triple); - - switch (Triple.getOS()) { - case llvm::Triple::AuroraUX: - return createAuroraUXHostInfo(*this, Triple); - case llvm::Triple::Darwin: - case llvm::Triple::MacOSX: - case llvm::Triple::IOS: - return createDarwinHostInfo(*this, Triple); - case llvm::Triple::DragonFly: - return createDragonFlyHostInfo(*this, Triple); - case llvm::Triple::OpenBSD: - return createOpenBSDHostInfo(*this, Triple); - case llvm::Triple::NetBSD: - return createNetBSDHostInfo(*this, Triple); - case llvm::Triple::FreeBSD: - return createFreeBSDHostInfo(*this, Triple); - case llvm::Triple::Minix: - return createMinixHostInfo(*this, Triple); - case llvm::Triple::Linux: - return createLinuxHostInfo(*this, Triple); - case llvm::Triple::Win32: - return createWindowsHostInfo(*this, Triple); - case llvm::Triple::MinGW32: - return createMinGWHostInfo(*this, Triple); - default: - return createUnknownHostInfo(*this, Triple); +/// \brief Compute target triple from args. +/// +/// This routine provides the logic to compute a target triple from various +/// args passed to the driver and the default triple string. +static llvm::Triple computeTargetTriple(StringRef DefaultTargetTriple, + const ArgList &Args, + StringRef DarwinArchName) { + // FIXME: Already done in Compilation *Driver::BuildCompilation + if (const Arg *A = Args.getLastArg(options::OPT_target)) + DefaultTargetTriple = A->getValue(Args); + + llvm::Triple Target(llvm::Triple::normalize(DefaultTargetTriple)); + + // Handle Darwin-specific options available here. + if (Target.isOSDarwin()) { + // If an explict Darwin arch name is given, that trumps all. + if (!DarwinArchName.empty()) { + Target.setArch( + llvm::Triple::getArchTypeForDarwinArchName(DarwinArchName)); + return Target; + } + + // Handle the Darwin '-arch' flag. + if (Arg *A = Args.getLastArg(options::OPT_arch)) { + llvm::Triple::ArchType DarwinArch + = llvm::Triple::getArchTypeForDarwinArchName(A->getValue(Args)); + if (DarwinArch != llvm::Triple::UnknownArch) + Target.setArch(DarwinArch); + } + } + + // Skip further flag support on OSes which don't support '-m32' or '-m64'. + if (Target.getArchName() == "tce" || + Target.getOS() == llvm::Triple::AuroraUX || + 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); + } + } + + return Target; +} + +const ToolChain &Driver::getToolChain(const ArgList &Args, + StringRef DarwinArchName) const { + llvm::Triple Target = computeTargetTriple(DefaultTargetTriple, Args, + DarwinArchName); + + ToolChain *&TC = ToolChains[Target.str()]; + if (!TC) { + switch (Target.getOS()) { + case llvm::Triple::AuroraUX: + TC = new toolchains::AuroraUX(*this, Target, Args); + break; + 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); + else + TC = new toolchains::Darwin_Generic_GCC(*this, Target, Args); + break; + case llvm::Triple::DragonFly: + TC = new toolchains::DragonFly(*this, Target, Args); + break; + case llvm::Triple::OpenBSD: + TC = new toolchains::OpenBSD(*this, Target, Args); + break; + case llvm::Triple::NetBSD: + TC = new toolchains::NetBSD(*this, Target, Args); + break; + case llvm::Triple::FreeBSD: + TC = new toolchains::FreeBSD(*this, Target, Args); + break; + case llvm::Triple::Minix: + TC = new toolchains::Minix(*this, Target, Args); + break; + case llvm::Triple::Linux: + if (Target.getArch() == llvm::Triple::hexagon) + TC = new toolchains::Hexagon_TC(*this, Target); + else + TC = new toolchains::Linux(*this, Target, Args); + break; + case llvm::Triple::Solaris: + TC = new toolchains::Solaris(*this, Target, Args); + break; + case llvm::Triple::Win32: + TC = new toolchains::Windows(*this, Target); + break; + case llvm::Triple::MinGW32: + // FIXME: We need a MinGW toolchain. Fallthrough for now. + default: + // TCE is an OSless target + if (Target.getArchName() == "tce") { + TC = new toolchains::TCEToolChain(*this, Target); + break; + } + + TC = new toolchains::Generic_GCC(*this, Target, Args); + break; + } } + return *TC; } bool Driver::ShouldUseClangCompiler(const Compilation &C, const JobAction &JA, diff --git a/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp b/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp index f2d9af8..715819d 100644 --- a/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/DriverOptions.cpp @@ -17,7 +17,7 @@ using namespace clang::driver::options; static const OptTable::Info InfoTable[] = { #define OPTION(NAME, ID, KIND, GROUP, ALIAS, FLAGS, PARAM, \ HELPTEXT, METAVAR) \ - { NAME, HELPTEXT, METAVAR, Option::KIND##Class, FLAGS, PARAM, \ + { NAME, HELPTEXT, METAVAR, Option::KIND##Class, PARAM, FLAGS, \ OPT_##GROUP, OPT_##ALIAS }, #include "clang/Driver/Options.inc" }; diff --git a/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp b/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp deleted file mode 100644 index 292678b..0000000 --- a/contrib/llvm/tools/clang/lib/Driver/HostInfo.cpp +++ /dev/null @@ -1,731 +0,0 @@ -//===--- HostInfo.cpp - Host specific information -------------------------===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "clang/Driver/HostInfo.h" - -#include "clang/Driver/Arg.h" -#include "clang/Driver/ArgList.h" -#include "clang/Driver/Driver.h" -#include "clang/Driver/DriverDiagnostic.h" -#include "clang/Driver/Option.h" -#include "clang/Driver/Options.h" - -#include "llvm/ADT/StringMap.h" -#include "llvm/Support/Compiler.h" - -#include "ToolChains.h" - -#include <cassert> - -using namespace clang::driver; - -HostInfo::HostInfo(const Driver &D, const llvm::Triple &_Triple) - : TheDriver(D), Triple(_Triple) { -} - -HostInfo::~HostInfo() { -} - -namespace { - -// Darwin Host Info - -/// DarwinHostInfo - Darwin host information implementation. -class DarwinHostInfo : public HostInfo { - /// Cache of tool chains we have created. - mutable llvm::DenseMap<unsigned, ToolChain*> ToolChains; - -public: - DarwinHostInfo(const Driver &D, const llvm::Triple &Triple); - ~DarwinHostInfo(); - - virtual bool useDriverDriver() const; - - virtual ToolChain *CreateToolChain(const ArgList &Args, - const char *ArchName) const; -}; - -DarwinHostInfo::DarwinHostInfo(const Driver &D, const llvm::Triple& Triple) - : HostInfo(D, Triple) { -} - -DarwinHostInfo::~DarwinHostInfo() { - for (llvm::DenseMap<unsigned, ToolChain*>::iterator - it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) - delete it->second; -} - -bool DarwinHostInfo::useDriverDriver() const { - return true; -} - -ToolChain *DarwinHostInfo::CreateToolChain(const ArgList &Args, - const char *ArchName) const { - llvm::Triple::ArchType Arch; - - if (!ArchName) { - // If we aren't looking for a specific arch, infer the default architecture - // based on -arch and -m32/-m64 command line options. - if (Arg *A = Args.getLastArg(options::OPT_arch)) { - // The gcc driver behavior with multiple -arch flags wasn't consistent for - // things which rely on a default architecture. We just use the last -arch - // to find the default tool chain (assuming it is valid). - Arch = llvm::Triple::getArchTypeForDarwinArchName(A->getValue(Args)); - - // If it was invalid just use the host, we will reject this command line - // later. - if (Arch == llvm::Triple::UnknownArch) - Arch = getTriple().getArch(); - } else { - // Otherwise default to the arch of the host. - Arch = getTriple().getArch(); - } - - // Honor -m32 and -m64 when finding the default tool chain. - // - // 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 (Arch == llvm::Triple::x86_64) - Arch = llvm::Triple::x86; - if (Arch == llvm::Triple::ppc64) - Arch = llvm::Triple::ppc; - } else { - if (Arch == llvm::Triple::x86) - Arch = llvm::Triple::x86_64; - if (Arch == llvm::Triple::ppc) - Arch = llvm::Triple::ppc64; - } - } - } else - Arch = llvm::Triple::getArchTypeForDarwinArchName(ArchName); - - assert(Arch != llvm::Triple::UnknownArch && "Unexpected arch!"); - ToolChain *&TC = ToolChains[Arch]; - if (!TC) { - llvm::Triple TCTriple(getTriple()); - TCTriple.setArch(Arch); - - // If we recognized the arch, match it to the toolchains we support. - if (Arch == llvm::Triple::x86 || Arch == llvm::Triple::x86_64 || - Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) { - TC = new toolchains::DarwinClang(*this, TCTriple); - } else - TC = new toolchains::Darwin_Generic_GCC(*this, TCTriple); - } - - return TC; -} - -// TCE Host Info - -/// TCEHostInfo - TCE host information implementation (see http://tce.cs.tut.fi) -class TCEHostInfo : public HostInfo { - -public: - TCEHostInfo(const Driver &D, const llvm::Triple &Triple); - ~TCEHostInfo() {} - - virtual bool useDriverDriver() const; - - virtual ToolChain *CreateToolChain(const ArgList &Args, - const char *ArchName) const; -}; - -TCEHostInfo::TCEHostInfo(const Driver &D, const llvm::Triple& Triple) - : HostInfo(D, Triple) { -} - -bool TCEHostInfo::useDriverDriver() const { - return false; -} - -ToolChain *TCEHostInfo::CreateToolChain(const ArgList &Args, - const char *ArchName) const { - llvm::Triple TCTriple(getTriple()); -// TCTriple.setArchName(ArchName); - return new toolchains::TCEToolChain(*this, TCTriple); -} - - -// Unknown Host Info - -/// UnknownHostInfo - Generic host information to use for unknown hosts. -class UnknownHostInfo : public HostInfo { - /// Cache of tool chains we have created. - mutable llvm::StringMap<ToolChain*> ToolChains; - -public: - UnknownHostInfo(const Driver &D, const llvm::Triple& Triple); - ~UnknownHostInfo(); - - virtual bool useDriverDriver() const; - - virtual ToolChain *CreateToolChain(const ArgList &Args, - const char *ArchName) const; -}; - -UnknownHostInfo::UnknownHostInfo(const Driver &D, const llvm::Triple& Triple) - : HostInfo(D, Triple) { -} - -UnknownHostInfo::~UnknownHostInfo() { - for (llvm::StringMap<ToolChain*>::iterator - it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) - delete it->second; -} - -bool UnknownHostInfo::useDriverDriver() const { - return false; -} - -ToolChain *UnknownHostInfo::CreateToolChain(const ArgList &Args, - const char *ArchName) const { - assert(!ArchName && - "Unexpected arch name on platform without driver support."); - - // Automatically handle some instances of -m32/-m64 we know about. - std::string Arch = getArchName(); - ArchName = Arch.c_str(); - if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { - if (Triple.getArch() == llvm::Triple::x86 || - Triple.getArch() == llvm::Triple::x86_64) { - ArchName = - (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; - } else if (Triple.getArch() == llvm::Triple::ppc || - Triple.getArch() == llvm::Triple::ppc64) { - ArchName = - (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64"; - } - } - - ToolChain *&TC = ToolChains[ArchName]; - if (!TC) { - llvm::Triple TCTriple(getTriple()); - TCTriple.setArchName(ArchName); - - TC = new toolchains::Generic_GCC(*this, TCTriple); - } - - return TC; -} - -// OpenBSD Host Info - -/// OpenBSDHostInfo - OpenBSD host information implementation. -class OpenBSDHostInfo : public HostInfo { - /// Cache of tool chains we have created. - mutable llvm::StringMap<ToolChain*> ToolChains; - -public: - OpenBSDHostInfo(const Driver &D, const llvm::Triple& Triple) - : HostInfo(D, Triple) {} - ~OpenBSDHostInfo(); - - virtual bool useDriverDriver() const; - - virtual ToolChain *CreateToolChain(const ArgList &Args, - const char *ArchName) const; -}; - -OpenBSDHostInfo::~OpenBSDHostInfo() { - for (llvm::StringMap<ToolChain*>::iterator - it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) - delete it->second; -} - -bool OpenBSDHostInfo::useDriverDriver() const { - return false; -} - -ToolChain *OpenBSDHostInfo::CreateToolChain(const ArgList &Args, - const char *ArchName) const { - assert(!ArchName && - "Unexpected arch name on platform without driver driver support."); - - std::string Arch = getArchName(); - ArchName = Arch.c_str(); - - ToolChain *&TC = ToolChains[ArchName]; - if (!TC) { - llvm::Triple TCTriple(getTriple()); - TCTriple.setArchName(ArchName); - - TC = new toolchains::OpenBSD(*this, TCTriple); - } - - return TC; -} - -// AuroraUX Host Info - -/// AuroraUXHostInfo - AuroraUX host information implementation. -class AuroraUXHostInfo : public HostInfo { - /// Cache of tool chains we have created. - mutable llvm::StringMap<ToolChain*> ToolChains; - -public: - AuroraUXHostInfo(const Driver &D, const llvm::Triple& Triple) - : HostInfo(D, Triple) {} - ~AuroraUXHostInfo(); - - virtual bool useDriverDriver() const; - - virtual ToolChain *CreateToolChain(const ArgList &Args, - const char *ArchName) const; -}; - -AuroraUXHostInfo::~AuroraUXHostInfo() { - for (llvm::StringMap<ToolChain*>::iterator - it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) - delete it->second; -} - -bool AuroraUXHostInfo::useDriverDriver() const { - return false; -} - -ToolChain *AuroraUXHostInfo::CreateToolChain(const ArgList &Args, - const char *ArchName) const { - assert(!ArchName && - "Unexpected arch name on platform without driver driver support."); - - ToolChain *&TC = ToolChains[getArchName()]; - - if (!TC) { - llvm::Triple TCTriple(getTriple()); - TCTriple.setArchName(getArchName()); - - TC = new toolchains::AuroraUX(*this, TCTriple); - } - - return TC; -} - -// FreeBSD Host Info - -/// FreeBSDHostInfo - FreeBSD host information implementation. -class FreeBSDHostInfo : public HostInfo { - /// Cache of tool chains we have created. - mutable llvm::StringMap<ToolChain*> ToolChains; - -public: - FreeBSDHostInfo(const Driver &D, const llvm::Triple& Triple) - : HostInfo(D, Triple) {} - ~FreeBSDHostInfo(); - - virtual bool useDriverDriver() const; - - virtual ToolChain *CreateToolChain(const ArgList &Args, - const char *ArchName) const; -}; - -FreeBSDHostInfo::~FreeBSDHostInfo() { - for (llvm::StringMap<ToolChain*>::iterator - it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) - delete it->second; -} - -bool FreeBSDHostInfo::useDriverDriver() const { - return false; -} - -ToolChain *FreeBSDHostInfo::CreateToolChain(const ArgList &Args, - const char *ArchName) const { - assert(!ArchName && - "Unexpected arch name on platform without driver driver support."); - - // Automatically handle some instances of -m32/-m64 we know about. - std::string Arch = getArchName(); - ArchName = Arch.c_str(); - if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { - if (Triple.getArch() == llvm::Triple::x86 || - Triple.getArch() == llvm::Triple::x86_64) { - ArchName = - (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; - } else if (Triple.getArch() == llvm::Triple::ppc || - Triple.getArch() == llvm::Triple::ppc64) { - ArchName = - (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64"; - } - } - - ToolChain *&TC = ToolChains[ArchName]; - if (!TC) { - llvm::Triple TCTriple(getTriple()); - TCTriple.setArchName(ArchName); - - TC = new toolchains::FreeBSD(*this, TCTriple); - } - - return TC; -} - -// NetBSD Host Info - -/// NetBSDHostInfo - NetBSD host information implementation. -class NetBSDHostInfo : public HostInfo { - /// Cache of tool chains we have created. - mutable llvm::StringMap<ToolChain*> ToolChains; - -public: - NetBSDHostInfo(const Driver &D, const llvm::Triple& Triple) - : HostInfo(D, Triple) {} - ~NetBSDHostInfo(); - - virtual bool useDriverDriver() const; - - virtual ToolChain *CreateToolChain(const ArgList &Args, - const char *ArchName) const; -}; - -NetBSDHostInfo::~NetBSDHostInfo() { - for (llvm::StringMap<ToolChain*>::iterator - it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) - delete it->second; -} - -bool NetBSDHostInfo::useDriverDriver() const { - return false; -} - -ToolChain *NetBSDHostInfo::CreateToolChain(const ArgList &Args, - const char *ArchName) const { - assert(!ArchName && - "Unexpected arch name on platform without driver driver support."); - - // Automatically handle some instances of -m32/-m64 we know about. - std::string Arch = getArchName(); - ArchName = Arch.c_str(); - if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { - if (Triple.getArch() == llvm::Triple::x86 || - Triple.getArch() == llvm::Triple::x86_64) { - ArchName = - (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; - } else if (Triple.getArch() == llvm::Triple::ppc || - Triple.getArch() == llvm::Triple::ppc64) { - ArchName = - (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64"; - } - } - llvm::Triple TargetTriple(getTriple()); - TargetTriple.setArchName(ArchName); - - ToolChain *TC; - - // XXX Cache toolchain even if -m32 is used - if (Arch == ArchName) { - TC = ToolChains[ArchName]; - if (TC) - return TC; - } - - TC = new toolchains::NetBSD(*this, TargetTriple, getTriple()); - - return TC; -} - -// Minix Host Info - -/// MinixHostInfo - Minix host information implementation. -class MinixHostInfo : public HostInfo { - /// Cache of tool chains we have created. - mutable llvm::StringMap<ToolChain*> ToolChains; - -public: - MinixHostInfo(const Driver &D, const llvm::Triple& Triple) - : HostInfo(D, Triple) {} - ~MinixHostInfo(); - - virtual bool useDriverDriver() const; - - virtual ToolChain *CreateToolChain(const ArgList &Args, - const char *ArchName) const; -}; - -MinixHostInfo::~MinixHostInfo() { - for (llvm::StringMap<ToolChain*>::iterator - it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it){ - delete it->second; - } -} - -bool MinixHostInfo::useDriverDriver() const { - return false; -} - -ToolChain *MinixHostInfo::CreateToolChain(const ArgList &Args, - const char *ArchName) const { - assert(!ArchName && - "Unexpected arch name on platform without driver driver support."); - - std::string Arch = getArchName(); - ArchName = Arch.c_str(); - - ToolChain *&TC = ToolChains[ArchName]; - if (!TC) { - llvm::Triple TCTriple(getTriple()); - TCTriple.setArchName(ArchName); - - TC = new toolchains::Minix(*this, TCTriple); - } - - return TC; -} - -// DragonFly Host Info - -/// DragonFlyHostInfo - DragonFly host information implementation. -class DragonFlyHostInfo : public HostInfo { - /// Cache of tool chains we have created. - mutable llvm::StringMap<ToolChain*> ToolChains; - -public: - DragonFlyHostInfo(const Driver &D, const llvm::Triple& Triple) - : HostInfo(D, Triple) {} - ~DragonFlyHostInfo(); - - virtual bool useDriverDriver() const; - - virtual ToolChain *CreateToolChain(const ArgList &Args, - const char *ArchName) const; -}; - -DragonFlyHostInfo::~DragonFlyHostInfo() { - for (llvm::StringMap<ToolChain*>::iterator - it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) - delete it->second; -} - -bool DragonFlyHostInfo::useDriverDriver() const { - return false; -} - -ToolChain *DragonFlyHostInfo::CreateToolChain(const ArgList &Args, - const char *ArchName) const { - assert(!ArchName && - "Unexpected arch name on platform without driver driver support."); - - ToolChain *&TC = ToolChains[getArchName()]; - - if (!TC) { - llvm::Triple TCTriple(getTriple()); - TCTriple.setArchName(getArchName()); - - TC = new toolchains::DragonFly(*this, TCTriple); - } - - return TC; -} - -// Linux Host Info - -/// LinuxHostInfo - Linux host information implementation. -class LinuxHostInfo : public HostInfo { - /// Cache of tool chains we have created. - mutable llvm::StringMap<ToolChain*> ToolChains; - -public: - LinuxHostInfo(const Driver &D, const llvm::Triple& Triple) - : HostInfo(D, Triple) {} - ~LinuxHostInfo(); - - virtual bool useDriverDriver() const; - - virtual ToolChain *CreateToolChain(const ArgList &Args, - const char *ArchName) const; -}; - -LinuxHostInfo::~LinuxHostInfo() { - for (llvm::StringMap<ToolChain*>::iterator - it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) - delete it->second; -} - -bool LinuxHostInfo::useDriverDriver() const { - return false; -} - -ToolChain *LinuxHostInfo::CreateToolChain(const ArgList &Args, - const char *ArchName) const { - - assert(!ArchName && - "Unexpected arch name on platform without driver driver support."); - - // Automatically handle some instances of -m32/-m64 we know about. - std::string Arch = getArchName(); - ArchName = Arch.c_str(); - if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { - if (Triple.getArch() == llvm::Triple::x86 || - Triple.getArch() == llvm::Triple::x86_64) { - ArchName = - (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; - } else if (Triple.getArch() == llvm::Triple::ppc || - Triple.getArch() == llvm::Triple::ppc64) { - ArchName = - (A->getOption().matches(options::OPT_m32)) ? "powerpc" : "powerpc64"; - } - } - - ToolChain *&TC = ToolChains[ArchName]; - - if (!TC) { - llvm::Triple TCTriple(getTriple()); - TCTriple.setArchName(ArchName); - - TC = new toolchains::Linux(*this, TCTriple); - } - - return TC; -} - -// Windows Host Info - -/// WindowsHostInfo - Host information to use on Microsoft Windows. -class WindowsHostInfo : public HostInfo { - /// Cache of tool chains we have created. - mutable llvm::StringMap<ToolChain*> ToolChains; - -public: - WindowsHostInfo(const Driver &D, const llvm::Triple& Triple); - ~WindowsHostInfo(); - - virtual bool useDriverDriver() const; - - virtual types::ID lookupTypeForExtension(const char *Ext) const { - return types::lookupTypeForExtension(Ext); - } - - virtual ToolChain *CreateToolChain(const ArgList &Args, - const char *ArchName) const; -}; - -WindowsHostInfo::WindowsHostInfo(const Driver &D, const llvm::Triple& Triple) - : HostInfo(D, Triple) { -} - -WindowsHostInfo::~WindowsHostInfo() { - for (llvm::StringMap<ToolChain*>::iterator - it = ToolChains.begin(), ie = ToolChains.end(); it != ie; ++it) - delete it->second; -} - -bool WindowsHostInfo::useDriverDriver() const { - return false; -} - -ToolChain *WindowsHostInfo::CreateToolChain(const ArgList &Args, - const char *ArchName) const { - assert(!ArchName && - "Unexpected arch name on platform without driver driver support."); - - // Automatically handle some instances of -m32/-m64 we know about. - std::string Arch = getArchName(); - ArchName = Arch.c_str(); - if (Arg *A = Args.getLastArg(options::OPT_m32, options::OPT_m64)) { - if (Triple.getArch() == llvm::Triple::x86 || - Triple.getArch() == llvm::Triple::x86_64) { - ArchName = - (A->getOption().matches(options::OPT_m32)) ? "i386" : "x86_64"; - } - } - - ToolChain *&TC = ToolChains[ArchName]; - if (!TC) { - llvm::Triple TCTriple(getTriple()); - TCTriple.setArchName(ArchName); - - TC = new toolchains::Windows(*this, TCTriple); - } - - return TC; -} - -// FIXME: This is a placeholder. -class MinGWHostInfo : public UnknownHostInfo { -public: - MinGWHostInfo(const Driver &D, const llvm::Triple& Triple); -}; - -MinGWHostInfo::MinGWHostInfo(const Driver &D, const llvm::Triple& Triple) - : UnknownHostInfo(D, Triple) {} - -} // end anon namespace - -const HostInfo * -clang::driver::createAuroraUXHostInfo(const Driver &D, - const llvm::Triple& Triple){ - return new AuroraUXHostInfo(D, Triple); -} - -const HostInfo * -clang::driver::createDarwinHostInfo(const Driver &D, - const llvm::Triple& Triple){ - return new DarwinHostInfo(D, Triple); -} - -const HostInfo * -clang::driver::createOpenBSDHostInfo(const Driver &D, - const llvm::Triple& Triple) { - return new OpenBSDHostInfo(D, Triple); -} - -const HostInfo * -clang::driver::createFreeBSDHostInfo(const Driver &D, - const llvm::Triple& Triple) { - return new FreeBSDHostInfo(D, Triple); -} - -const HostInfo * -clang::driver::createNetBSDHostInfo(const Driver &D, - const llvm::Triple& Triple) { - return new NetBSDHostInfo(D, Triple); -} - -const HostInfo * -clang::driver::createMinixHostInfo(const Driver &D, - const llvm::Triple& Triple) { - return new MinixHostInfo(D, Triple); -} - -const HostInfo * -clang::driver::createDragonFlyHostInfo(const Driver &D, - const llvm::Triple& Triple) { - return new DragonFlyHostInfo(D, Triple); -} - -const HostInfo * -clang::driver::createLinuxHostInfo(const Driver &D, - const llvm::Triple& Triple) { - return new LinuxHostInfo(D, Triple); -} - -const HostInfo * -clang::driver::createTCEHostInfo(const Driver &D, - const llvm::Triple& Triple) { - return new TCEHostInfo(D, Triple); -} - -const HostInfo * -clang::driver::createWindowsHostInfo(const Driver &D, - const llvm::Triple& Triple) { - return new WindowsHostInfo(D, Triple); -} - -const HostInfo * -clang::driver::createMinGWHostInfo(const Driver &D, - const llvm::Triple& Triple) { - return new MinGWHostInfo(D, Triple); -} - -const HostInfo * -clang::driver::createUnknownHostInfo(const Driver &D, - const llvm::Triple& Triple) { - return new UnknownHostInfo(D, Triple); -} diff --git a/contrib/llvm/tools/clang/lib/Driver/Job.cpp b/contrib/llvm/tools/clang/lib/Driver/Job.cpp index 5443d70..825c86a 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Job.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Job.cpp @@ -16,6 +16,8 @@ using namespace clang::driver; Job::~Job() {} +void Command::anchor() {} + Command::Command(const Action &_Source, const Tool &_Creator, const char *_Executable, const ArgStringList &_Arguments) : Job(CommandClass), Source(_Source), Creator(_Creator), diff --git a/contrib/llvm/tools/clang/lib/Driver/Option.cpp b/contrib/llvm/tools/clang/lib/Driver/Option.cpp index ee1963f..03360ea 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Option.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Option.cpp @@ -61,8 +61,6 @@ Option::~Option() { void Option::dump() const { llvm::errs() << "<"; switch (Kind) { - default: - llvm_unreachable("Invalid kind"); #define P(N) case N: llvm::errs() << #N; break P(GroupClass); P(InputClass); diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp index 9453848..db4d2a8 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChain.cpp @@ -14,31 +14,31 @@ #include "clang/Driver/ArgList.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" -#include "clang/Driver/HostInfo.h" #include "clang/Driver/ObjCRuntime.h" #include "clang/Driver/Options.h" +#include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ErrorHandling.h" using namespace clang::driver; using namespace clang; -ToolChain::ToolChain(const HostInfo &H, const llvm::Triple &T) - : Host(H), Triple(T) { +ToolChain::ToolChain(const Driver &D, const llvm::Triple &T) + : D(D), Triple(T) { } ToolChain::~ToolChain() { } const Driver &ToolChain::getDriver() const { - return Host.getDriver(); + return D; } std::string ToolChain::GetFilePath(const char *Name) const { - return Host.getDriver().GetFilePath(Name, *this); + return D.GetFilePath(Name, *this); } std::string ToolChain::GetProgramPath(const char *Name, bool WantFile) const { - return Host.getDriver().GetProgramPath(Name, *this, WantFile); + return D.GetProgramPath(Name, *this, WantFile); } types::ID ToolChain::LookupTypeForExtension(const char *Ext) const { @@ -55,6 +55,7 @@ void ToolChain::configureObjCRuntime(ObjCRuntime &runtime) const { // Assume a minimal NeXT runtime. runtime.HasARC = false; runtime.HasWeak = false; + runtime.HasSubscripting = false; runtime.HasTerminate = false; return; @@ -62,6 +63,7 @@ void ToolChain::configureObjCRuntime(ObjCRuntime &runtime) const { // Assume a maximal GNU runtime. runtime.HasARC = true; runtime.HasWeak = true; + runtime.HasSubscripting = false; // to be added runtime.HasTerminate = false; // to be added return; } @@ -73,11 +75,15 @@ void ToolChain::configureObjCRuntime(ObjCRuntime &runtime) const { // FIXME: tblgen this. static const char *getARMTargetCPU(const ArgList &Args, const llvm::Triple &Triple) { - // FIXME: Warn on inconsistent use of -mcpu and -march. - - // If we have -mcpu=, use that. - if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) - return A->getValue(Args); + // For Darwin targets, the -arch option (which is translated to a + // corresponding -march option) should determine the architecture + // (and the Mach-O slice) regardless of any -mcpu options. + if (!Triple.isOSDarwin()) { + // FIXME: Warn on inconsistent use of -mcpu and -march. + // If we have -mcpu=, use that. + if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) + return A->getValue(Args); + } StringRef MArch; if (Arg *A = Args.getLastArg(options::OPT_march_EQ)) { @@ -88,45 +94,27 @@ static const char *getARMTargetCPU(const ArgList &Args, MArch = Triple.getArchName(); } - if (MArch == "armv2" || MArch == "armv2a") - return "arm2"; - if (MArch == "armv3") - return "arm6"; - if (MArch == "armv3m") - return "arm7m"; - if (MArch == "armv4" || MArch == "armv4t") - return "arm7tdmi"; - if (MArch == "armv5" || MArch == "armv5t") - return "arm10tdmi"; - if (MArch == "armv5e" || MArch == "armv5te") - return "arm1026ejs"; - if (MArch == "armv5tej") - return "arm926ej-s"; - if (MArch == "armv6" || MArch == "armv6k") - return "arm1136jf-s"; - if (MArch == "armv6j") - return "arm1136j-s"; - if (MArch == "armv6z" || MArch == "armv6zk") - return "arm1176jzf-s"; - if (MArch == "armv6t2") - return "arm1156t2-s"; - if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a") - return "cortex-a8"; - if (MArch == "armv7r" || MArch == "armv7-r") - return "cortex-r4"; - if (MArch == "armv7m" || MArch == "armv7-m") - return "cortex-m3"; - if (MArch == "ep9312") - return "ep9312"; - if (MArch == "iwmmxt") - return "iwmmxt"; - if (MArch == "xscale") - return "xscale"; - if (MArch == "armv6m" || MArch == "armv6-m") - return "cortex-m0"; - - // If all else failed, return the most base CPU LLVM supports. - return "arm7tdmi"; + return llvm::StringSwitch<const char *>(MArch) + .Cases("armv2", "armv2a","arm2") + .Case("armv3", "arm6") + .Case("armv3m", "arm7m") + .Cases("armv4", "armv4t", "arm7tdmi") + .Cases("armv5", "armv5t", "arm10tdmi") + .Cases("armv5e", "armv5te", "arm1026ejs") + .Case("armv5tej", "arm926ej-s") + .Cases("armv6", "armv6k", "arm1136jf-s") + .Case("armv6j", "arm1136j-s") + .Cases("armv6z", "armv6zk", "arm1176jzf-s") + .Case("armv6t2", "arm1156t2-s") + .Cases("armv7", "armv7a", "armv7-a", "cortex-a8") + .Cases("armv7r", "armv7-r", "cortex-r4") + .Cases("armv7m", "armv7-m", "cortex-m3") + .Case("ep9312", "ep9312") + .Case("iwmmxt", "iwmmxt") + .Case("xscale", "xscale") + .Cases("armv6m", "armv6-m", "cortex-m0") + // If all else failed, return the most base CPU LLVM supports. + .Default("arm7tdmi"); } /// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular @@ -135,38 +123,23 @@ static const char *getARMTargetCPU(const ArgList &Args, // FIXME: This is redundant with -mcpu, why does LLVM use this. // FIXME: tblgen this, or kill it! static const char *getLLVMArchSuffixForARM(StringRef CPU) { - if (CPU == "arm7tdmi" || CPU == "arm7tdmi-s" || CPU == "arm710t" || - CPU == "arm720t" || CPU == "arm9" || CPU == "arm9tdmi" || - CPU == "arm920" || CPU == "arm920t" || CPU == "arm922t" || - CPU == "arm940t" || CPU == "ep9312") - return "v4t"; - - if (CPU == "arm10tdmi" || CPU == "arm1020t") - return "v5"; - - if (CPU == "arm9e" || CPU == "arm926ej-s" || CPU == "arm946e-s" || - CPU == "arm966e-s" || CPU == "arm968e-s" || CPU == "arm10e" || - CPU == "arm1020e" || CPU == "arm1022e" || CPU == "xscale" || - CPU == "iwmmxt") - return "v5e"; - - if (CPU == "arm1136j-s" || CPU == "arm1136jf-s" || CPU == "arm1176jz-s" || - CPU == "arm1176jzf-s" || CPU == "mpcorenovfp" || CPU == "mpcore") - return "v6"; - - if (CPU == "arm1156t2-s" || CPU == "arm1156t2f-s") - return "v6t2"; - - if (CPU == "cortex-a8" || CPU == "cortex-a9") - return "v7"; - - if (CPU == "cortex-m3") - return "v7m"; - - if (CPU == "cortex-m0") - return "v6m"; - - return ""; + return llvm::StringSwitch<const char *>(CPU) + .Cases("arm7tdmi", "arm7tdmi-s", "arm710t", "v4t") + .Cases("arm720t", "arm9", "arm9tdmi", "v4t") + .Cases("arm920", "arm920t", "arm922t", "v4t") + .Cases("arm940t", "ep9312","v4t") + .Cases("arm10tdmi", "arm1020t", "v5") + .Cases("arm9e", "arm926ej-s", "arm946e-s", "v5e") + .Cases("arm966e-s", "arm968e-s", "arm10e", "v5e") + .Cases("arm1020e", "arm1022e", "xscale", "iwmmxt", "v5e") + .Cases("arm1136j-s", "arm1136jf-s", "arm1176jz-s", "v6") + .Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6") + .Cases("arm1156t2-s", "arm1156t2f-s", "v6t2") + .Cases("cortex-a8", "cortex-a9", "v7") + .Case("cortex-m3", "v7m") + .Case("cortex-m4", "v7m") + .Case("cortex-m0", "v6m") + .Default(""); } std::string ToolChain::ComputeLLVMTriple(const ArgList &Args, @@ -216,6 +189,22 @@ void ToolChain::AddClangSystemIncludeArgs(const ArgList &DriverArgs, // Each toolchain should provide the appropriate include flags. } +ToolChain::RuntimeLibType ToolChain::GetRuntimeLibType( + const ArgList &Args) const +{ + if (Arg *A = Args.getLastArg(options::OPT_rtlib_EQ)) { + StringRef Value = A->getValue(Args); + if (Value == "compiler-rt") + return ToolChain::RLT_CompilerRT; + if (Value == "libgcc") + return ToolChain::RLT_Libgcc; + getDriver().Diag(diag::err_drv_invalid_rtlib_name) + << A->getAsString(Args); + } + + return GetDefaultRuntimeLibType(); +} + ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) { StringRef Value = A->getValue(Args); @@ -230,6 +219,40 @@ ToolChain::CXXStdlibType ToolChain::GetCXXStdlibType(const ArgList &Args) const{ return ToolChain::CST_Libstdcxx; } +/// \brief Utility function to add a system include directory to CC1 arguments. +/*static*/ void ToolChain::addSystemInclude(const ArgList &DriverArgs, + ArgStringList &CC1Args, + const Twine &Path) { + CC1Args.push_back("-internal-isystem"); + CC1Args.push_back(DriverArgs.MakeArgString(Path)); +} + +/// \brief Utility function to add a system include directory with extern "C" +/// semantics to CC1 arguments. +/// +/// Note that this should be used rarely, and only for directories that +/// historically and for legacy reasons are treated as having implicit extern +/// "C" semantics. These semantics are *ignored* by and large today, but its +/// important to preserve the preprocessor changes resulting from the +/// classification. +/*static*/ void ToolChain::addExternCSystemInclude(const ArgList &DriverArgs, + ArgStringList &CC1Args, + const Twine &Path) { + CC1Args.push_back("-internal-externc-isystem"); + CC1Args.push_back(DriverArgs.MakeArgString(Path)); +} + +/// \brief Utility function to add a list of system include directories to CC1. +/*static*/ void ToolChain::addSystemIncludes(const ArgList &DriverArgs, + ArgStringList &CC1Args, + ArrayRef<StringRef> Paths) { + for (ArrayRef<StringRef>::iterator I = Paths.begin(), E = Paths.end(); + I != E; ++I) { + CC1Args.push_back("-internal-isystem"); + CC1Args.push_back(DriverArgs.MakeArgString(*I)); + } +} + void ToolChain::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, ArgStringList &CC1Args) const { // Header search paths should be handled by each of the subclasses. diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp index 80394ac..fa9ed49 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.cpp @@ -9,16 +9,11 @@ #include "ToolChains.h" -#ifdef HAVE_CLANG_CONFIG_H -# include "clang/Config/config.h" -#endif - #include "clang/Driver/Arg.h" #include "clang/Driver/ArgList.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Driver.h" #include "clang/Driver/DriverDiagnostic.h" -#include "clang/Driver/HostInfo.h" #include "clang/Driver/ObjCRuntime.h" #include "clang/Driver/OptTable.h" #include "clang/Driver/Option.h" @@ -38,16 +33,7 @@ #include <cstdlib> // ::getenv -#include "llvm/Config/config.h" // for CXX_INCLUDE_ROOT - -// Include the necessary headers to interface with the Windows registry and -// environment. -#ifdef _MSC_VER - #define WIN32_LEAN_AND_MEAN 1 - #include <Windows.h> - #undef min - #undef max -#endif +#include "clang/Config/config.h" // for GCC_INSTALL_PREFIX #ifndef CLANG_PREFIX #define CLANG_PREFIX @@ -57,56 +43,26 @@ using namespace clang::driver; using namespace clang::driver::toolchains; using namespace clang; -/// \brief Utility function to add a system include directory to CC1 arguments. -static void addSystemInclude(const ArgList &DriverArgs, ArgStringList &CC1Args, - const Twine &Path) { - CC1Args.push_back("-internal-isystem"); - CC1Args.push_back(DriverArgs.MakeArgString(Path)); -} - -/// \brief Utility function to add a system include directory with extern "C" -/// semantics to CC1 arguments. -/// -/// Note that this should be used rarely, and only for directories that -/// historically and for legacy reasons are treated as having implicit extern -/// "C" semantics. These semantics are *ignored* by and large today, but its -/// important to preserve the preprocessor changes resulting from the -/// classification. -static void addExternCSystemInclude(const ArgList &DriverArgs, - ArgStringList &CC1Args, const Twine &Path) { - CC1Args.push_back("-internal-externc-isystem"); - CC1Args.push_back(DriverArgs.MakeArgString(Path)); -} - -/// \brief Utility function to add a list of system include directories to CC1. -static void addSystemIncludes(const ArgList &DriverArgs, - ArgStringList &CC1Args, - ArrayRef<StringRef> Paths) { - for (ArrayRef<StringRef>::iterator I = Paths.begin(), E = Paths.end(); - I != E; ++I) { - CC1Args.push_back("-internal-isystem"); - CC1Args.push_back(DriverArgs.MakeArgString(*I)); - } -} - /// Darwin - Darwin tool chain for i386 and x86_64. -Darwin::Darwin(const HostInfo &Host, const llvm::Triple& Triple) - : ToolChain(Host, Triple), TargetInitialized(false), +Darwin::Darwin(const Driver &D, const llvm::Triple& Triple) + : ToolChain(D, Triple), TargetInitialized(false), ARCRuntimeForSimulator(ARCSimulator_None), LibCXXForSimulator(LibCXXSimulator_None) { - // Compute the initial Darwin version based on the host. - bool HadExtra; - std::string OSName = Triple.getOSName(); - if (!Driver::GetReleaseVersion(&OSName.c_str()[6], - DarwinVersion[0], DarwinVersion[1], - DarwinVersion[2], HadExtra)) - getDriver().Diag(diag::err_drv_invalid_darwin_version) << OSName; - + // Compute the initial Darwin version from the triple + unsigned Major, Minor, Micro; + if (!Triple.getMacOSXVersion(Major, Minor, Micro)) + getDriver().Diag(diag::err_drv_invalid_darwin_version) << + Triple.getOSName(); llvm::raw_string_ostream(MacosxVersionMin) - << "10." << std::max(0, (int)DarwinVersion[0] - 4) << '.' - << DarwinVersion[1]; + << Major << '.' << Minor << '.' << Micro; + + // FIXME: DarwinVersion is only used to find GCC's libexec directory. + // It should be removed when we stop supporting that. + DarwinVersion[0] = Minor + 4; + DarwinVersion[1] = Micro; + DarwinVersion[2] = 0; } types::ID Darwin::LookupTypeForExtension(const char *Ext) const { @@ -141,12 +97,17 @@ bool Darwin::hasARCRuntime() const { return !isMacosxVersionLT(10, 7); } +bool Darwin::hasSubscriptingRuntime() const { + return !isTargetIPhoneOS() && !isMacosxVersionLT(10, 8); +} + /// Darwin provides an ARC runtime starting in MacOS X 10.7 and iOS 5.0. void Darwin::configureObjCRuntime(ObjCRuntime &runtime) const { if (runtime.getKind() != ObjCRuntime::NeXT) return ToolChain::configureObjCRuntime(runtime); runtime.HasARC = runtime.HasWeak = hasARCRuntime(); + runtime.HasSubscripting = hasSubscriptingRuntime(); // So far, objc_terminate is only available in iOS 5. // FIXME: do the simulator logic properly. @@ -225,18 +186,16 @@ std::string Darwin::ComputeEffectiveClangTriple(const ArgList &Args, if (!isTargetInitialized()) return Triple.getTriple(); - unsigned Version[3]; - getTargetVersion(Version); - - llvm::SmallString<16> Str; - llvm::raw_svector_ostream(Str) - << (isTargetIPhoneOS() ? "ios" : "macosx") - << Version[0] << "." << Version[1] << "." << Version[2]; - Triple.setOSName(Str.str()); + SmallString<16> Str; + Str += isTargetIPhoneOS() ? "ios" : "macosx"; + Str += getTargetVersion().getAsString(); + Triple.setOSName(Str); return Triple.getTriple(); } +void Generic_ELF::anchor() {} + Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const { Action::ActionClass Key; @@ -255,15 +214,9 @@ Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA, } else Key = JA.getKind(); - // FIXME: This doesn't belong here, but ideally we will support static soon - // anyway. - bool HasStatic = (C.getArgs().hasArg(options::OPT_mkernel) || - C.getArgs().hasArg(options::OPT_static) || - C.getArgs().hasArg(options::OPT_fapple_kext)); - bool IsIADefault = IsIntegratedAssemblerDefault() && !HasStatic; bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as, options::OPT_no_integrated_as, - IsIADefault); + IsIntegratedAssemblerDefault()); Tool *&T = Tools[Key]; if (!T) { @@ -274,6 +227,7 @@ Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA, case Action::PreprocessJobClass: T = new tools::darwin::Preprocess(*this); break; case Action::AnalyzeJobClass: + case Action::MigrateJobClass: T = new tools::Clang(*this); break; case Action::PrecompileJobClass: case Action::CompileJobClass: @@ -300,8 +254,8 @@ Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA, } -DarwinClang::DarwinClang(const HostInfo &Host, const llvm::Triple& Triple) - : Darwin(Host, Triple) +DarwinClang::DarwinClang(const Driver &D, const llvm::Triple& Triple) + : Darwin(D, Triple) { getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().getInstalledDir() != getDriver().Dir) @@ -344,8 +298,11 @@ void DarwinClang::AddLinkSearchPathArgs(const ArgList &Args, // Unfortunately, we still might depend on a few of the libraries that are // only available in the gcc library directory (in particular // libstdc++.dylib). For now, hardcode the path to the known install location. + // FIXME: This should get ripped out someday. However, when building on + // 10.6 (darwin10), we're still relying on this to find libstdc++.dylib. llvm::sys::Path P(getDriver().Dir); P.eraseComponent(); // .../usr/bin -> ../usr + P.appendComponent("llvm-gcc-4.2"); P.appendComponent("lib"); P.appendComponent("gcc"); switch (getTriple().getArch()) { @@ -416,9 +373,11 @@ void DarwinClang::AddLinkARCArgs(const ArgList &Args, P.appendComponent("libarclite_"); std::string s = P.str(); // Mash in the platform. - if (isTargetIPhoneOS()) + if (isTargetIOSSimulator()) + s += "iphonesimulator"; + else if (isTargetIPhoneOS()) s += "iphoneos"; - // FIXME: isTargetIphoneOSSimulator() is not returning true. + // FIXME: Remove this once we depend fully on -mios-simulator-version-min. else if (ARCRuntimeForSimulator != ARCSimulator_None) s += "iphonesimulator"; else @@ -445,6 +404,16 @@ void DarwinClang::AddLinkRuntimeLib(const ArgList &Args, void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, ArgStringList &CmdArgs) const { + // Darwin only supports the compiler-rt based runtime libraries. + switch (GetRuntimeLibType(Args)) { + case ToolChain::RLT_CompilerRT: + break; + default: + getDriver().Diag(diag::err_drv_unsupported_rtlib_for_platform) + << Args.getLastArg(options::OPT_rtlib_EQ)->getValue(Args) << "darwin"; + return; + } + // Darwin doesn't support real static executables, don't link any runtime // libraries with -static. if (Args.hasArg(options::OPT_static)) @@ -459,6 +428,38 @@ void DarwinClang::AddLinkRuntimeLibArgs(const ArgList &Args, return; } + // If we are building profile support, link that library in. + if (Args.hasArg(options::OPT_fprofile_arcs) || + Args.hasArg(options::OPT_fprofile_generate) || + Args.hasArg(options::OPT_fcreate_profile) || + Args.hasArg(options::OPT_coverage)) { + // Select the appropriate runtime library for the target. + if (isTargetIPhoneOS()) { + AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_ios.a"); + } else { + AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.profile_osx.a"); + } + } + + // Add ASAN runtime library, if required. Dynamic libraries and bundles + // should not be linked with the runtime library. + if (Args.hasFlag(options::OPT_faddress_sanitizer, + options::OPT_fno_address_sanitizer, false)) { + if (Args.hasArg(options::OPT_dynamiclib) || + Args.hasArg(options::OPT_bundle)) return; + if (isTargetIPhoneOS()) { + getDriver().Diag(diag::err_drv_clang_unsupported_per_platform) + << "-faddress-sanitizer"; + } else { + AddLinkRuntimeLib(Args, CmdArgs, "libclang_rt.asan_osx.a"); + + // The ASAN runtime library requires C++ and CoreFoundation. + AddCXXStdlibLibArgs(Args, CmdArgs); + CmdArgs.push_back("-framework"); + CmdArgs.push_back("CoreFoundation"); + } + } + // Otherwise link libSystem, then the dynamic runtime library, and finally any // target specific static runtime library. CmdArgs.push_back("-lSystem"); @@ -540,7 +541,7 @@ void Darwin::AddDeploymentTarget(DerivedArgList &Args) const { // '-miphoneos-version-min' to help us know whether there is an ARC runtime // or not; try to parse a __IPHONE_OS_VERSION_MIN_REQUIRED // define passed in command-line. - if (!iOSVersion) { + if (!iOSVersion && !iOSSimVersion) { for (arg_iterator it = Args.filtered_begin(options::OPT_D), ie = Args.filtered_end(); it != ie; ++it) { StringRef define = (*it)->getValue(Args); @@ -717,6 +718,8 @@ void DarwinClang::AddCXXStdlibLibArgs(const ArgList &Args, } // Otherwise, look in the root. + // FIXME: This should be removed someday when we don't have to care about + // 10.6 and earlier, where /usr/lib/libstdc++.dylib does not exist. if ((llvm::sys::fs::exists("/usr/lib/libstdc++.dylib", Exists) || !Exists)&& (!llvm::sys::fs::exists("/usr/lib/libstdc++.6.dylib", Exists) && Exists)){ CmdArgs.push_back("/usr/lib/libstdc++.6.dylib"); @@ -1022,6 +1025,10 @@ bool Darwin::SupportsObjCGC() const { return !isTargetIPhoneOS(); } +bool Darwin::SupportsObjCARC() const { + return isTargetIPhoneOS() || !isMacosxVersionLT(10, 6); +} + std::string Darwin_Generic_GCC::ComputeEffectiveClangTriple(const ArgList &Args, types::ID InputType) const { @@ -1032,8 +1039,345 @@ Darwin_Generic_GCC::ComputeEffectiveClangTriple(const ArgList &Args, /// all subcommands; this relies on gcc translating the majority of /// command line options. -Generic_GCC::Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple) - : ToolChain(Host, Triple) { +/// \brief Parse a GCCVersion object out of a string of text. +/// +/// This is the primary means of forming GCCVersion objects. +/*static*/ +Generic_GCC::GCCVersion Linux::GCCVersion::Parse(StringRef VersionText) { + const GCCVersion BadVersion = { VersionText.str(), -1, -1, -1, "" }; + std::pair<StringRef, StringRef> First = VersionText.split('.'); + std::pair<StringRef, StringRef> Second = First.second.split('.'); + + GCCVersion GoodVersion = { VersionText.str(), -1, -1, -1, "" }; + if (First.first.getAsInteger(10, GoodVersion.Major) || + GoodVersion.Major < 0) + return BadVersion; + if (Second.first.getAsInteger(10, GoodVersion.Minor) || + GoodVersion.Minor < 0) + return BadVersion; + + // First look for a number prefix and parse that if present. Otherwise just + // stash the entire patch string in the suffix, and leave the number + // unspecified. This covers versions strings such as: + // 4.4 + // 4.4.0 + // 4.4.x + // 4.4.2-rc4 + // 4.4.x-patched + // And retains any patch number it finds. + StringRef PatchText = GoodVersion.PatchSuffix = Second.second.str(); + if (!PatchText.empty()) { + if (unsigned EndNumber = PatchText.find_first_not_of("0123456789")) { + // Try to parse the number and any suffix. + if (PatchText.slice(0, EndNumber).getAsInteger(10, GoodVersion.Patch) || + GoodVersion.Patch < 0) + return BadVersion; + GoodVersion.PatchSuffix = PatchText.substr(EndNumber).str(); + } + } + + return GoodVersion; +} + +/// \brief Less-than for GCCVersion, implementing a Strict Weak Ordering. +bool Generic_GCC::GCCVersion::operator<(const GCCVersion &RHS) const { + if (Major < RHS.Major) return true; if (Major > RHS.Major) return false; + if (Minor < RHS.Minor) return true; if (Minor > RHS.Minor) return false; + + // Note that we rank versions with *no* patch specified is better than ones + // hard-coding a patch version. Thus if the RHS has no patch, it always + // wins, and the LHS only wins if it has no patch and the RHS does have + // a patch. + if (RHS.Patch == -1) return true; if (Patch == -1) return false; + if (Patch < RHS.Patch) return true; if (Patch > RHS.Patch) return false; + + // Finally, between completely tied version numbers, the version with the + // suffix loses as we prefer full releases. + if (RHS.PatchSuffix.empty()) return true; + return false; +} + +static StringRef getGCCToolchainDir(const ArgList &Args) { + const Arg *A = Args.getLastArg(options::OPT_gcc_toolchain); + if (A) + return A->getValue(Args); + return GCC_INSTALL_PREFIX; +} + +/// \brief Construct a GCCInstallationDetector from the driver. +/// +/// This performs all of the autodetection and sets up the various paths. +/// Once constructed, a GCCInstallation is esentially immutable. +/// +/// FIXME: We shouldn't need an explicit TargetTriple parameter here, and +/// should instead pull the target out of the driver. This is currently +/// necessary because the driver doesn't store the final version of the target +/// triple. +Generic_GCC::GCCInstallationDetector::GCCInstallationDetector( + const Driver &D, + const llvm::Triple &TargetTriple, + const ArgList &Args) + : IsValid(false) { + llvm::Triple MultiarchTriple + = TargetTriple.isArch32Bit() ? TargetTriple.get64BitArchVariant() + : TargetTriple.get32BitArchVariant(); + llvm::Triple::ArchType TargetArch = TargetTriple.getArch(); + // The library directories which may contain GCC installations. + SmallVector<StringRef, 4> CandidateLibDirs, CandidateMultiarchLibDirs; + // The compatible GCC triples for this particular architecture. + SmallVector<StringRef, 10> CandidateTripleAliases; + SmallVector<StringRef, 10> CandidateMultiarchTripleAliases; + CollectLibDirsAndTriples(TargetTriple, MultiarchTriple, CandidateLibDirs, + CandidateTripleAliases, + CandidateMultiarchLibDirs, + CandidateMultiarchTripleAliases); + + // Compute the set of prefixes for our search. + SmallVector<std::string, 8> Prefixes(D.PrefixDirs.begin(), + D.PrefixDirs.end()); + + StringRef GCCToolchainDir = getGCCToolchainDir(Args); + if (GCCToolchainDir != "") { + if (GCCToolchainDir.back() == '/') + GCCToolchainDir = GCCToolchainDir.drop_back(); // remove the / + + Prefixes.push_back(GCCToolchainDir); + } else { + Prefixes.push_back(D.SysRoot); + Prefixes.push_back(D.SysRoot + "/usr"); + Prefixes.push_back(D.InstalledDir + "/.."); + } + + // Loop over the various components which exist and select the best GCC + // installation available. GCC installs are ranked by version number. + Version = GCCVersion::Parse("0.0.0"); + for (unsigned i = 0, ie = Prefixes.size(); i < ie; ++i) { + if (!llvm::sys::fs::exists(Prefixes[i])) + continue; + for (unsigned j = 0, je = CandidateLibDirs.size(); j < je; ++j) { + const std::string LibDir = Prefixes[i] + CandidateLibDirs[j].str(); + if (!llvm::sys::fs::exists(LibDir)) + continue; + for (unsigned k = 0, ke = CandidateTripleAliases.size(); k < ke; ++k) + ScanLibDirForGCCTriple(TargetArch, LibDir, CandidateTripleAliases[k]); + } + for (unsigned j = 0, je = CandidateMultiarchLibDirs.size(); j < je; ++j) { + const std::string LibDir + = Prefixes[i] + CandidateMultiarchLibDirs[j].str(); + if (!llvm::sys::fs::exists(LibDir)) + continue; + for (unsigned k = 0, ke = CandidateMultiarchTripleAliases.size(); k < ke; + ++k) + ScanLibDirForGCCTriple(TargetArch, LibDir, + CandidateMultiarchTripleAliases[k], + /*NeedsMultiarchSuffix=*/true); + } + } +} + +/*static*/ void Generic_GCC::GCCInstallationDetector::CollectLibDirsAndTriples( + const llvm::Triple &TargetTriple, + const llvm::Triple &MultiarchTriple, + SmallVectorImpl<StringRef> &LibDirs, + SmallVectorImpl<StringRef> &TripleAliases, + SmallVectorImpl<StringRef> &MultiarchLibDirs, + SmallVectorImpl<StringRef> &MultiarchTripleAliases) { + // Declare a bunch of static data sets that we'll select between below. These + // are specifically designed to always refer to string literals to avoid any + // lifetime or initialization issues. + static const char *const ARMLibDirs[] = { "/lib" }; + static const char *const ARMTriples[] = { + "arm-linux-gnueabi", + "arm-linux-androideabi" + }; + + static const char *const X86_64LibDirs[] = { "/lib64", "/lib" }; + static const char *const X86_64Triples[] = { + "x86_64-linux-gnu", + "x86_64-unknown-linux-gnu", + "x86_64-pc-linux-gnu", + "x86_64-redhat-linux6E", + "x86_64-redhat-linux", + "x86_64-suse-linux", + "x86_64-manbo-linux-gnu", + "x86_64-linux-gnu", + "x86_64-slackware-linux" + }; + static const char *const X86LibDirs[] = { "/lib32", "/lib" }; + static const char *const X86Triples[] = { + "i686-linux-gnu", + "i686-pc-linux-gnu", + "i486-linux-gnu", + "i386-linux-gnu", + "i686-redhat-linux", + "i586-redhat-linux", + "i386-redhat-linux", + "i586-suse-linux", + "i486-slackware-linux" + }; + + static const char *const MIPSLibDirs[] = { "/lib" }; + static const char *const MIPSTriples[] = { "mips-linux-gnu" }; + static const char *const MIPSELLibDirs[] = { "/lib" }; + static const char *const MIPSELTriples[] = { "mipsel-linux-gnu" }; + + static const char *const PPCLibDirs[] = { "/lib32", "/lib" }; + static const char *const PPCTriples[] = { + "powerpc-linux-gnu", + "powerpc-unknown-linux-gnu", + "powerpc-suse-linux" + }; + static const char *const PPC64LibDirs[] = { "/lib64", "/lib" }; + static const char *const PPC64Triples[] = { + "powerpc64-linux-gnu", + "powerpc64-unknown-linux-gnu", + "powerpc64-suse-linux", + "ppc64-redhat-linux" + }; + + switch (TargetTriple.getArch()) { + case llvm::Triple::arm: + case llvm::Triple::thumb: + LibDirs.append(ARMLibDirs, ARMLibDirs + llvm::array_lengthof(ARMLibDirs)); + TripleAliases.append( + ARMTriples, ARMTriples + llvm::array_lengthof(ARMTriples)); + break; + case llvm::Triple::x86_64: + LibDirs.append( + X86_64LibDirs, X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs)); + TripleAliases.append( + X86_64Triples, X86_64Triples + llvm::array_lengthof(X86_64Triples)); + MultiarchLibDirs.append( + X86LibDirs, X86LibDirs + llvm::array_lengthof(X86LibDirs)); + MultiarchTripleAliases.append( + X86Triples, X86Triples + llvm::array_lengthof(X86Triples)); + break; + case llvm::Triple::x86: + LibDirs.append(X86LibDirs, X86LibDirs + llvm::array_lengthof(X86LibDirs)); + TripleAliases.append( + X86Triples, X86Triples + llvm::array_lengthof(X86Triples)); + MultiarchLibDirs.append( + X86_64LibDirs, X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs)); + MultiarchTripleAliases.append( + X86_64Triples, X86_64Triples + llvm::array_lengthof(X86_64Triples)); + break; + case llvm::Triple::mips: + LibDirs.append( + MIPSLibDirs, MIPSLibDirs + llvm::array_lengthof(MIPSLibDirs)); + TripleAliases.append( + MIPSTriples, MIPSTriples + llvm::array_lengthof(MIPSTriples)); + break; + case llvm::Triple::mipsel: + LibDirs.append( + MIPSELLibDirs, MIPSELLibDirs + llvm::array_lengthof(MIPSELLibDirs)); + TripleAliases.append( + MIPSELTriples, MIPSELTriples + llvm::array_lengthof(MIPSELTriples)); + break; + case llvm::Triple::ppc: + LibDirs.append(PPCLibDirs, PPCLibDirs + llvm::array_lengthof(PPCLibDirs)); + TripleAliases.append( + PPCTriples, PPCTriples + llvm::array_lengthof(PPCTriples)); + MultiarchLibDirs.append( + PPC64LibDirs, PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs)); + MultiarchTripleAliases.append( + PPC64Triples, PPC64Triples + llvm::array_lengthof(PPC64Triples)); + break; + case llvm::Triple::ppc64: + LibDirs.append( + PPC64LibDirs, PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs)); + TripleAliases.append( + PPC64Triples, PPC64Triples + llvm::array_lengthof(PPC64Triples)); + MultiarchLibDirs.append( + PPCLibDirs, PPCLibDirs + llvm::array_lengthof(PPCLibDirs)); + MultiarchTripleAliases.append( + PPCTriples, PPCTriples + llvm::array_lengthof(PPCTriples)); + break; + + default: + // By default, just rely on the standard lib directories and the original + // triple. + break; + } + + // Always append the drivers target triple to the end, in case it doesn't + // match any of our aliases. + TripleAliases.push_back(TargetTriple.str()); + + // Also include the multiarch variant if it's different. + if (TargetTriple.str() != MultiarchTriple.str()) + MultiarchTripleAliases.push_back(MultiarchTriple.str()); +} + +void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( + llvm::Triple::ArchType TargetArch, const std::string &LibDir, + StringRef CandidateTriple, bool NeedsMultiarchSuffix) { + // There are various different suffixes involving the triple we + // check for. We also record what is necessary to walk from each back + // up to the lib directory. + const std::string LibSuffixes[] = { + "/gcc/" + CandidateTriple.str(), + "/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(), + + // Ubuntu has a strange mis-matched pair of triples that this happens to + // match. + // FIXME: It may be worthwhile to generalize this and look for a second + // triple. + "/i386-linux-gnu/gcc/" + CandidateTriple.str() + }; + const std::string InstallSuffixes[] = { + "/../../..", + "/../../../..", + "/../../../.." + }; + // Only look at the final, weird Ubuntu suffix for i386-linux-gnu. + const unsigned NumLibSuffixes = (llvm::array_lengthof(LibSuffixes) - + (TargetArch != llvm::Triple::x86)); + for (unsigned i = 0; i < NumLibSuffixes; ++i) { + StringRef LibSuffix = LibSuffixes[i]; + llvm::error_code EC; + for (llvm::sys::fs::directory_iterator LI(LibDir + LibSuffix, EC), LE; + !EC && LI != LE; LI = LI.increment(EC)) { + StringRef VersionText = llvm::sys::path::filename(LI->path()); + GCCVersion CandidateVersion = GCCVersion::Parse(VersionText); + static const GCCVersion MinVersion = { "4.1.1", 4, 1, 1, "" }; + if (CandidateVersion < MinVersion) + continue; + if (CandidateVersion <= Version) + continue; + + // Some versions of SUSE and Fedora on ppc64 put 32-bit libs + // in what would normally be GCCInstallPath and put the 64-bit + // libs in a subdirectory named 64. The simple logic we follow is that + // *if* there is a subdirectory of the right name with crtbegin.o in it, + // we use that. If not, and if not a multiarch triple, we look for + // crtbegin.o without the subdirectory. + StringRef MultiarchSuffix + = (TargetArch == llvm::Triple::x86_64 || + TargetArch == llvm::Triple::ppc64) ? "/64" : "/32"; + if (llvm::sys::fs::exists(LI->path() + MultiarchSuffix + "/crtbegin.o")) { + GCCMultiarchSuffix = MultiarchSuffix.str(); + } else { + if (NeedsMultiarchSuffix || + !llvm::sys::fs::exists(LI->path() + "/crtbegin.o")) + continue; + GCCMultiarchSuffix.clear(); + } + + Version = CandidateVersion; + GCCTriple.setTriple(CandidateTriple); + // FIXME: We hack together the directory name here instead of + // using LI to ensure stable path separators across Windows and + // Linux. + GCCInstallPath = LibDir + LibSuffixes[i] + "/" + VersionText.str(); + GCCParentLibPath = GCCInstallPath + InstallSuffixes[i]; + IsValid = true; + } + } +} + +Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple& Triple, + const ArgList &Args) + : ToolChain(D, Triple), GCCInstallation(getDriver(), Triple, Args) { getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().getInstalledDir() != getDriver().Dir) getProgramPaths().push_back(getDriver().Dir); @@ -1066,6 +1410,7 @@ Tool &Generic_GCC::SelectTool(const Compilation &C, case Action::PrecompileJobClass: T = new tools::gcc::Precompile(*this); break; case Action::AnalyzeJobClass: + case Action::MigrateJobClass: T = new tools::Clang(*this); break; case Action::CompileJobClass: T = new tools::gcc::Compile(*this); break; @@ -1101,13 +1446,80 @@ const char *Generic_GCC::GetDefaultRelocationModel() const { const char *Generic_GCC::GetForcedPicModel() const { return 0; } +/// Hexagon Toolchain + +Hexagon_TC::Hexagon_TC(const Driver &D, const llvm::Triple& Triple) + : ToolChain(D, Triple) { + getProgramPaths().push_back(getDriver().getInstalledDir()); + if (getDriver().getInstalledDir() != getDriver().Dir.c_str()) + getProgramPaths().push_back(getDriver().Dir); +} + +Hexagon_TC::~Hexagon_TC() { + // Free tool implementations. + for (llvm::DenseMap<unsigned, Tool*>::iterator + it = Tools.begin(), ie = Tools.end(); it != ie; ++it) + delete it->second; +} + +Tool &Hexagon_TC::SelectTool(const Compilation &C, + const JobAction &JA, + const ActionList &Inputs) const { + Action::ActionClass Key; + // if (JA.getKind () == Action::CompileJobClass) + // Key = JA.getKind (); + // else + + if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) + Key = Action::AnalyzeJobClass; + else + Key = JA.getKind(); + // if ((JA.getKind () == Action::CompileJobClass) + // && (JA.getType () != types::TY_LTO_BC)) { + // Key = JA.getKind (); + // } + + Tool *&T = Tools[Key]; + if (!T) { + switch (Key) { + case Action::InputClass: + case Action::BindArchClass: + assert(0 && "Invalid tool kind."); + case Action::AnalyzeJobClass: + T = new tools::Clang(*this); break; + case Action::AssembleJobClass: + T = new tools::hexagon::Assemble(*this); break; + case Action::LinkJobClass: + T = new tools::hexagon::Link(*this); break; + default: + assert(false && "Unsupported action for Hexagon target."); + } + } + + return *T; +} + +bool Hexagon_TC::IsUnwindTablesDefault() const { + // FIXME: Gross; we should probably have some separate target + // definition, possibly even reusing the one in clang. + return getArchName() == "x86_64"; +} + +const char *Hexagon_TC::GetDefaultRelocationModel() const { + return "static"; +} + +const char *Hexagon_TC::GetForcedPicModel() const { + return 0; +} // End Hexagon + /// TCEToolChain - A tool chain using the llvm bitcode tools to perform /// all subcommands. See http://tce.cs.tut.fi for our peculiar target. /// Currently does not support anything else but compilation. -TCEToolChain::TCEToolChain(const HostInfo &Host, const llvm::Triple& Triple) - : ToolChain(Host, Triple) { +TCEToolChain::TCEToolChain(const Driver &D, const llvm::Triple& Triple) + : ToolChain(D, Triple) { // Path mangling to find libexec std::string Path(getDriver().Dir); @@ -1159,8 +1571,8 @@ Tool &TCEToolChain::SelectTool(const Compilation &C, /// OpenBSD - OpenBSD tool chain which can call as(1) and ld(1) directly. -OpenBSD::OpenBSD(const HostInfo &Host, const llvm::Triple& Triple) - : Generic_ELF(Host, Triple) { +OpenBSD::OpenBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) + : Generic_ELF(D, Triple, Args) { getFilePaths().push_back(getDriver().Dir + "/../lib"); getFilePaths().push_back("/usr/lib"); } @@ -1199,26 +1611,17 @@ Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA, /// FreeBSD - FreeBSD tool chain which can call as(1) and ld(1) directly. -FreeBSD::FreeBSD(const HostInfo &Host, const llvm::Triple& Triple) - : Generic_ELF(Host, Triple) { - - // Determine if we are compiling 32-bit code on an x86_64 platform. - bool Lib32 = false; - if (Triple.getArch() == llvm::Triple::x86 && - llvm::Triple(getDriver().DefaultHostTriple).getArch() == - llvm::Triple::x86_64) - Lib32 = true; +FreeBSD::FreeBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) + : Generic_ELF(D, Triple, Args) { - if (Triple.getArch() == llvm::Triple::ppc && - llvm::Triple(getDriver().DefaultHostTriple).getArch() == - llvm::Triple::ppc64) - Lib32 = true; - - if (Lib32) { - getFilePaths().push_back(CLANG_PREFIX "/usr/lib32"); - } else { - getFilePaths().push_back(CLANG_PREFIX "/usr/lib"); - } + // When targeting 32-bit platforms, look for '/usr/lib32/crt1.o' and fall + // back to '/usr/lib' if it doesn't exist. + if ((Triple.getArch() == llvm::Triple::x86 || + Triple.getArch() == llvm::Triple::ppc) && + llvm::sys::fs::exists(getDriver().SysRoot + CLANG_PREFIX "/usr/lib32/crt1.o")) + getFilePaths().push_back(getDriver().SysRoot + CLANG_PREFIX "/usr/lib32"); + else + getFilePaths().push_back(getDriver().SysRoot + CLANG_PREFIX "/usr/lib"); } Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA, @@ -1254,21 +1657,19 @@ Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA, /// NetBSD - NetBSD tool chain which can call as(1) and ld(1) directly. -NetBSD::NetBSD(const HostInfo &Host, const llvm::Triple& Triple, - const llvm::Triple& ToolTriple) - : Generic_ELF(Host, Triple), ToolTriple(ToolTriple) { - - // Determine if we are compiling 32-bit code on an x86_64 platform. - bool Lib32 = false; - if (ToolTriple.getArch() == llvm::Triple::x86_64 && - Triple.getArch() == llvm::Triple::x86) - Lib32 = true; +NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) + : Generic_ELF(D, Triple, Args) { if (getDriver().UseStdLib) { - if (Lib32) + // When targeting a 32-bit platform, try the special directory used on + // 64-bit hosts, and only fall back to the main library directory if that + // doesn't work. + // FIXME: It'd be nicer to test if this directory exists, but I'm not sure + // what all logic is needed to emulate the '=' prefix here. + if (Triple.getArch() == llvm::Triple::x86) getFilePaths().push_back("=/usr/lib/i386"); - else - getFilePaths().push_back("=/usr/lib"); + + getFilePaths().push_back("=/usr/lib"); } } @@ -1291,10 +1692,10 @@ Tool &NetBSD::SelectTool(const Compilation &C, const JobAction &JA, if (UseIntegratedAs) T = new tools::ClangAs(*this); else - T = new tools::netbsd::Assemble(*this, ToolTriple); + T = new tools::netbsd::Assemble(*this); break; case Action::LinkJobClass: - T = new tools::netbsd::Link(*this, ToolTriple); + T = new tools::netbsd::Link(*this); break; default: T = &Generic_GCC::SelectTool(C, JA, Inputs); @@ -1306,12 +1707,10 @@ Tool &NetBSD::SelectTool(const Compilation &C, const JobAction &JA, /// Minix - Minix tool chain which can call as(1) and ld(1) directly. -Minix::Minix(const HostInfo &Host, const llvm::Triple& Triple) - : Generic_GCC(Host, Triple) { +Minix::Minix(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) + : Generic_ELF(D, Triple, Args) { getFilePaths().push_back(getDriver().Dir + "/../lib"); getFilePaths().push_back("/usr/lib"); - getFilePaths().push_back("/usr/gnu/lib"); - getFilePaths().push_back("/usr/gnu/lib/gcc/i686-pc-minix/4.4.3"); } Tool &Minix::SelectTool(const Compilation &C, const JobAction &JA, @@ -1339,8 +1738,9 @@ Tool &Minix::SelectTool(const Compilation &C, const JobAction &JA, /// AuroraUX - AuroraUX tool chain which can call as(1) and ld(1) directly. -AuroraUX::AuroraUX(const HostInfo &Host, const llvm::Triple& Triple) - : Generic_GCC(Host, Triple) { +AuroraUX::AuroraUX(const Driver &D, const llvm::Triple& Triple, + const ArgList &Args) + : Generic_GCC(D, Triple, Args) { getProgramPaths().push_back(getDriver().getInstalledDir()); if (getDriver().getInstalledDir() != getDriver().Dir) @@ -1377,6 +1777,42 @@ Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA, return *T; } +/// Solaris - Solaris tool chain which can call as(1) and ld(1) directly. + +Solaris::Solaris(const Driver &D, const llvm::Triple& Triple, + const ArgList &Args) + : Generic_GCC(D, Triple, Args) { + + getProgramPaths().push_back(getDriver().getInstalledDir()); + if (getDriver().getInstalledDir() != getDriver().Dir) + getProgramPaths().push_back(getDriver().Dir); + + getFilePaths().push_back(getDriver().Dir + "/../lib"); + getFilePaths().push_back("/usr/lib"); +} + +Tool &Solaris::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { + Action::ActionClass Key; + if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) + Key = Action::AnalyzeJobClass; + else + Key = JA.getKind(); + + Tool *&T = Tools[Key]; + if (!T) { + switch (Key) { + case Action::AssembleJobClass: + T = new tools::solaris::Assemble(*this); break; + case Action::LinkJobClass: + T = new tools::solaris::Link(*this); break; + default: + T = &Generic_GCC::SelectTool(C, JA, Inputs); + } + } + + return *T; +} /// Linux toolchain (very bare-bones at the moment). @@ -1392,6 +1828,7 @@ enum LinuxDistro { Fedora13, Fedora14, Fedora15, + Fedora16, FedoraRawhide, OpenSuse11_3, OpenSuse11_4, @@ -1404,62 +1841,55 @@ enum LinuxDistro { UbuntuMaverick, UbuntuNatty, UbuntuOneiric, + UbuntuPrecise, UnknownDistro }; static bool IsRedhat(enum LinuxDistro Distro) { - return Distro == Fedora13 || Distro == Fedora14 || - Distro == Fedora15 || Distro == FedoraRawhide || - Distro == RHEL4 || Distro == RHEL5 || Distro == RHEL6; + return (Distro >= Fedora13 && Distro <= FedoraRawhide) || + (Distro >= RHEL4 && Distro <= RHEL6); } static bool IsOpenSuse(enum LinuxDistro Distro) { - return Distro == OpenSuse11_3 || Distro == OpenSuse11_4 || - Distro == OpenSuse12_1; + return Distro >= OpenSuse11_3 && Distro <= OpenSuse12_1; } static bool IsDebian(enum LinuxDistro Distro) { - return Distro == DebianLenny || Distro == DebianSqueeze || - Distro == DebianWheezy; + return Distro >= DebianLenny && Distro <= DebianWheezy; } static bool IsUbuntu(enum LinuxDistro Distro) { - return Distro == UbuntuHardy || Distro == UbuntuIntrepid || - Distro == UbuntuLucid || Distro == UbuntuMaverick || - Distro == UbuntuJaunty || Distro == UbuntuKarmic || - Distro == UbuntuNatty || Distro == UbuntuOneiric; + return Distro >= UbuntuHardy && Distro <= UbuntuPrecise; } static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) { - llvm::OwningPtr<llvm::MemoryBuffer> File; + OwningPtr<llvm::MemoryBuffer> File; if (!llvm::MemoryBuffer::getFile("/etc/lsb-release", File)) { StringRef Data = File.get()->getBuffer(); SmallVector<StringRef, 8> Lines; Data.split(Lines, "\n"); - for (unsigned int i = 0, s = Lines.size(); i < s; ++ i) { - if (Lines[i] == "DISTRIB_CODENAME=hardy") - return UbuntuHardy; - else if (Lines[i] == "DISTRIB_CODENAME=intrepid") - return UbuntuIntrepid; - else if (Lines[i] == "DISTRIB_CODENAME=jaunty") - return UbuntuJaunty; - else if (Lines[i] == "DISTRIB_CODENAME=karmic") - return UbuntuKarmic; - else if (Lines[i] == "DISTRIB_CODENAME=lucid") - return UbuntuLucid; - else if (Lines[i] == "DISTRIB_CODENAME=maverick") - return UbuntuMaverick; - else if (Lines[i] == "DISTRIB_CODENAME=natty") - return UbuntuNatty; - else if (Lines[i] == "DISTRIB_CODENAME=oneiric") - return UbuntuOneiric; - } - return UnknownDistro; + LinuxDistro Version = UnknownDistro; + for (unsigned i = 0, s = Lines.size(); i != s; ++i) + if (Version == UnknownDistro && Lines[i].startswith("DISTRIB_CODENAME=")) + Version = llvm::StringSwitch<LinuxDistro>(Lines[i].substr(17)) + .Case("hardy", UbuntuHardy) + .Case("intrepid", UbuntuIntrepid) + .Case("jaunty", UbuntuJaunty) + .Case("karmic", UbuntuKarmic) + .Case("lucid", UbuntuLucid) + .Case("maverick", UbuntuMaverick) + .Case("natty", UbuntuNatty) + .Case("oneiric", UbuntuOneiric) + .Case("precise", UbuntuPrecise) + .Default(UnknownDistro); + return Version; } if (!llvm::MemoryBuffer::getFile("/etc/redhat-release", File)) { StringRef Data = File.get()->getBuffer(); - if (Data.startswith("Fedora release 15")) + if (Data.startswith("Fedora release 16")) + return Fedora16; + else if (Data.startswith("Fedora release 15")) return Fedora15; else if (Data.startswith("Fedora release 14")) return Fedora14; @@ -1486,23 +1916,19 @@ static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) { StringRef Data = File.get()->getBuffer(); if (Data[0] == '5') return DebianLenny; - else if (Data.startswith("squeeze/sid")) + else if (Data.startswith("squeeze/sid") || Data[0] == '6') return DebianSqueeze; - else if (Data.startswith("wheezy/sid")) + else if (Data.startswith("wheezy/sid") || Data[0] == '7') return DebianWheezy; return UnknownDistro; } - if (!llvm::MemoryBuffer::getFile("/etc/SuSE-release", File)) { - StringRef Data = File.get()->getBuffer(); - if (Data.startswith("openSUSE 11.3")) - return OpenSuse11_3; - else if (Data.startswith("openSUSE 11.4")) - return OpenSuse11_4; - else if (Data.startswith("openSUSE 12.1")) - return OpenSuse12_1; - return UnknownDistro; - } + if (!llvm::MemoryBuffer::getFile("/etc/SuSE-release", File)) + return llvm::StringSwitch<LinuxDistro>(File.get()->getBuffer()) + .StartsWith("openSUSE 11.3", OpenSuse11_3) + .StartsWith("openSUSE 11.4", OpenSuse11_4) + .StartsWith("openSUSE 12.1", OpenSuse12_1) + .Default(UnknownDistro); bool Exists; if (!llvm::sys::fs::exists("/etc/exherbo-release", Exists) && Exists) @@ -1514,247 +1940,6 @@ static LinuxDistro DetectLinuxDistro(llvm::Triple::ArchType Arch) { return UnknownDistro; } -/// \brief Parse a GCCVersion object out of a string of text. -/// -/// This is the primary means of forming GCCVersion objects. -/*static*/ Linux::GCCVersion Linux::GCCVersion::Parse(StringRef VersionText) { - const GCCVersion BadVersion = { VersionText.str(), -1, -1, -1, "" }; - std::pair<StringRef, StringRef> First = VersionText.split('.'); - std::pair<StringRef, StringRef> Second = First.second.split('.'); - - GCCVersion GoodVersion = { VersionText.str(), -1, -1, -1, "" }; - if (First.first.getAsInteger(10, GoodVersion.Major) || - GoodVersion.Major < 0) - return BadVersion; - if (Second.first.getAsInteger(10, GoodVersion.Minor) || - GoodVersion.Minor < 0) - return BadVersion; - - // First look for a number prefix and parse that if present. Otherwise just - // stash the entire patch string in the suffix, and leave the number - // unspecified. This covers versions strings such as: - // 4.4 - // 4.4.0 - // 4.4.x - // 4.4.2-rc4 - // 4.4.x-patched - // And retains any patch number it finds. - StringRef PatchText = GoodVersion.PatchSuffix = Second.second.str(); - if (!PatchText.empty()) { - if (unsigned EndNumber = PatchText.find_first_not_of("0123456789")) { - // Try to parse the number and any suffix. - if (PatchText.slice(0, EndNumber).getAsInteger(10, GoodVersion.Patch) || - GoodVersion.Patch < 0) - return BadVersion; - GoodVersion.PatchSuffix = PatchText.substr(EndNumber).str(); - } - } - - return GoodVersion; -} - -/// \brief Less-than for GCCVersion, implementing a Strict Weak Ordering. -bool Linux::GCCVersion::operator<(const GCCVersion &RHS) const { - if (Major < RHS.Major) return true; if (Major > RHS.Major) return false; - if (Minor < RHS.Minor) return true; if (Minor > RHS.Minor) return false; - - // Note that we rank versions with *no* patch specified is better than ones - // hard-coding a patch version. Thus if the RHS has no patch, it always - // wins, and the LHS only wins if it has no patch and the RHS does have - // a patch. - if (RHS.Patch == -1) return true; if (Patch == -1) return false; - if (Patch < RHS.Patch) return true; if (Patch > RHS.Patch) return false; - - // Finally, between completely tied version numbers, the version with the - // suffix loses as we prefer full releases. - if (RHS.PatchSuffix.empty()) return true; - return false; -} - -/// \brief Construct a GCCInstallationDetector from the driver. -/// -/// This performs all of the autodetection and sets up the various paths. -/// Once constructed, a GCCInstallation is esentially immutable. -Linux::GCCInstallationDetector::GCCInstallationDetector(const Driver &D) - : IsValid(false), - GccTriple(D.DefaultHostTriple) { - // FIXME: Using CXX_INCLUDE_ROOT is here is a bit of a hack, but - // avoids adding yet another option to configure/cmake. - // It would probably be cleaner to break it in two variables - // CXX_GCC_ROOT with just /foo/bar - // CXX_GCC_VER with 4.5.2 - // Then we would have - // CXX_INCLUDE_ROOT = CXX_GCC_ROOT/include/c++/CXX_GCC_VER - // and this function would return - // CXX_GCC_ROOT/lib/gcc/CXX_INCLUDE_ARCH/CXX_GCC_VER - llvm::SmallString<128> CxxIncludeRoot(CXX_INCLUDE_ROOT); - if (CxxIncludeRoot != "") { - // This is of the form /foo/bar/include/c++/4.5.2/ - if (CxxIncludeRoot.back() == '/') - llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the / - StringRef Version = llvm::sys::path::filename(CxxIncludeRoot); - llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the version - llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the c++ - llvm::sys::path::remove_filename(CxxIncludeRoot); // remove the include - GccInstallPath = CxxIncludeRoot.str(); - GccInstallPath.append("/lib/gcc/"); - GccInstallPath.append(CXX_INCLUDE_ARCH); - GccInstallPath.append("/"); - GccInstallPath.append(Version); - GccParentLibPath = GccInstallPath + "/../../.."; - IsValid = true; - return; - } - - llvm::Triple::ArchType HostArch = llvm::Triple(GccTriple).getArch(); - // The library directories which may contain GCC installations. - SmallVector<StringRef, 4> CandidateLibDirs; - // The compatible GCC triples for this particular architecture. - SmallVector<StringRef, 10> CandidateTriples; - CollectLibDirsAndTriples(HostArch, CandidateLibDirs, CandidateTriples); - - // Always include the default host triple as the final fallback if no - // specific triple is detected. - CandidateTriples.push_back(D.DefaultHostTriple); - - // Compute the set of prefixes for our search. - SmallVector<std::string, 8> Prefixes(D.PrefixDirs.begin(), - D.PrefixDirs.end()); - Prefixes.push_back(D.SysRoot); - Prefixes.push_back(D.SysRoot + "/usr"); - Prefixes.push_back(D.InstalledDir + "/.."); - - // Loop over the various components which exist and select the best GCC - // installation available. GCC installs are ranked by version number. - Version = GCCVersion::Parse("0.0.0"); - for (unsigned i = 0, ie = Prefixes.size(); i < ie; ++i) { - if (!llvm::sys::fs::exists(Prefixes[i])) - continue; - for (unsigned j = 0, je = CandidateLibDirs.size(); j < je; ++j) { - const std::string LibDir = Prefixes[i] + CandidateLibDirs[j].str(); - if (!llvm::sys::fs::exists(LibDir)) - continue; - for (unsigned k = 0, ke = CandidateTriples.size(); k < ke; ++k) - ScanLibDirForGCCTriple(HostArch, LibDir, CandidateTriples[k]); - } - } -} - -/*static*/ void Linux::GCCInstallationDetector::CollectLibDirsAndTriples( - llvm::Triple::ArchType HostArch, SmallVectorImpl<StringRef> &LibDirs, - SmallVectorImpl<StringRef> &Triples) { - if (HostArch == llvm::Triple::arm || HostArch == llvm::Triple::thumb) { - static const char *const ARMLibDirs[] = { "/lib" }; - static const char *const ARMTriples[] = { "arm-linux-gnueabi" }; - LibDirs.append(ARMLibDirs, ARMLibDirs + llvm::array_lengthof(ARMLibDirs)); - Triples.append(ARMTriples, ARMTriples + llvm::array_lengthof(ARMTriples)); - } else if (HostArch == llvm::Triple::x86_64) { - static const char *const X86_64LibDirs[] = { "/lib64", "/lib" }; - static const char *const X86_64Triples[] = { - "x86_64-linux-gnu", - "x86_64-unknown-linux-gnu", - "x86_64-pc-linux-gnu", - "x86_64-redhat-linux6E", - "x86_64-redhat-linux", - "x86_64-suse-linux", - "x86_64-manbo-linux-gnu", - "x86_64-linux-gnu", - "x86_64-slackware-linux" - }; - LibDirs.append(X86_64LibDirs, - X86_64LibDirs + llvm::array_lengthof(X86_64LibDirs)); - Triples.append(X86_64Triples, - X86_64Triples + llvm::array_lengthof(X86_64Triples)); - } else if (HostArch == llvm::Triple::x86) { - static const char *const X86LibDirs[] = { "/lib32", "/lib" }; - static const char *const X86Triples[] = { - "i686-linux-gnu", - "i686-pc-linux-gnu", - "i486-linux-gnu", - "i386-linux-gnu", - "i686-redhat-linux", - "i586-redhat-linux", - "i386-redhat-linux", - "i586-suse-linux", - "i486-slackware-linux" - }; - LibDirs.append(X86LibDirs, X86LibDirs + llvm::array_lengthof(X86LibDirs)); - Triples.append(X86Triples, X86Triples + llvm::array_lengthof(X86Triples)); - } else if (HostArch == llvm::Triple::ppc) { - static const char *const PPCLibDirs[] = { "/lib32", "/lib" }; - static const char *const PPCTriples[] = { - "powerpc-linux-gnu", - "powerpc-unknown-linux-gnu" - }; - LibDirs.append(PPCLibDirs, PPCLibDirs + llvm::array_lengthof(PPCLibDirs)); - Triples.append(PPCTriples, PPCTriples + llvm::array_lengthof(PPCTriples)); - } else if (HostArch == llvm::Triple::ppc64) { - static const char *const PPC64LibDirs[] = { "/lib64", "/lib" }; - static const char *const PPC64Triples[] = { - "powerpc64-unknown-linux-gnu" - }; - LibDirs.append(PPC64LibDirs, - PPC64LibDirs + llvm::array_lengthof(PPC64LibDirs)); - Triples.append(PPC64Triples, - PPC64Triples + llvm::array_lengthof(PPC64Triples)); - } -} - -void Linux::GCCInstallationDetector::ScanLibDirForGCCTriple( - llvm::Triple::ArchType HostArch, const std::string &LibDir, - StringRef CandidateTriple) { - // There are various different suffixes involving the triple we - // check for. We also record what is necessary to walk from each back - // up to the lib directory. - const std::string Suffixes[] = { - "/gcc/" + CandidateTriple.str(), - "/" + CandidateTriple.str() + "/gcc/" + CandidateTriple.str(), - - // Ubuntu has a strange mis-matched pair of triples that this happens to - // match. - // FIXME: It may be worthwhile to generalize this and look for a second - // triple. - "/i386-linux-gnu/gcc/" + CandidateTriple.str() - }; - const std::string InstallSuffixes[] = { - "/../../..", - "/../../../..", - "/../../../.." - }; - // Only look at the final, weird Ubuntu suffix for i386-linux-gnu. - const unsigned NumSuffixes = (llvm::array_lengthof(Suffixes) - - (HostArch != llvm::Triple::x86)); - for (unsigned i = 0; i < NumSuffixes; ++i) { - StringRef Suffix = Suffixes[i]; - llvm::error_code EC; - for (llvm::sys::fs::directory_iterator LI(LibDir + Suffix, EC), LE; - !EC && LI != LE; LI = LI.increment(EC)) { - StringRef VersionText = llvm::sys::path::filename(LI->path()); - GCCVersion CandidateVersion = GCCVersion::Parse(VersionText); - static const GCCVersion MinVersion = { "4.1.1", 4, 1, 1, "" }; - if (CandidateVersion < MinVersion) - continue; - if (CandidateVersion <= Version) - continue; - if (!llvm::sys::fs::exists(LI->path() + "/crtbegin.o")) - continue; - - Version = CandidateVersion; - GccTriple = CandidateTriple.str(); - // FIXME: We hack together the directory name here instead of - // using LI to ensure stable path separators across Windows and - // Linux. - GccInstallPath = LibDir + Suffixes[i] + "/" + VersionText.str(); - GccParentLibPath = GccInstallPath + InstallSuffixes[i]; - IsValid = true; - } - } -} - -static void addPathIfExists(Twine Path, ToolChain::path_list &Paths) { - if (llvm::sys::fs::exists(Path)) Paths.push_back(Path.str()); -} - /// \brief Get our best guess at the multiarch triple for a target. /// /// Debian-based systems are starting to use a multiarch setup where they use @@ -1771,36 +1956,49 @@ static std::string getMultiarchTriple(const llvm::Triple TargetTriple, // We use the existence of '/lib/<triple>' as a directory to detect some // common linux triples that don't quite match the Clang triple for both - // 32-bit and 64-bit targets. This works around annoying discrepancies on - // Debian-based systems. + // 32-bit and 64-bit targets. Multiarch fixes its install triples to these + // regardless of what the actual target triple is. case llvm::Triple::x86: - if (llvm::sys::fs::exists(SysRoot + "/lib/i686-linux-gnu")) - return "i686-linux-gnu"; if (llvm::sys::fs::exists(SysRoot + "/lib/i386-linux-gnu")) return "i386-linux-gnu"; return TargetTriple.str(); case llvm::Triple::x86_64: if (llvm::sys::fs::exists(SysRoot + "/lib/x86_64-linux-gnu")) return "x86_64-linux-gnu"; - if (llvm::sys::fs::exists(SysRoot + "/lib/x86_64-pc-linux-gnu")) - return "x86_64-pc-linux-gnu"; - if (llvm::sys::fs::exists(SysRoot + "/lib/x86_64-unknown-linux-gnu")) - return "x86_64-unknown-linux-gnu"; + return TargetTriple.str(); + case llvm::Triple::mips: + if (llvm::sys::fs::exists(SysRoot + "/lib/mips-linux-gnu")) + return "mips-linux-gnu"; + return TargetTriple.str(); + case llvm::Triple::mipsel: + if (llvm::sys::fs::exists(SysRoot + "/lib/mipsel-linux-gnu")) + return "mipsel-linux-gnu"; + return TargetTriple.str(); + case llvm::Triple::ppc: + if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc-linux-gnu")) + return "powerpc-linux-gnu"; + return TargetTriple.str(); + case llvm::Triple::ppc64: + if (llvm::sys::fs::exists(SysRoot + "/lib/powerpc64-linux-gnu")) + return "powerpc64-linux-gnu"; return TargetTriple.str(); } } -Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) - : Generic_ELF(Host, Triple), GCCInstallation(getDriver()) { - llvm::Triple::ArchType Arch = - llvm::Triple(getDriver().DefaultHostTriple).getArch(); +static void addPathIfExists(Twine Path, ToolChain::path_list &Paths) { + if (llvm::sys::fs::exists(Path)) Paths.push_back(Path.str()); +} + +Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) + : Generic_ELF(D, Triple, Args) { + llvm::Triple::ArchType Arch = Triple.getArch(); const std::string &SysRoot = getDriver().SysRoot; // OpenSuse stores the linker with the compiler, add that to the search // path. ToolChain::path_list &PPaths = getProgramPaths(); PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" + - GCCInstallation.getTriple() + "/bin").str()); + GCCInstallation.getTriple().str() + "/bin").str()); Linker = GetProgramPath("ld"); @@ -1814,13 +2012,27 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) if (Arch == llvm::Triple::arm || Arch == llvm::Triple::thumb) ExtraOpts.push_back("-X"); - if (IsRedhat(Distro) || IsOpenSuse(Distro) || Distro == UbuntuMaverick || - Distro == UbuntuNatty || Distro == UbuntuOneiric) - ExtraOpts.push_back("--hash-style=gnu"); + const bool IsMips = Arch == llvm::Triple::mips || + Arch == llvm::Triple::mipsel || + Arch == llvm::Triple::mips64 || + Arch == llvm::Triple::mips64el; - if (IsDebian(Distro) || IsOpenSuse(Distro) || Distro == UbuntuLucid || - Distro == UbuntuJaunty || Distro == UbuntuKarmic) - ExtraOpts.push_back("--hash-style=both"); + const bool IsAndroid = Triple.getEnvironment() == llvm::Triple::ANDROIDEABI; + + // Do not use 'gnu' hash style for Mips targets because .gnu.hash + // and the MIPS ABI require .dynsym to be sorted in different ways. + // .gnu.hash needs symbols to be grouped by hash code whereas the MIPS + // ABI requires a mapping between the GOT and the symbol table. + // Android loader does not support .gnu.hash. + if (!IsMips && !IsAndroid) { + if (IsRedhat(Distro) || IsOpenSuse(Distro) || + (IsUbuntu(Distro) && Distro >= UbuntuMaverick)) + ExtraOpts.push_back("--hash-style=gnu"); + + if (IsDebian(Distro) || IsOpenSuse(Distro) || Distro == UbuntuLucid || + Distro == UbuntuJaunty || Distro == UbuntuKarmic) + ExtraOpts.push_back("--hash-style=both"); + } if (IsRedhat(Distro)) ExtraOpts.push_back("--no-add-needed"); @@ -1828,9 +2040,7 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) if (Distro == DebianSqueeze || Distro == DebianWheezy || IsOpenSuse(Distro) || (IsRedhat(Distro) && Distro != RHEL4 && Distro != RHEL5) || - Distro == UbuntuLucid || - Distro == UbuntuMaverick || Distro == UbuntuKarmic || - Distro == UbuntuNatty || Distro == UbuntuOneiric) + (IsUbuntu(Distro) && Distro >= UbuntuKarmic)) ExtraOpts.push_back("--build-id"); if (IsOpenSuse(Distro)) @@ -1842,24 +2052,31 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) // possible permutations of these directories, and seeing which ones it added // to the link paths. path_list &Paths = getFilePaths(); - const bool Is32Bits = (getArch() == llvm::Triple::x86 || - getArch() == llvm::Triple::ppc); - const std::string Suffix32 = Arch == llvm::Triple::x86_64 ? "/32" : ""; - const std::string Suffix64 = Arch == llvm::Triple::x86_64 ? "" : "/64"; - const std::string Suffix = Is32Bits ? Suffix32 : Suffix64; - const std::string Multilib = Is32Bits ? "lib32" : "lib64"; + const std::string Multilib = Triple.isArch32Bit() ? "lib32" : "lib64"; const std::string MultiarchTriple = getMultiarchTriple(Triple, SysRoot); // Add the multilib suffixed paths where they are available. if (GCCInstallation.isValid()) { + const llvm::Triple &GCCTriple = GCCInstallation.getTriple(); const std::string &LibPath = GCCInstallation.getParentLibPath(); - const std::string &GccTriple = GCCInstallation.getTriple(); - addPathIfExists(GCCInstallation.getInstallPath() + Suffix, Paths); - addPathIfExists(LibPath + "/../" + GccTriple + "/lib/../" + Multilib, + addPathIfExists((GCCInstallation.getInstallPath() + + GCCInstallation.getMultiarchSuffix()), Paths); - addPathIfExists(LibPath + "/" + MultiarchTriple, Paths); - addPathIfExists(LibPath + "/../" + Multilib, Paths); + + // If the GCC installation we found is inside of the sysroot, we want to + // prefer libraries installed in the parent prefix of the GCC installation. + // It is important to *not* use these paths when the GCC installation is + // outside of the system root as that can pick up un-intented libraries. + // This usually happens when there is an external cross compiler on the + // host system, and a more minimal sysroot available that is the target of + // the cross. + if (StringRef(LibPath).startswith(SysRoot)) { + addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib/../" + Multilib, + Paths); + addPathIfExists(LibPath + "/" + MultiarchTriple, Paths); + addPathIfExists(LibPath + "/../" + Multilib, Paths); + } } addPathIfExists(SysRoot + "/lib/" + MultiarchTriple, Paths); addPathIfExists(SysRoot + "/lib/../" + Multilib, Paths); @@ -1869,22 +2086,22 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple) // Try walking via the GCC triple path in case of multiarch GCC // installations with strange symlinks. if (GCCInstallation.isValid()) - addPathIfExists(SysRoot + "/usr/lib/" + GCCInstallation.getTriple() + + addPathIfExists(SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() + "/../../" + Multilib, Paths); // Add the non-multilib suffixed paths (if potentially different). if (GCCInstallation.isValid()) { const std::string &LibPath = GCCInstallation.getParentLibPath(); - const std::string &GccTriple = GCCInstallation.getTriple(); - if (!Suffix.empty()) + const llvm::Triple &GCCTriple = GCCInstallation.getTriple(); + if (!GCCInstallation.getMultiarchSuffix().empty()) addPathIfExists(GCCInstallation.getInstallPath(), Paths); - addPathIfExists(LibPath + "/../" + GccTriple + "/lib", Paths); - addPathIfExists(LibPath + "/" + MultiarchTriple, Paths); - addPathIfExists(LibPath, Paths); + + if (StringRef(LibPath).startswith(SysRoot)) { + addPathIfExists(LibPath + "/../" + GCCTriple.str() + "/lib", Paths); + addPathIfExists(LibPath, Paths); + } } - addPathIfExists(SysRoot + "/lib/" + MultiarchTriple, Paths); addPathIfExists(SysRoot + "/lib", Paths); - addPathIfExists(SysRoot + "/usr/lib/" + MultiarchTriple, Paths); addPathIfExists(SysRoot + "/usr/lib", Paths); } @@ -1981,6 +2198,18 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, const StringRef ARMMultiarchIncludeDirs[] = { "/usr/include/arm-linux-gnueabi" }; + const StringRef MIPSMultiarchIncludeDirs[] = { + "/usr/include/mips-linux-gnu" + }; + const StringRef MIPSELMultiarchIncludeDirs[] = { + "/usr/include/mipsel-linux-gnu" + }; + const StringRef PPCMultiarchIncludeDirs[] = { + "/usr/include/powerpc-linux-gnu" + }; + const StringRef PPC64MultiarchIncludeDirs[] = { + "/usr/include/powerpc64-linux-gnu" + }; ArrayRef<StringRef> MultiarchIncludeDirs; if (getTriple().getArch() == llvm::Triple::x86_64) { MultiarchIncludeDirs = X86_64MultiarchIncludeDirs; @@ -1988,11 +2217,19 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, MultiarchIncludeDirs = X86MultiarchIncludeDirs; } else if (getTriple().getArch() == llvm::Triple::arm) { MultiarchIncludeDirs = ARMMultiarchIncludeDirs; + } else if (getTriple().getArch() == llvm::Triple::mips) { + MultiarchIncludeDirs = MIPSMultiarchIncludeDirs; + } else if (getTriple().getArch() == llvm::Triple::mipsel) { + MultiarchIncludeDirs = MIPSELMultiarchIncludeDirs; + } else if (getTriple().getArch() == llvm::Triple::ppc) { + MultiarchIncludeDirs = PPCMultiarchIncludeDirs; + } else if (getTriple().getArch() == llvm::Triple::ppc64) { + MultiarchIncludeDirs = PPC64MultiarchIncludeDirs; } for (ArrayRef<StringRef>::iterator I = MultiarchIncludeDirs.begin(), E = MultiarchIncludeDirs.end(); I != E; ++I) { - if (llvm::sys::fs::exists(*I)) { + if (llvm::sys::fs::exists(D.SysRoot + *I)) { addExternCSystemInclude(DriverArgs, CC1Args, D.SysRoot + *I); break; } @@ -2001,12 +2238,18 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs, if (getTriple().getOS() == llvm::Triple::RTEMS) return; + // Add an include of '/include' directly. This isn't provided by default by + // system GCCs, but is often used with cross-compiling GCCs, and harmless to + // add even when Clang is acting as-if it were a system compiler. + addExternCSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/include"); + addExternCSystemInclude(DriverArgs, CC1Args, D.SysRoot + "/usr/include"); } -static bool addLibStdCXXIncludePaths(Twine Base, Twine TargetArchDir, - const ArgList &DriverArgs, - ArgStringList &CC1Args) { +/// \brief Helper to add the thre variant paths for a libstdc++ installation. +/*static*/ bool Linux::addLibStdCXXIncludePaths(Twine Base, Twine TargetArchDir, + const ArgList &DriverArgs, + ArgStringList &CC1Args) { if (!llvm::sys::fs::exists(Base)) return false; addSystemInclude(DriverArgs, CC1Args, Base); @@ -2029,37 +2272,10 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, return; } - const llvm::Triple &TargetTriple = getTriple(); - const llvm::Triple::ArchType TargetArch = TargetTriple.getArch(); - bool IsTarget64Bit = (TargetArch == llvm::Triple::x86_64 || - TargetArch == llvm::Triple::ppc64); - - StringRef CxxIncludeRoot(CXX_INCLUDE_ROOT); - if (!CxxIncludeRoot.empty()) { - StringRef CxxIncludeArch(CXX_INCLUDE_ARCH); - if (CxxIncludeArch.empty()) - CxxIncludeArch = TargetTriple.str(); - - addLibStdCXXIncludePaths( - CxxIncludeRoot, - CxxIncludeArch + (IsTarget64Bit ? CXX_INCLUDE_64BIT_DIR - : CXX_INCLUDE_32BIT_DIR), - DriverArgs, CC1Args); + // We need a detected GCC installation on Linux to provide libstdc++'s + // headers. We handled the libc++ case above. + if (!GCCInstallation.isValid()) return; - } - - // Check if the target architecture specific dirs need a suffix. Note that we - // only support the suffix-based bi-arch-like header scheme for host/target - // mismatches of just bit width. - llvm::Triple::ArchType HostArch = - llvm::Triple(getDriver().DefaultHostTriple).getArch(); - StringRef Suffix; - if ((HostArch == llvm::Triple::x86 && TargetArch == llvm::Triple::x86_64) || - (HostArch == llvm::Triple::ppc && TargetArch == llvm::Triple::ppc64)) - Suffix = "/64"; - if ((HostArch == llvm::Triple::x86_64 && TargetArch == llvm::Triple::x86) || - (HostArch == llvm::Triple::ppc64 && TargetArch == llvm::Triple::ppc)) - Suffix = "/32"; // By default, look for the C++ headers in an include directory adjacent to // the lib directory of the GCC installation. Note that this is expect to be @@ -2068,20 +2284,22 @@ void Linux::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, StringRef InstallDir = GCCInstallation.getInstallPath(); StringRef Version = GCCInstallation.getVersion(); if (!addLibStdCXXIncludePaths(LibDir + "/../include/c++/" + Version, - GCCInstallation.getTriple() + Suffix, + (GCCInstallation.getTriple().str() + + GCCInstallation.getMultiarchSuffix()), DriverArgs, CC1Args)) { // Gentoo is weird and places its headers inside the GCC install, so if the // first attempt to find the headers fails, try this pattern. addLibStdCXXIncludePaths(InstallDir + "/include/g++-v4", - GCCInstallation.getTriple() + Suffix, + (GCCInstallation.getTriple().str() + + GCCInstallation.getMultiarchSuffix()), DriverArgs, CC1Args); } } /// DragonFly - DragonFly tool chain which can call as(1) and ld(1) directly. -DragonFly::DragonFly(const HostInfo &Host, const llvm::Triple& Triple) - : Generic_ELF(Host, Triple) { +DragonFly::DragonFly(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) + : Generic_ELF(D, Triple, Args) { // Path mangling to find libexec getProgramPaths().push_back(getDriver().getInstalledDir()); @@ -2115,322 +2333,3 @@ Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA, return *T; } - -Windows::Windows(const HostInfo &Host, const llvm::Triple& Triple) - : ToolChain(Host, Triple) { -} - -Tool &Windows::SelectTool(const Compilation &C, const JobAction &JA, - const ActionList &Inputs) const { - Action::ActionClass Key; - if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) - Key = Action::AnalyzeJobClass; - else - Key = JA.getKind(); - - bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as, - options::OPT_no_integrated_as, - IsIntegratedAssemblerDefault()); - - Tool *&T = Tools[Key]; - if (!T) { - switch (Key) { - case Action::InputClass: - case Action::BindArchClass: - case Action::LipoJobClass: - case Action::DsymutilJobClass: - case Action::VerifyJobClass: - llvm_unreachable("Invalid tool kind."); - case Action::PreprocessJobClass: - case Action::PrecompileJobClass: - case Action::AnalyzeJobClass: - case Action::CompileJobClass: - T = new tools::Clang(*this); break; - case Action::AssembleJobClass: - if (!UseIntegratedAs && getTriple().getEnvironment() == llvm::Triple::MachO) - T = new tools::darwin::Assemble(*this); - else - T = new tools::ClangAs(*this); - break; - case Action::LinkJobClass: - T = new tools::visualstudio::Link(*this); break; - } - } - - return *T; -} - -bool Windows::IsIntegratedAssemblerDefault() const { - return true; -} - -bool Windows::IsUnwindTablesDefault() const { - // FIXME: Gross; we should probably have some separate target - // definition, possibly even reusing the one in clang. - return getArchName() == "x86_64"; -} - -const char *Windows::GetDefaultRelocationModel() const { - return "static"; -} - -const char *Windows::GetForcedPicModel() const { - if (getArchName() == "x86_64") - return "pic"; - return 0; -} - -// FIXME: This probably should goto to some platform utils place. -#ifdef _MSC_VER - -/// \brief Read registry string. -/// This also supports a means to look for high-versioned keys by use -/// of a $VERSION placeholder in the key path. -/// $VERSION in the key path is a placeholder for the version number, -/// causing the highest value path to be searched for and used. -/// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION". -/// There can be additional characters in the component. Only the numberic -/// characters are compared. -static bool getSystemRegistryString(const char *keyPath, const char *valueName, - char *value, size_t maxLength) { - HKEY hRootKey = NULL; - HKEY hKey = NULL; - const char* subKey = NULL; - DWORD valueType; - DWORD valueSize = maxLength - 1; - long lResult; - bool returnValue = false; - - if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) { - hRootKey = HKEY_CLASSES_ROOT; - subKey = keyPath + 18; - } else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) { - hRootKey = HKEY_USERS; - subKey = keyPath + 11; - } else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) { - hRootKey = HKEY_LOCAL_MACHINE; - subKey = keyPath + 19; - } else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) { - hRootKey = HKEY_CURRENT_USER; - subKey = keyPath + 18; - } else { - return false; - } - - const char *placeHolder = strstr(subKey, "$VERSION"); - char bestName[256]; - bestName[0] = '\0'; - // If we have a $VERSION placeholder, do the highest-version search. - if (placeHolder) { - const char *keyEnd = placeHolder - 1; - const char *nextKey = placeHolder; - // Find end of previous key. - while ((keyEnd > subKey) && (*keyEnd != '\\')) - keyEnd--; - // Find end of key containing $VERSION. - while (*nextKey && (*nextKey != '\\')) - nextKey++; - size_t partialKeyLength = keyEnd - subKey; - char partialKey[256]; - if (partialKeyLength > sizeof(partialKey)) - partialKeyLength = sizeof(partialKey); - strncpy(partialKey, subKey, partialKeyLength); - partialKey[partialKeyLength] = '\0'; - HKEY hTopKey = NULL; - lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey); - if (lResult == ERROR_SUCCESS) { - char keyName[256]; - int bestIndex = -1; - double bestValue = 0.0; - DWORD index, size = sizeof(keyName) - 1; - for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL, - NULL, NULL, NULL) == ERROR_SUCCESS; index++) { - const char *sp = keyName; - while (*sp && !isdigit(*sp)) - sp++; - if (!*sp) - continue; - const char *ep = sp + 1; - while (*ep && (isdigit(*ep) || (*ep == '.'))) - ep++; - char numBuf[32]; - strncpy(numBuf, sp, sizeof(numBuf) - 1); - numBuf[sizeof(numBuf) - 1] = '\0'; - double value = strtod(numBuf, NULL); - if (value > bestValue) { - bestIndex = (int)index; - bestValue = value; - strcpy(bestName, keyName); - } - size = sizeof(keyName) - 1; - } - // If we found the highest versioned key, open the key and get the value. - if (bestIndex != -1) { - // Append rest of key. - strncat(bestName, nextKey, sizeof(bestName) - 1); - bestName[sizeof(bestName) - 1] = '\0'; - // Open the chosen key path remainder. - lResult = RegOpenKeyEx(hTopKey, bestName, 0, KEY_READ, &hKey); - if (lResult == ERROR_SUCCESS) { - lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType, - (LPBYTE)value, &valueSize); - if (lResult == ERROR_SUCCESS) - returnValue = true; - RegCloseKey(hKey); - } - } - RegCloseKey(hTopKey); - } - } else { - lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey); - if (lResult == ERROR_SUCCESS) { - lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType, - (LPBYTE)value, &valueSize); - if (lResult == ERROR_SUCCESS) - returnValue = true; - RegCloseKey(hKey); - } - } - return returnValue; -} - -/// \brief Get Windows SDK installation directory. -static bool getWindowsSDKDir(std::string &path) { - char windowsSDKInstallDir[256]; - // Try the Windows registry. - bool hasSDKDir = getSystemRegistryString( - "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", - "InstallationFolder", - windowsSDKInstallDir, - sizeof(windowsSDKInstallDir) - 1); - // If we have both vc80 and vc90, pick version we were compiled with. - if (hasSDKDir && windowsSDKInstallDir[0]) { - path = windowsSDKInstallDir; - return true; - } - return false; -} - - // Get Visual Studio installation directory. -static bool getVisualStudioDir(std::string &path) { - // First check the environment variables that vsvars32.bat sets. - const char* vcinstalldir = getenv("VCINSTALLDIR"); - if (vcinstalldir) { - char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC")); - if (p) - *p = '\0'; - path = vcinstalldir; - return true; - } - - char vsIDEInstallDir[256]; - char vsExpressIDEInstallDir[256]; - // Then try the windows registry. - bool hasVCDir = getSystemRegistryString( - "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION", - "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1); - bool hasVCExpressDir = getSystemRegistryString( - "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION", - "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1); - // If we have both vc80 and vc90, pick version we were compiled with. - if (hasVCDir && vsIDEInstallDir[0]) { - char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE"); - if (p) - *p = '\0'; - path = vsIDEInstallDir; - return true; - } - - if (hasVCExpressDir && vsExpressIDEInstallDir[0]) { - char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE"); - if (p) - *p = '\0'; - path = vsExpressIDEInstallDir; - return true; - } - - // Try the environment. - const char *vs100comntools = getenv("VS100COMNTOOLS"); - const char *vs90comntools = getenv("VS90COMNTOOLS"); - const char *vs80comntools = getenv("VS80COMNTOOLS"); - const char *vscomntools = NULL; - - // Try to find the version that we were compiled with - if(false) {} - #if (_MSC_VER >= 1600) // VC100 - else if(vs100comntools) { - vscomntools = vs100comntools; - } - #elif (_MSC_VER == 1500) // VC80 - else if(vs90comntools) { - vscomntools = vs90comntools; - } - #elif (_MSC_VER == 1400) // VC80 - else if(vs80comntools) { - vscomntools = vs80comntools; - } - #endif - // Otherwise find any version we can - else if (vs100comntools) - vscomntools = vs100comntools; - else if (vs90comntools) - vscomntools = vs90comntools; - else if (vs80comntools) - vscomntools = vs80comntools; - - if (vscomntools && *vscomntools) { - const char *p = strstr(vscomntools, "\\Common7\\Tools"); - path = p ? std::string(vscomntools, p) : vscomntools; - return true; - } - return false; -} - -#endif // _MSC_VER - -void Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs, - ArgStringList &CC1Args) const { - if (DriverArgs.hasArg(options::OPT_nostdinc)) - return; - - if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { - llvm::sys::Path P(getDriver().ResourceDir); - P.appendComponent("include"); - addSystemInclude(DriverArgs, CC1Args, P.str()); - } - - if (DriverArgs.hasArg(options::OPT_nostdlibinc)) - return; - - std::string VSDir; - std::string WindowsSDKDir; - -#ifdef _MSC_VER - // When built with access to the proper Windows APIs, try to actually find - // the correct include paths first. - if (getVisualStudioDir(VSDir)) { - addSystemInclude(DriverArgs, CC1Args, VSDir + "\\VC\\include"); - if (getWindowsSDKDir(WindowsSDKDir)) - addSystemInclude(DriverArgs, CC1Args, WindowsSDKDir + "\\include"); - else - addSystemInclude(DriverArgs, CC1Args, - VSDir + "\\VC\\PlatformSDK\\Include"); - return; - } -#endif // _MSC_VER - - // As a fallback, select default install paths. - const StringRef Paths[] = { - "C:/Program Files/Microsoft Visual Studio 10.0/VC/include", - "C:/Program Files/Microsoft Visual Studio 9.0/VC/include", - "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include", - "C:/Program Files/Microsoft Visual Studio 8/VC/include", - "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include" - }; - addSystemIncludes(DriverArgs, CC1Args, Paths); -} - -void Windows::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, - ArgStringList &CC1Args) const { - // FIXME: There should probably be logic here to find libc++ on Windows. -} diff --git a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h index 0e4d67c..eaa6be1 100644 --- a/contrib/llvm/tools/clang/lib/Driver/ToolChains.h +++ b/contrib/llvm/tools/clang/lib/Driver/ToolChains.h @@ -13,6 +13,7 @@ #include "clang/Driver/Action.h" #include "clang/Driver/ToolChain.h" +#include "clang/Basic/VersionTuple.h" #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Compiler.h" @@ -27,10 +28,100 @@ namespace toolchains { /// command line options. class LLVM_LIBRARY_VISIBILITY Generic_GCC : public ToolChain { protected: + /// \brief Struct to store and manipulate GCC versions. + /// + /// We rely on assumptions about the form and structure of GCC version + /// numbers: they consist of at most three '.'-separated components, and each + /// component is a non-negative integer except for the last component. For + /// the last component we are very flexible in order to tolerate release + /// candidates or 'x' wildcards. + /// + /// Note that the ordering established among GCCVersions is based on the + /// preferred version string to use. For example we prefer versions without + /// a hard-coded patch number to those with a hard coded patch number. + /// + /// Currently this doesn't provide any logic for textual suffixes to patches + /// in the way that (for example) Debian's version format does. If that ever + /// becomes necessary, it can be added. + struct GCCVersion { + /// \brief The unparsed text of the version. + std::string Text; + + /// \brief The parsed major, minor, and patch numbers. + int Major, Minor, Patch; + + /// \brief Any textual suffix on the patch number. + std::string PatchSuffix; + + static GCCVersion Parse(StringRef VersionText); + bool operator<(const GCCVersion &RHS) const; + bool operator>(const GCCVersion &RHS) const { return RHS < *this; } + bool operator<=(const GCCVersion &RHS) const { return !(*this > RHS); } + bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); } + }; + + + /// \brief This is a class to find a viable GCC installation for Clang to + /// use. + /// + /// This class tries to find a GCC installation on the system, and report + /// information about it. It starts from the host information provided to the + /// Driver, and has logic for fuzzing that where appropriate. + class GCCInstallationDetector { + + bool IsValid; + llvm::Triple GCCTriple; + + // FIXME: These might be better as path objects. + std::string GCCInstallPath; + std::string GCCMultiarchSuffix; + std::string GCCParentLibPath; + + GCCVersion Version; + + public: + GCCInstallationDetector(const Driver &D, const llvm::Triple &TargetTriple, + const ArgList &Args); + + /// \brief Check whether we detected a valid GCC install. + bool isValid() const { return IsValid; } + + /// \brief Get the GCC triple for the detected install. + const llvm::Triple &getTriple() const { return GCCTriple; } + + /// \brief Get the detected GCC installation path. + StringRef getInstallPath() const { return GCCInstallPath; } + + /// \brief Get the detected GCC installation path suffix for multiarch GCCs. + StringRef getMultiarchSuffix() const { return GCCMultiarchSuffix; } + + /// \brief Get the detected GCC parent lib path. + StringRef getParentLibPath() const { return GCCParentLibPath; } + + /// \brief Get the detected GCC version string. + StringRef getVersion() const { return Version.Text; } + + private: + static void CollectLibDirsAndTriples( + const llvm::Triple &TargetTriple, + const llvm::Triple &MultiarchTriple, + SmallVectorImpl<StringRef> &LibDirs, + SmallVectorImpl<StringRef> &TripleAliases, + SmallVectorImpl<StringRef> &MultiarchLibDirs, + SmallVectorImpl<StringRef> &MultiarchTripleAliases); + + void ScanLibDirForGCCTriple(llvm::Triple::ArchType TargetArch, + const std::string &LibDir, + StringRef CandidateTriple, + bool NeedsMultiarchSuffix = false); + }; + + GCCInstallationDetector GCCInstallation; + mutable llvm::DenseMap<unsigned, Tool*> Tools; public: - Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple); + Generic_GCC(const Driver &D, const llvm::Triple& Triple, const ArgList &Args); ~Generic_GCC(); virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, @@ -39,9 +130,37 @@ public: virtual bool IsUnwindTablesDefault() const; virtual const char *GetDefaultRelocationModel() const; virtual const char *GetForcedPicModel() const; + +protected: + /// \name ToolChain Implementation Helper Functions + /// @{ + + /// \brief Check whether the target triple's architecture is 64-bits. + bool isTarget64Bit() const { return getTriple().isArch64Bit(); } + + /// \brief Check whether the target triple's architecture is 32-bits. + bool isTarget32Bit() const { return getTriple().isArch32Bit(); } + + /// @} +}; + +class LLVM_LIBRARY_VISIBILITY Hexagon_TC : public ToolChain { +protected: + mutable llvm::DenseMap<unsigned, Tool*> Tools; + +public: + Hexagon_TC(const Driver &D, const llvm::Triple& Triple); + ~Hexagon_TC(); + + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; + + virtual bool IsUnwindTablesDefault() const; + virtual const char *GetDefaultRelocationModel() const; + virtual const char *GetForcedPicModel() const; }; -/// Darwin - The base Darwin tool chain. + /// Darwin - The base Darwin tool chain. class LLVM_LIBRARY_VISIBILITY Darwin : public ToolChain { public: /// The host version. @@ -80,19 +199,20 @@ private: mutable bool TargetIsIPhoneOSSimulator; /// The OS version we are targeting. - mutable unsigned TargetVersion[3]; + mutable VersionTuple TargetVersion; /// The default macosx-version-min of this tool chain; empty until /// initialized. std::string MacosxVersionMin; bool hasARCRuntime() const; + bool hasSubscriptingRuntime() const; private: void AddDeploymentTarget(DerivedArgList &Args) const; public: - Darwin(const HostInfo &Host, const llvm::Triple& Triple); + Darwin(const Driver &D, const llvm::Triple& Triple); ~Darwin(); std::string ComputeEffectiveClangTriple(const ArgList &Args, @@ -111,17 +231,14 @@ public: // change. This will go away when we move away from argument translation. if (TargetInitialized && TargetIsIPhoneOS == IsIPhoneOS && TargetIsIPhoneOSSimulator == IsIOSSim && - TargetVersion[0] == Major && TargetVersion[1] == Minor && - TargetVersion[2] == Micro) + TargetVersion == VersionTuple(Major, Minor, Micro)) return; assert(!TargetInitialized && "Target already initialized!"); TargetInitialized = true; TargetIsIPhoneOS = IsIPhoneOS; TargetIsIPhoneOSSimulator = IsIOSSim; - TargetVersion[0] = Major; - TargetVersion[1] = Minor; - TargetVersion[2] = Micro; + TargetVersion = VersionTuple(Major, Minor, Micro); } bool isTargetIPhoneOS() const { @@ -134,13 +251,17 @@ public: return TargetIsIPhoneOSSimulator; } + bool isTargetMacOS() const { + return !isTargetIOSSimulator() && + !isTargetIPhoneOS() && + ARCRuntimeForSimulator == ARCSimulator_None; + } + bool isTargetInitialized() const { return TargetInitialized; } - void getTargetVersion(unsigned (&Res)[3]) const { + VersionTuple getTargetVersion() const { assert(TargetInitialized && "Target not initialized!"); - Res[0] = TargetVersion[0]; - Res[1] = TargetVersion[1]; - Res[2] = TargetVersion[2]; + return TargetVersion; } /// getDarwinArchName - Get the "Darwin" arch name for a particular compiler @@ -148,24 +269,14 @@ public: /// distinct architectures. StringRef getDarwinArchName(const ArgList &Args) const; - static bool isVersionLT(unsigned (&A)[3], unsigned (&B)[3]) { - for (unsigned i=0; i < 3; ++i) { - if (A[i] > B[i]) return false; - if (A[i] < B[i]) return true; - } - return false; - } - bool isIPhoneOSVersionLT(unsigned V0, unsigned V1=0, unsigned V2=0) const { assert(isTargetIPhoneOS() && "Unexpected call for OS X target!"); - unsigned B[3] = { V0, V1, V2 }; - return isVersionLT(TargetVersion, B); + return TargetVersion < VersionTuple(V0, V1, V2); } bool isMacosxVersionLT(unsigned V0, unsigned V1=0, unsigned V2=0) const { assert(!isTargetIPhoneOS() && "Unexpected call for iPhoneOS target!"); - unsigned B[3] = { V0, V1, V2 }; - return isVersionLT(TargetVersion, B); + return TargetVersion < VersionTuple(V0, V1, V2); } /// AddLinkSearchPathArgs - Add the linker search paths to \arg CmdArgs. @@ -211,9 +322,8 @@ public: #ifdef DISABLE_DEFAULT_INTEGRATED_ASSEMBLER return false; #else - // Default integrated assembler to on for x86. - return (getTriple().getArch() == llvm::Triple::x86 || - getTriple().getArch() == llvm::Triple::x86_64); + // Default integrated assembler to on for Darwin. + return true; #endif } virtual bool IsStrictAliasingDefault() const { @@ -225,7 +335,7 @@ public: } virtual bool IsObjCDefaultSynthPropertiesDefault() const { - return false; + return true; } virtual bool IsObjCNonFragileABIDefault() const { @@ -248,10 +358,13 @@ public: virtual unsigned GetDefaultStackProtectorLevel(bool KernelOrKext) const { // Stack protectors default to on for user code on 10.5, // and for everything in 10.6 and beyond - return !isTargetIPhoneOS() && + return isTargetIPhoneOS() || (!isMacosxVersionLT(10, 6) || (!isMacosxVersionLT(10, 5) && !KernelOrKext)); } + virtual RuntimeLibType GetDefaultRuntimeLibType() const { + return ToolChain::RLT_CompilerRT; + } virtual const char *GetDefaultRelocationModel() const; virtual const char *GetForcedPicModel() const; @@ -259,6 +372,8 @@ public: virtual bool SupportsObjCGC() const; + virtual bool SupportsObjCARC() const; + virtual bool UseDwarfDebugFlags() const; virtual bool UseSjLjExceptions() const; @@ -272,7 +387,7 @@ private: void AddGCCLibexecPath(unsigned darwinVersion); public: - DarwinClang(const HostInfo &Host, const llvm::Triple& Triple); + DarwinClang(const Driver &D, const llvm::Triple& Triple); /// @name Darwin ToolChain Implementation /// { @@ -299,8 +414,8 @@ public: /// Darwin_Generic_GCC - Generic Darwin tool chain using gcc. class LLVM_LIBRARY_VISIBILITY Darwin_Generic_GCC : public Generic_GCC { public: - Darwin_Generic_GCC(const HostInfo &Host, const llvm::Triple& Triple) - : Generic_GCC(Host, Triple) {} + Darwin_Generic_GCC(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) + : Generic_GCC(D, Triple, Args) {} std::string ComputeEffectiveClangTriple(const ArgList &Args, types::ID InputType) const; @@ -309,9 +424,10 @@ public: }; class LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC { - public: - Generic_ELF(const HostInfo &Host, const llvm::Triple& Triple) - : Generic_GCC(Host, Triple) {} + virtual void anchor(); +public: + Generic_ELF(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) + : Generic_GCC(D, Triple, Args) {} virtual bool IsIntegratedAssemblerDefault() const { // Default integrated assembler to on for x86. @@ -322,15 +438,36 @@ class LLVM_LIBRARY_VISIBILITY Generic_ELF : public Generic_GCC { class LLVM_LIBRARY_VISIBILITY AuroraUX : public Generic_GCC { public: - AuroraUX(const HostInfo &Host, const llvm::Triple& Triple); + AuroraUX(const Driver &D, const llvm::Triple& Triple, const ArgList &Args); + + virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const; +}; + +class LLVM_LIBRARY_VISIBILITY Solaris : public Generic_GCC { +public: + Solaris(const Driver &D, const llvm::Triple& Triple, const ArgList &Args); virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const; + + virtual bool IsIntegratedAssemblerDefault() const { return true; } }; + class LLVM_LIBRARY_VISIBILITY OpenBSD : public Generic_ELF { public: - OpenBSD(const HostInfo &Host, const llvm::Triple& Triple); + OpenBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args); + + virtual bool IsObjCNonFragileABIDefault() const { return true; } + virtual bool IsObjCLegacyDispatchDefault() const { + llvm::Triple::ArchType Arch = getTriple().getArch(); + if (Arch == llvm::Triple::arm || + Arch == llvm::Triple::x86 || + Arch == llvm::Triple::x86_64) + return false; + return true; + } virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const; @@ -338,26 +475,43 @@ public: class LLVM_LIBRARY_VISIBILITY FreeBSD : public Generic_ELF { public: - FreeBSD(const HostInfo &Host, const llvm::Triple& Triple); + FreeBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args); + + virtual bool IsObjCNonFragileABIDefault() const { return true; } + virtual bool IsObjCLegacyDispatchDefault() const { + llvm::Triple::ArchType Arch = getTriple().getArch(); + if (Arch == llvm::Triple::arm || + Arch == llvm::Triple::x86 || + Arch == llvm::Triple::x86_64) + return false; + return true; + } virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const; }; class LLVM_LIBRARY_VISIBILITY NetBSD : public Generic_ELF { - const llvm::Triple ToolTriple; - public: - NetBSD(const HostInfo &Host, const llvm::Triple& Triple, - const llvm::Triple& ToolTriple); + NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args); + + virtual bool IsObjCNonFragileABIDefault() const { return true; } + virtual bool IsObjCLegacyDispatchDefault() const { + llvm::Triple::ArchType Arch = getTriple().getArch(); + if (Arch == llvm::Triple::arm || + Arch == llvm::Triple::x86 || + Arch == llvm::Triple::x86_64) + return false; + return true; + } virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const; }; -class LLVM_LIBRARY_VISIBILITY Minix : public Generic_GCC { +class LLVM_LIBRARY_VISIBILITY Minix : public Generic_ELF { public: - Minix(const HostInfo &Host, const llvm::Triple& Triple); + Minix(const Driver &D, const llvm::Triple& Triple, const ArgList &Args); virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const; @@ -365,95 +519,15 @@ public: class LLVM_LIBRARY_VISIBILITY DragonFly : public Generic_ELF { public: - DragonFly(const HostInfo &Host, const llvm::Triple& Triple); + DragonFly(const Driver &D, const llvm::Triple& Triple, const ArgList &Args); virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const; }; class LLVM_LIBRARY_VISIBILITY Linux : public Generic_ELF { - /// \brief Struct to store and manipulate GCC versions. - /// - /// We rely on assumptions about the form and structure of GCC version - /// numbers: they consist of at most three '.'-separated components, and each - /// component is a non-negative integer except for the last component. For - /// the last component we are very flexible in order to tolerate release - /// candidates or 'x' wildcards. - /// - /// Note that the ordering established among GCCVersions is based on the - /// preferred version string to use. For example we prefer versions without - /// a hard-coded patch number to those with a hard coded patch number. - /// - /// Currently this doesn't provide any logic for textual suffixes to patches - /// in the way that (for example) Debian's version format does. If that ever - /// becomes necessary, it can be added. - struct GCCVersion { - /// \brief The unparsed text of the version. - std::string Text; - - /// \brief The parsed major, minor, and patch numbers. - int Major, Minor, Patch; - - /// \brief Any textual suffix on the patch number. - std::string PatchSuffix; - - static GCCVersion Parse(StringRef VersionText); - bool operator<(const GCCVersion &RHS) const; - bool operator>(const GCCVersion &RHS) const { return RHS < *this; } - bool operator<=(const GCCVersion &RHS) const { return !(*this > RHS); } - bool operator>=(const GCCVersion &RHS) const { return !(*this < RHS); } - }; - - - /// \brief This is a class to find a viable GCC installation for Clang to - /// use. - /// - /// This class tries to find a GCC installation on the system, and report - /// information about it. It starts from the host information provided to the - /// Driver, and has logic for fuzzing that where appropriate. - class GCCInstallationDetector { - - bool IsValid; - std::string GccTriple; - - // FIXME: These might be better as path objects. - std::string GccInstallPath; - std::string GccParentLibPath; - - GCCVersion Version; - - public: - GCCInstallationDetector(const Driver &D); - - /// \brief Check whether we detected a valid GCC install. - bool isValid() const { return IsValid; } - - /// \brief Get the GCC triple for the detected install. - StringRef getTriple() const { return GccTriple; } - - /// \brief Get the detected GCC installation path. - StringRef getInstallPath() const { return GccInstallPath; } - - /// \brief Get the detected GCC parent lib path. - StringRef getParentLibPath() const { return GccParentLibPath; } - - /// \brief Get the detected GCC version string. - StringRef getVersion() const { return Version.Text; } - - private: - static void CollectLibDirsAndTriples(llvm::Triple::ArchType HostArch, - SmallVectorImpl<StringRef> &LibDirs, - SmallVectorImpl<StringRef> &Triples); - - void ScanLibDirForGCCTriple(llvm::Triple::ArchType HostArch, - const std::string &LibDir, - StringRef CandidateTriple); - }; - - GCCInstallationDetector GCCInstallation; - public: - Linux(const HostInfo &Host, const llvm::Triple& Triple); + Linux(const Driver &D, const llvm::Triple& Triple, const ArgList &Args); virtual bool HasNativeLLVMSupport() const; @@ -467,6 +541,11 @@ public: std::string Linker; std::vector<std::string> ExtraOpts; + +private: + static bool addLibStdCXXIncludePaths(Twine Base, Twine TargetArchDir, + const ArgList &DriverArgs, + ArgStringList &CC1Args); }; @@ -474,7 +553,7 @@ public: /// all subcommands. See http://tce.cs.tut.fi for our peculiar target. class LLVM_LIBRARY_VISIBILITY TCEToolChain : public ToolChain { public: - TCEToolChain(const HostInfo &Host, const llvm::Triple& Triple); + TCEToolChain(const Driver &D, const llvm::Triple& Triple); ~TCEToolChain(); virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, @@ -493,7 +572,7 @@ class LLVM_LIBRARY_VISIBILITY Windows : public ToolChain { mutable llvm::DenseMap<unsigned, Tool*> Tools; public: - Windows(const HostInfo &Host, const llvm::Triple& Triple); + Windows(const Driver &D, const llvm::Triple& Triple); virtual Tool &SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const; diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp index d9423d2..d3dab19 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.cpp @@ -16,7 +16,6 @@ #include "clang/Driver/DriverDiagnostic.h" #include "clang/Driver/Compilation.h" #include "clang/Driver/Job.h" -#include "clang/Driver/HostInfo.h" #include "clang/Driver/ObjCRuntime.h" #include "clang/Driver/Option.h" #include "clang/Driver/Options.h" @@ -36,13 +35,6 @@ #include "InputInfo.h" #include "ToolChains.h" -#ifdef __CYGWIN__ -#include <cygwin/version.h> -#if defined(CYGWIN_VERSION_DLL_MAJOR) && CYGWIN_VERSION_DLL_MAJOR<1007 -#define IS_CYGWIN15 1 -#endif -#endif - using namespace clang::driver; using namespace clang::driver::tools; using namespace clang; @@ -96,6 +88,39 @@ static void QuoteTarget(StringRef Target, } } +static void addDirectoryList(const ArgList &Args, + ArgStringList &CmdArgs, + const char *ArgName, + const char *EnvVar) { + const char *DirList = ::getenv(EnvVar); + if (!DirList) + return; // Nothing to do. + + StringRef Dirs(DirList); + if (Dirs.empty()) // Empty string should not add '.'. + return; + + StringRef::size_type Delim; + while ((Delim = Dirs.find(llvm::sys::PathSeparator)) != StringRef::npos) { + if (Delim == 0) { // Leading colon. + CmdArgs.push_back(ArgName); + CmdArgs.push_back("."); + } else { + CmdArgs.push_back(ArgName); + CmdArgs.push_back(Args.MakeArgString(Dirs.substr(0, Delim))); + } + Dirs = Dirs.substr(Delim + 1); + } + + if (Dirs.empty()) { // Trailing colon. + CmdArgs.push_back(ArgName); + CmdArgs.push_back("."); + } else { // Add the last path. + CmdArgs.push_back(ArgName); + CmdArgs.push_back(Args.MakeArgString(Dirs)); + } +} + static void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs, const ArgList &Args, ArgStringList &CmdArgs) { @@ -136,6 +161,9 @@ static void AddLinkerInputs(const ToolChain &TC, } else A.renderAsInput(Args, CmdArgs); } + + // LIBRARY_PATH - included following the user specified library paths. + addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); } /// \brief Determine whether Objective-C automated reference counting is @@ -144,6 +172,13 @@ static bool isObjCAutoRefCount(const ArgList &Args) { return Args.hasFlag(options::OPT_fobjc_arc, options::OPT_fno_objc_arc, false); } +/// \brief Determine whether we are linking the ObjC runtime. +static bool isObjCRuntimeLinked(const ArgList &Args) { + if (isObjCAutoRefCount(Args)) + return true; + return Args.hasArg(options::OPT_fobjc_link_runtime); +} + static void addProfileRT(const ToolChain &TC, const ArgList &Args, ArgStringList &CmdArgs, llvm::Triple Triple) { @@ -157,53 +192,14 @@ static void addProfileRT(const ToolChain &TC, const ArgList &Args, // the link line. We cannot do the same thing because unlike gcov there is a // libprofile_rt.so. We used to use the -l:libprofile_rt.a syntax, but that is // not supported by old linkers. - Twine ProfileRT = - Twine(TC.getDriver().Dir) + "/../lib/" + "libprofile_rt.a"; - - if (Triple.isOSDarwin()) { - // On Darwin, if the static library doesn't exist try the dylib. - bool Exists; - if (llvm::sys::fs::exists(ProfileRT.str(), Exists) || !Exists) - ProfileRT = - Twine(TC.getDriver().Dir) + "/../lib/" + "libprofile_rt.dylib"; - } + std::string ProfileRT = + std::string(TC.getDriver().Dir) + "/../lib/libprofile_rt.a"; CmdArgs.push_back(Args.MakeArgString(ProfileRT)); } -static void AddIncludeDirectoryList(const ArgList &Args, - ArgStringList &CmdArgs, - const char *ArgName, - const char *DirList) { - if (!DirList) - return; // Nothing to do. - - StringRef Dirs(DirList); - if (Dirs.empty()) // Empty string should not add '.'. - return; - - StringRef::size_type Delim; - while ((Delim = Dirs.find(llvm::sys::PathSeparator)) != StringRef::npos) { - if (Delim == 0) { // Leading colon. - CmdArgs.push_back(ArgName); - CmdArgs.push_back("."); - } else { - CmdArgs.push_back(ArgName); - CmdArgs.push_back(Args.MakeArgString(Dirs.substr(0, Delim))); - } - Dirs = Dirs.substr(Delim + 1); - } - - if (Dirs.empty()) { // Trailing colon. - CmdArgs.push_back(ArgName); - CmdArgs.push_back("."); - } else { // Add the last path. - CmdArgs.push_back(ArgName); - CmdArgs.push_back(Args.MakeArgString(Dirs)); - } -} - -void Clang::AddPreprocessingOptions(const Driver &D, +void Clang::AddPreprocessingOptions(Compilation &C, + const Driver &D, const ArgList &Args, ArgStringList &CmdArgs, const InputInfo &Output, @@ -225,11 +221,13 @@ void Clang::AddPreprocessingOptions(const Driver &D, DepFile = Output.getFilename(); } else if (Arg *MF = Args.getLastArg(options::OPT_MF)) { DepFile = MF->getValue(Args); + C.addFailureResultFile(DepFile); } else if (A->getOption().matches(options::OPT_M) || A->getOption().matches(options::OPT_MM)) { DepFile = "-"; } else { DepFile = darwin::CC1::getDependencyFileName(Args, Inputs); + C.addFailureResultFile(DepFile); } CmdArgs.push_back("-dependency-file"); CmdArgs.push_back(DepFile); @@ -247,13 +245,13 @@ void Clang::AddPreprocessingOptions(const Driver &D, // Otherwise derive from the base input. // // FIXME: This should use the computed output file location. - llvm::SmallString<128> P(Inputs[0].getBaseInput()); + SmallString<128> P(Inputs[0].getBaseInput()); llvm::sys::path::replace_extension(P, "o"); DepTarget = Args.MakeArgString(llvm::sys::path::filename(P)); } CmdArgs.push_back("-MT"); - llvm::SmallString<128> Quoted; + SmallString<128> Quoted; QuoteTarget(DepTarget, Quoted); CmdArgs.push_back(Args.MakeArgString(Quoted)); } @@ -281,7 +279,7 @@ void Clang::AddPreprocessingOptions(const Driver &D, if (A->getOption().matches(options::OPT_MQ)) { CmdArgs.push_back("-MT"); - llvm::SmallString<128> Quoted; + SmallString<128> Quoted; QuoteTarget(A->getValue(Args), Quoted); CmdArgs.push_back(Args.MakeArgString(Quoted)); @@ -392,7 +390,7 @@ void Clang::AddPreprocessingOptions(const Driver &D, A->claim(); A->render(Args, CmdArgs); } else { - llvm::SmallString<128> DefaultModuleCache; + SmallString<128> DefaultModuleCache; llvm::sys::path::system_temp_directory(/*erasedOnReboot=*/false, DefaultModuleCache); llvm::sys::path::append(DefaultModuleCache, "clang-module-cache"); @@ -400,24 +398,20 @@ void Clang::AddPreprocessingOptions(const Driver &D, CmdArgs.push_back(Args.MakeArgString(DefaultModuleCache)); } - Args.AddAllArgs(CmdArgs, options::OPT_fauto_module_import); - // Parse additional include paths from environment variables. + // FIXME: We should probably sink the logic for handling these from the + // frontend into the driver. It will allow deleting 4 otherwise unused flags. // CPATH - included following the user specified includes (but prior to // builtin and standard includes). - AddIncludeDirectoryList(Args, CmdArgs, "-I", ::getenv("CPATH")); + addDirectoryList(Args, CmdArgs, "-I", "CPATH"); // C_INCLUDE_PATH - system includes enabled when compiling C. - AddIncludeDirectoryList(Args, CmdArgs, "-c-isystem", - ::getenv("C_INCLUDE_PATH")); + addDirectoryList(Args, CmdArgs, "-c-isystem", "C_INCLUDE_PATH"); // CPLUS_INCLUDE_PATH - system includes enabled when compiling C++. - AddIncludeDirectoryList(Args, CmdArgs, "-cxx-isystem", - ::getenv("CPLUS_INCLUDE_PATH")); + addDirectoryList(Args, CmdArgs, "-cxx-isystem", "CPLUS_INCLUDE_PATH"); // OBJC_INCLUDE_PATH - system includes enabled when compiling ObjC. - AddIncludeDirectoryList(Args, CmdArgs, "-objc-isystem", - ::getenv("OBJC_INCLUDE_PATH")); + addDirectoryList(Args, CmdArgs, "-objc-isystem", "OBJC_INCLUDE_PATH"); // OBJCPLUS_INCLUDE_PATH - system includes enabled when compiling ObjC++. - AddIncludeDirectoryList(Args, CmdArgs, "-objcxx-isystem", - ::getenv("OBJCPLUS_INCLUDE_PATH")); + addDirectoryList(Args, CmdArgs, "-objcxx-isystem", "OBJCPLUS_INCLUDE_PATH"); // Add C++ include arguments, if needed. if (types::isCXX(Inputs[0].getType())) @@ -489,6 +483,9 @@ static const char *getLLVMArchSuffixForARM(StringRef CPU) { .Cases("arm1176jzf-s", "mpcorenovfp", "mpcore", "v6") .Cases("arm1156t2-s", "arm1156t2f-s", "v6t2") .Cases("cortex-a8", "cortex-a9", "v7") + .Case("cortex-m3", "v7m") + .Case("cortex-m4", "v7m") + .Case("cortex-m0", "v6m") .Default(""); } @@ -504,46 +501,78 @@ static bool isSignedCharDefault(const llvm::Triple &Triple) { if (Triple.isOSDarwin()) return true; return false; - - case llvm::Triple::systemz: - return false; } } -void Clang::AddARMTargetArgs(const ArgList &Args, - ArgStringList &CmdArgs, - bool KernelOrKext) const { - const Driver &D = getToolChain().getDriver(); - llvm::Triple Triple = getToolChain().getTriple(); +// Handle -mfpu=. +// +// FIXME: Centralize feature selection, defaulting shouldn't be also in the +// frontend target. +static void addFPUArgs(const Driver &D, const Arg *A, const ArgList &Args, + ArgStringList &CmdArgs) { + StringRef FPU = A->getValue(Args); + + // Set the target features based on the FPU. + if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") { + // Disable any default FPU support. + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-vfp2"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-vfp3"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-neon"); + } else if (FPU == "vfp3-d16" || FPU == "vfpv3-d16") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+vfp3"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+d16"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-neon"); + } else if (FPU == "vfp") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+vfp2"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-neon"); + } else if (FPU == "vfp3" || FPU == "vfpv3") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+vfp3"); + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-neon"); + } else if (FPU == "neon") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+neon"); + } else + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); +} - // Select the ABI to use. - // - // FIXME: Support -meabi. - const char *ABIName = 0; - if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { - ABIName = A->getValue(Args); - } else { - // Select the default based on the platform. - switch(Triple.getEnvironment()) { - case llvm::Triple::GNUEABI: - ABIName = "aapcs-linux"; - break; - case llvm::Triple::EABI: - ABIName = "aapcs"; - break; - default: - ABIName = "apcs-gnu"; - } - } - CmdArgs.push_back("-target-abi"); - CmdArgs.push_back(ABIName); +// Handle -mfpmath=. +static void addFPMathArgs(const Driver &D, const Arg *A, const ArgList &Args, + ArgStringList &CmdArgs, StringRef CPU) { + StringRef FPMath = A->getValue(Args); + + // Set the target features based on the FPMath. + if (FPMath == "neon") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+neonfp"); + + if (CPU != "cortex-a8" && CPU != "cortex-a9" && CPU != "cortex-a9-mp") + D.Diag(diag::err_drv_invalid_feature) << "-mfpmath=neon" << CPU; + + } else if (FPMath == "vfp" || FPMath == "vfp2" || FPMath == "vfp3" || + FPMath == "vfp4") { + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("-neonfp"); - // Set the CPU based on -march= and -mcpu=. - CmdArgs.push_back("-target-cpu"); - CmdArgs.push_back(getARMTargetCPU(Args, Triple)); + // FIXME: Add warnings when disabling a feature not present for a given CPU. + } else + D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); +} - // Select the float ABI as determined by -msoft-float, -mhard-float, and - // -mfloat-abi=. +// Select the float ABI as determined by -msoft-float, -mhard-float, and +// -mfloat-abi=. +static StringRef getARMFloatABI(const Driver &D, + const ArgList &Args, + const llvm::Triple &Triple) { StringRef FloatABI; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, @@ -564,7 +593,6 @@ void Clang::AddARMTargetArgs(const ArgList &Args, // If unspecified, choose the default based on the platform. if (FloatABI.empty()) { - const llvm::Triple &Triple = getToolChain().getTriple(); switch (Triple.getOS()) { case llvm::Triple::Darwin: case llvm::Triple::MacOSX: @@ -582,7 +610,7 @@ void Clang::AddARMTargetArgs(const ArgList &Args, } case llvm::Triple::Linux: { - if (getToolChain().getTriple().getEnvironment() == llvm::Triple::GNUEABI) { + if (Triple.getEnvironment() == llvm::Triple::GNUEABI) { FloatABI = "softfp"; break; } @@ -598,6 +626,15 @@ void Clang::AddARMTargetArgs(const ArgList &Args, // EABI is always AAPCS, and if it was not marked 'hard', it's softfp FloatABI = "softfp"; break; + case llvm::Triple::ANDROIDEABI: { + StringRef ArchName = + getLLVMArchSuffixForARM(getARMTargetCPU(Args, Triple)); + if (ArchName.startswith("v7")) + FloatABI = "softfp"; + else + FloatABI = "soft"; + break; + } default: // Assume "soft", but warn the user we are guessing. FloatABI = "soft"; @@ -607,6 +644,45 @@ void Clang::AddARMTargetArgs(const ArgList &Args, } } + return FloatABI; +} + + +void Clang::AddARMTargetArgs(const ArgList &Args, + ArgStringList &CmdArgs, + bool KernelOrKext) const { + const Driver &D = getToolChain().getDriver(); + llvm::Triple Triple = getToolChain().getTriple(); + + // Select the ABI to use. + // + // FIXME: Support -meabi. + const char *ABIName = 0; + if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { + ABIName = A->getValue(Args); + } else { + // Select the default based on the platform. + switch(Triple.getEnvironment()) { + case llvm::Triple::ANDROIDEABI: + case llvm::Triple::GNUEABI: + ABIName = "aapcs-linux"; + break; + case llvm::Triple::EABI: + ABIName = "aapcs"; + break; + default: + ABIName = "apcs-gnu"; + } + } + CmdArgs.push_back("-target-abi"); + CmdArgs.push_back(ABIName); + + // Set the CPU based on -march= and -mcpu=. + CmdArgs.push_back("-target-cpu"); + CmdArgs.push_back(getARMTargetCPU(Args, Triple)); + + // Determine floating point ABI from the options & target defaults. + StringRef FloatABI = getARMFloatABI(D, Args, Triple); if (FloatABI == "soft") { // Floating point operations and argument passing are soft. // @@ -644,33 +720,12 @@ void Clang::AddARMTargetArgs(const ArgList &Args, } // Honor -mfpu=. - // - // FIXME: Centralize feature selection, defaulting shouldn't be also in the - // frontend target. - if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) { - StringRef FPU = A->getValue(Args); - - // Set the target features based on the FPU. - if (FPU == "fpa" || FPU == "fpe2" || FPU == "fpe3" || FPU == "maverick") { - // Disable any default FPU support. - CmdArgs.push_back("-target-feature"); - CmdArgs.push_back("-vfp2"); - CmdArgs.push_back("-target-feature"); - CmdArgs.push_back("-vfp3"); - CmdArgs.push_back("-target-feature"); - CmdArgs.push_back("-neon"); - } else if (FPU == "vfp") { - CmdArgs.push_back("-target-feature"); - CmdArgs.push_back("+vfp2"); - } else if (FPU == "vfp3") { - CmdArgs.push_back("-target-feature"); - CmdArgs.push_back("+vfp3"); - } else if (FPU == "neon") { - CmdArgs.push_back("-target-feature"); - CmdArgs.push_back("+neon"); - } else - D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); - } + if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) + addFPUArgs(D, A, Args, CmdArgs); + + // Honor -mfpmath=. + if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ)) + addFPMathArgs(D, A, Args, CmdArgs, getARMTargetCPU(Args, Triple)); // Setting -msoft-float effectively disables NEON because of the GCC // implementation, although the same isn't true of VFP or VFP3. @@ -703,25 +758,32 @@ void Clang::AddARMTargetArgs(const ArgList &Args, // Get default architecture. static const char* getMipsArchFromCPU(StringRef CPUName) { - if (CPUName == "mips32r1" || CPUName == "4ke") + if (CPUName == "mips32" || CPUName == "mips32r2") return "mips"; - assert((CPUName == "mips64r1" || CPUName == "mips64r2") && + assert((CPUName == "mips64" || CPUName == "mips64r2") && "Unexpected cpu name."); return "mips64"; } +// Check that ArchName is a known Mips architecture name. +static bool checkMipsArchName(StringRef ArchName) { + return ArchName == "mips" || + ArchName == "mipsel" || + ArchName == "mips64" || + ArchName == "mips64el"; +} + // Get default target cpu. -static const char* getMipsCPUFromArch(StringRef ArchName, const Driver &D) { +static const char* getMipsCPUFromArch(StringRef ArchName) { if (ArchName == "mips" || ArchName == "mipsel") - return "mips32r1"; - else if (ArchName == "mips64" || ArchName == "mips64el") - return "mips64r1"; - else - D.Diag(diag::err_drv_invalid_arch_name) << ArchName; + return "mips32"; + + assert((ArchName == "mips64" || ArchName == "mips64el") && + "Unexpected arch name."); - return 0; + return "mips64"; } // Get default ABI. @@ -734,61 +796,98 @@ static const char* getMipsABIFromArch(StringRef ArchName) { return "n64"; } -void Clang::AddMIPSTargetArgs(const ArgList &Args, - ArgStringList &CmdArgs) const { - const Driver &D = getToolChain().getDriver(); - +// Get CPU and ABI names. They are not independent +// so we have to calculate them together. +static void getMipsCPUAndABI(const ArgList &Args, + const ToolChain &TC, + StringRef &CPUName, + StringRef &ABIName) { StringRef ArchName; - const char *CPUName; - // Set target cpu and architecture. + // Select target cpu and architecture. if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { CPUName = A->getValue(Args); ArchName = getMipsArchFromCPU(CPUName); } else { - ArchName = Args.MakeArgString(getToolChain().getArchName()); - CPUName = getMipsCPUFromArch(ArchName, D); + ArchName = Args.MakeArgString(TC.getArchName()); + if (!checkMipsArchName(ArchName)) + TC.getDriver().Diag(diag::err_drv_invalid_arch_name) << ArchName; + else + CPUName = getMipsCPUFromArch(ArchName); } - - CmdArgs.push_back("-target-cpu"); - CmdArgs.push_back(CPUName); // Select the ABI to use. - const char *ABIName = 0; if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) ABIName = A->getValue(Args); else ABIName = getMipsABIFromArch(ArchName); +} + +void Clang::AddMIPSTargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + const Driver &D = getToolChain().getDriver(); + StringRef CPUName; + StringRef ABIName; + getMipsCPUAndABI(Args, getToolChain(), CPUName, ABIName); + + CmdArgs.push_back("-target-cpu"); + CmdArgs.push_back(CPUName.data()); CmdArgs.push_back("-target-abi"); - CmdArgs.push_back(ABIName); + CmdArgs.push_back(ABIName.data()); - // Select the float ABI as determined by -msoft-float, -mhard-float, and + // Select the float ABI as determined by -msoft-float, -mhard-float, + // and -mfloat-abi=. StringRef FloatABI; if (Arg *A = Args.getLastArg(options::OPT_msoft_float, - options::OPT_mhard_float)) { + options::OPT_mhard_float, + options::OPT_mfloat_abi_EQ)) { if (A->getOption().matches(options::OPT_msoft_float)) FloatABI = "soft"; else if (A->getOption().matches(options::OPT_mhard_float)) FloatABI = "hard"; + else { + FloatABI = A->getValue(Args); + if (FloatABI != "soft" && FloatABI != "single" && FloatABI != "hard") { + D.Diag(diag::err_drv_invalid_mfloat_abi) + << A->getAsString(Args); + FloatABI = "hard"; + } + } } // If unspecified, choose the default based on the platform. if (FloatABI.empty()) { - // Assume "soft", but warn the user we are guessing. - FloatABI = "soft"; - D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; + // Assume "hard", because it's a default value used by gcc. + // When we start to recognize specific target MIPS processors, + // we will be able to select the default more correctly. + FloatABI = "hard"; } if (FloatABI == "soft") { // Floating point operations and argument passing are soft. - // - // FIXME: This changes CPP defines, we need -target-soft-float. CmdArgs.push_back("-msoft-float"); - } else { + CmdArgs.push_back("-mfloat-abi"); + CmdArgs.push_back("soft"); + + // FIXME: Note, this is a hack. We need to pass the selected float + // mode to the MipsTargetInfoBase to define appropriate macros there. + // Now it is the only method. + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+soft-float"); + } + else if (FloatABI == "single") { + // Restrict the use of hardware floating-point + // instructions to 32-bit operations. + CmdArgs.push_back("-target-feature"); + CmdArgs.push_back("+single-float"); + } + else { + // Floating point operations and argument passing are hard. assert(FloatABI == "hard" && "Invalid float abi!"); - CmdArgs.push_back("-mhard-float"); + CmdArgs.push_back("-mfloat-abi"); + CmdArgs.push_back("hard"); } } @@ -797,9 +896,8 @@ void Clang::AddSparcTargetArgs(const ArgList &Args, const Driver &D = getToolChain().getDriver(); if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) { - StringRef MArch = A->getValue(Args); CmdArgs.push_back("-target-cpu"); - CmdArgs.push_back(MArch.str().c_str()); + CmdArgs.push_back(A->getValue(Args)); } // Select the float ABI as determined by -msoft-float, -mhard-float, and @@ -941,6 +1039,70 @@ void Clang::AddX86TargetArgs(const ArgList &Args, } } +static Arg* getLastHexagonArchArg (const ArgList &Args) +{ + Arg * A = NULL; + + for (ArgList::const_iterator it = Args.begin(), ie = Args.end(); + it != ie; ++it) { + if ((*it)->getOption().matches(options::OPT_march_EQ) || + (*it)->getOption().matches(options::OPT_mcpu_EQ)) { + A = *it; + A->claim(); + } + else if ((*it)->getOption().matches(options::OPT_m_Joined)){ + StringRef Value = (*it)->getValue(Args,0); + if (Value.startswith("v")) { + A = *it; + A->claim(); + } + } + } + return A; +} + +static StringRef getHexagonTargetCPU(const ArgList &Args) +{ + Arg *A; + llvm::StringRef WhichHexagon; + + // Select the default CPU (v4) if none was given or detection failed. + if ((A = getLastHexagonArchArg (Args))) { + WhichHexagon = A->getValue(Args); + if (WhichHexagon == "") + return "v4"; + else + return WhichHexagon; + } + else + return "v4"; +} + +void Clang::AddHexagonTargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + llvm::Triple Triple = getToolChain().getTriple(); + + CmdArgs.push_back("-target-cpu"); + CmdArgs.push_back(Args.MakeArgString("hexagon" + getHexagonTargetCPU(Args))); + CmdArgs.push_back("-fno-signed-char"); + CmdArgs.push_back("-nobuiltininc"); + + if (Args.hasArg(options::OPT_mqdsp6_compat)) + CmdArgs.push_back("-mqdsp6-compat"); + + if (Arg *A = Args.getLastArg(options::OPT_G, + options::OPT_msmall_data_threshold_EQ)) { + std::string SmallDataThreshold="-small-data-threshold="; + SmallDataThreshold += A->getValue(Args); + CmdArgs.push_back ("-mllvm"); + CmdArgs.push_back(Args.MakeArgString(SmallDataThreshold)); + A->claim(); + } + + CmdArgs.push_back ("-mllvm"); + CmdArgs.push_back ("-machine-sink-split=0"); +} + static bool shouldUseExceptionTablesForObjCExceptions(unsigned objcABIVersion, const llvm::Triple &Triple) { @@ -966,11 +1128,20 @@ shouldUseExceptionTablesForObjCExceptions(unsigned objcABIVersion, /// Objective-C exceptions. static void addExceptionArgs(const ArgList &Args, types::ID InputType, const llvm::Triple &Triple, - bool KernelOrKext, bool IsRewriter, + bool KernelOrKext, unsigned objcABIVersion, ArgStringList &CmdArgs) { - if (KernelOrKext) + if (KernelOrKext) { + // -mkernel and -fapple-kext imply no exceptions, so claim exception related + // arguments now to avoid warnings about unused arguments. + Args.ClaimAllArgs(options::OPT_fexceptions); + Args.ClaimAllArgs(options::OPT_fno_exceptions); + Args.ClaimAllArgs(options::OPT_fobjc_exceptions); + Args.ClaimAllArgs(options::OPT_fno_objc_exceptions); + Args.ClaimAllArgs(options::OPT_fcxx_exceptions); + Args.ClaimAllArgs(options::OPT_fno_cxx_exceptions); return; + } // Exceptions are enabled by default. bool ExceptionsEnabled = true; @@ -1033,28 +1204,29 @@ static void addExceptionArgs(const ArgList &Args, types::ID InputType, static bool ShouldDisableCFI(const ArgList &Args, const ToolChain &TC) { + bool Default = true; if (TC.getTriple().isOSDarwin()) { // The native darwin assembler doesn't support cfi directives, so // we disable them if we think the .s file will be passed to it. + Default = Args.hasFlag(options::OPT_integrated_as, + options::OPT_no_integrated_as, + TC.IsIntegratedAssemblerDefault()); + } + return !Args.hasFlag(options::OPT_fdwarf2_cfi_asm, + options::OPT_fno_dwarf2_cfi_asm, + Default); +} - // FIXME: Duplicated code with ToolChains.cpp - // FIXME: This doesn't belong here, but ideally we will support static soon - // anyway. - bool HasStatic = (Args.hasArg(options::OPT_mkernel) || - Args.hasArg(options::OPT_static) || - Args.hasArg(options::OPT_fapple_kext)); - bool IsIADefault = TC.IsIntegratedAssemblerDefault() && !HasStatic; - bool UseIntegratedAs = Args.hasFlag(options::OPT_integrated_as, - options::OPT_no_integrated_as, - IsIADefault); - bool UseCFI = Args.hasFlag(options::OPT_fdwarf2_cfi_asm, - options::OPT_fno_dwarf2_cfi_asm, - UseIntegratedAs); - return !UseCFI; - } - - // For now we assume that every other assembler support CFI. - return false; +static bool ShouldDisableDwarfDirectory(const ArgList &Args, + const ToolChain &TC) { + bool IsIADefault = TC.IsIntegratedAssemblerDefault(); + bool UseIntegratedAs = Args.hasFlag(options::OPT_integrated_as, + options::OPT_no_integrated_as, + IsIADefault); + bool UseDwarfDirectory = Args.hasFlag(options::OPT_fdwarf_directory_asm, + options::OPT_fno_dwarf_directory_asm, + UseIntegratedAs); + return !UseDwarfDirectory; } /// \brief Check whether the given input tree contains any compilation actions. @@ -1092,6 +1264,46 @@ static bool UseRelaxAll(Compilation &C, const ArgList &Args) { RelaxDefault); } +/// If AddressSanitizer is enabled, add appropriate linker flags (Linux). +/// This needs to be called before we add the C run-time (malloc, etc). +static void addAsanRTLinux(const ToolChain &TC, const ArgList &Args, + ArgStringList &CmdArgs) { + // Add asan linker flags when linking an executable, but not a shared object. + if (Args.hasArg(options::OPT_shared) || + !Args.hasFlag(options::OPT_faddress_sanitizer, + options::OPT_fno_address_sanitizer, false)) + return; + + // LibAsan is "libclang_rt.asan-<ArchName>.a" in the Linux library resource + // directory. + SmallString<128> LibAsan(TC.getDriver().ResourceDir); + llvm::sys::path::append(LibAsan, "lib", "linux", + (Twine("libclang_rt.asan-") + + TC.getArchName() + ".a")); + CmdArgs.push_back(Args.MakeArgString(LibAsan)); + CmdArgs.push_back("-lpthread"); + CmdArgs.push_back("-ldl"); + CmdArgs.push_back("-export-dynamic"); +} + +static bool shouldUseFramePointer(const ArgList &Args, + const llvm::Triple &Triple) { + if (Arg *A = Args.getLastArg(options::OPT_fno_omit_frame_pointer, + options::OPT_fomit_frame_pointer)) + return A->getOption().matches(options::OPT_fno_omit_frame_pointer); + + // Don't use a frame pointer on linux x86 and x86_64 if optimizing. + if ((Triple.getArch() == llvm::Triple::x86_64 || + Triple.getArch() == llvm::Triple::x86) && + Triple.getOS() == llvm::Triple::Linux) { + if (Arg *A = Args.getLastArg(options::OPT_O_Group)) + if (!A->getOption().matches(options::OPT_O0)) + return false; + } + + return true; +} + void Clang::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -1116,9 +1328,13 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Select the appropriate action. bool IsRewriter = false; + bool IsModernRewriter = false; + if (isa<AnalyzeJobAction>(JA)) { assert(JA.getType() == types::TY_Plist && "Invalid output type."); CmdArgs.push_back("-analyze"); + } else if (isa<MigrateJobAction>(JA)) { + CmdArgs.push_back("-migrate"); } else if (isa<PreprocessJobAction>(JA)) { if (Output.getType() == types::TY_Dependencies) CmdArgs.push_back("-Eonly"); @@ -1184,6 +1400,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-emit-pch"); } else if (JA.getType() == types::TY_RewrittenObjC) { CmdArgs.push_back("-rewrite-objc"); + IsModernRewriter = true; + } else if (JA.getType() == types::TY_RewrittenLegacyObjC) { + CmdArgs.push_back("-rewrite-objc"); IsRewriter = true; } else { assert(JA.getType() == types::TY_PP_Asm && @@ -1218,17 +1437,27 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-analyzer-eagerly-assume"); + CmdArgs.push_back("-analyzer-ipa=inlining"); + // Add default argument set. if (!Args.hasArg(options::OPT__analyzer_no_default_checks)) { CmdArgs.push_back("-analyzer-checker=core"); - CmdArgs.push_back("-analyzer-checker=deadcode"); - CmdArgs.push_back("-analyzer-checker=security"); if (getToolChain().getTriple().getOS() != llvm::Triple::Win32) CmdArgs.push_back("-analyzer-checker=unix"); if (getToolChain().getTriple().getVendor() == llvm::Triple::Apple) CmdArgs.push_back("-analyzer-checker=osx"); + + CmdArgs.push_back("-analyzer-checker=deadcode"); + + // Enable the following experimental checkers for testing. + CmdArgs.push_back("-analyzer-checker=security.insecureAPI.UncheckedReturn"); + CmdArgs.push_back("-analyzer-checker=security.insecureAPI.getpw"); + CmdArgs.push_back("-analyzer-checker=security.insecureAPI.gets"); + CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mktemp"); + CmdArgs.push_back("-analyzer-checker=security.insecureAPI.mkstemp"); + CmdArgs.push_back("-analyzer-checker=security.insecureAPI.vfork"); } // Set the output format. The default is plist, for (lame) historical @@ -1260,15 +1489,43 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // would do to enable flag_pic. // // FIXME: Centralize this code. - bool PICEnabled = (Args.hasArg(options::OPT_fPIC) || - Args.hasArg(options::OPT_fpic) || - Args.hasArg(options::OPT_fPIE) || - Args.hasArg(options::OPT_fpie)); - bool PICDisabled = (Args.hasArg(options::OPT_mkernel) || - Args.hasArg(options::OPT_static)); + Arg *LastPICArg = 0; + for (ArgList::const_iterator I = Args.begin(), E = Args.end(); I != E; ++I) { + if ((*I)->getOption().matches(options::OPT_fPIC) || + (*I)->getOption().matches(options::OPT_fno_PIC) || + (*I)->getOption().matches(options::OPT_fpic) || + (*I)->getOption().matches(options::OPT_fno_pic) || + (*I)->getOption().matches(options::OPT_fPIE) || + (*I)->getOption().matches(options::OPT_fno_PIE) || + (*I)->getOption().matches(options::OPT_fpie) || + (*I)->getOption().matches(options::OPT_fno_pie)) { + LastPICArg = *I; + (*I)->claim(); + } + } + bool PICDisabled = false; + bool PICEnabled = false; + bool PICForPIE = false; + if (LastPICArg) { + PICForPIE = (LastPICArg->getOption().matches(options::OPT_fPIE) || + LastPICArg->getOption().matches(options::OPT_fpie)); + PICEnabled = (PICForPIE || + LastPICArg->getOption().matches(options::OPT_fPIC) || + LastPICArg->getOption().matches(options::OPT_fpic)); + PICDisabled = !PICEnabled; + } + // Note that these flags are trump-cards. Regardless of the order w.r.t. the + // PIC or PIE options above, if these show up, PIC is disabled. + if (Args.hasArg(options::OPT_mkernel)) + PICDisabled = true; + if (Args.hasArg(options::OPT_static)) + PICDisabled = true; + bool DynamicNoPIC = Args.hasArg(options::OPT_mdynamic_no_pic); + + // Select the relocation model. const char *Model = getToolChain().GetForcedPicModel(); if (!Model) { - if (Args.hasArg(options::OPT_mdynamic_no_pic)) + if (DynamicNoPIC) Model = "dynamic-no-pic"; else if (PICDisabled) Model = "static"; @@ -1277,19 +1534,25 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, else Model = getToolChain().GetDefaultRelocationModel(); } - if (StringRef(Model) != "pic") { + StringRef ModelStr = Model ? Model : ""; + if (Model && ModelStr != "pic") { CmdArgs.push_back("-mrelocation-model"); CmdArgs.push_back(Model); } - // Infer the __PIC__ value. - // - // FIXME: This isn't quite right on Darwin, which always sets - // __PIC__=2. - if (strcmp(Model, "pic") == 0 || strcmp(Model, "dynamic-no-pic") == 0) { + // Infer the __PIC__ and __PIE__ values. + if (ModelStr == "pic" && PICForPIE) { + CmdArgs.push_back("-pie-level"); + CmdArgs.push_back((LastPICArg && + LastPICArg->getOption().matches(options::OPT_fPIE)) ? + "2" : "1"); + } else if (ModelStr == "pic" || ModelStr == "dynamic-no-pic") { CmdArgs.push_back("-pic-level"); - CmdArgs.push_back(Args.hasArg(options::OPT_fPIC) ? "2" : "1"); + CmdArgs.push_back(((ModelStr != "dynamic-no-pic" && LastPICArg && + LastPICArg->getOption().matches(options::OPT_fPIC)) || + getToolChain().getTriple().isOSDarwin()) ? "2" : "1"); } + if (!Args.hasFlag(options::OPT_fmerge_all_constants, options::OPT_fno_merge_all_constants)) CmdArgs.push_back("-fno-merge-all-constants"); @@ -1304,9 +1567,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasFlag(options::OPT_mrtd, options::OPT_mno_rtd, false)) CmdArgs.push_back("-mrtd"); - // FIXME: Set --enable-unsafe-fp-math. - if (Args.hasFlag(options::OPT_fno_omit_frame_pointer, - options::OPT_fomit_frame_pointer)) + if (shouldUseFramePointer(Args, getToolChain().getTriple())) CmdArgs.push_back("-mdisable-fp-elim"); if (!Args.hasFlag(options::OPT_fzero_initialized_in_bss, options::OPT_fno_zero_initialized_in_bss)) @@ -1315,6 +1576,96 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_strict_aliasing, getToolChain().IsStrictAliasingDefault())) CmdArgs.push_back("-relaxed-aliasing"); + if (Args.hasFlag(options::OPT_fstrict_enums, options::OPT_fno_strict_enums, + false)) + CmdArgs.push_back("-fstrict-enums"); + if (!Args.hasFlag(options::OPT_foptimize_sibling_calls, + options::OPT_fno_optimize_sibling_calls)) + CmdArgs.push_back("-mdisable-tail-calls"); + + // Handle various floating point optimization flags, mapping them to the + // appropriate LLVM code generation flags. The pattern for all of these is to + // default off the codegen optimizations, and if any flag enables them and no + // flag disables them after the flag enabling them, enable the codegen + // optimization. This is complicated by several "umbrella" flags. + if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_ffinite_math_only, + options::OPT_fno_finite_math_only, + options::OPT_fhonor_infinities, + options::OPT_fno_honor_infinities)) + if (A->getOption().getID() != options::OPT_fno_finite_math_only && + A->getOption().getID() != options::OPT_fhonor_infinities) + CmdArgs.push_back("-menable-no-infs"); + if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_ffinite_math_only, + options::OPT_fno_finite_math_only, + options::OPT_fhonor_nans, + options::OPT_fno_honor_nans)) + if (A->getOption().getID() != options::OPT_fno_finite_math_only && + A->getOption().getID() != options::OPT_fhonor_nans) + CmdArgs.push_back("-menable-no-nans"); + + // -fno-math-errno is default. + bool MathErrno = false; + if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_fmath_errno, + options::OPT_fno_math_errno)) { + if (A->getOption().getID() == options::OPT_fmath_errno) { + CmdArgs.push_back("-fmath-errno"); + MathErrno = true; + } + } + + // There are several flags which require disabling very specific + // optimizations. Any of these being disabled forces us to turn off the + // entire set of LLVM optimizations, so collect them through all the flag + // madness. + bool AssociativeMath = false; + if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_funsafe_math_optimizations, + options::OPT_fno_unsafe_math_optimizations, + options::OPT_fassociative_math, + options::OPT_fno_associative_math)) + if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && + A->getOption().getID() != options::OPT_fno_associative_math) + AssociativeMath = true; + bool ReciprocalMath = false; + if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_funsafe_math_optimizations, + options::OPT_fno_unsafe_math_optimizations, + options::OPT_freciprocal_math, + options::OPT_fno_reciprocal_math)) + if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && + A->getOption().getID() != options::OPT_fno_reciprocal_math) + ReciprocalMath = true; + bool SignedZeros = true; + if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_funsafe_math_optimizations, + options::OPT_fno_unsafe_math_optimizations, + options::OPT_fsigned_zeros, + options::OPT_fno_signed_zeros)) + if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && + A->getOption().getID() != options::OPT_fsigned_zeros) + SignedZeros = false; + bool TrappingMath = true; + if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_funsafe_math_optimizations, + options::OPT_fno_unsafe_math_optimizations, + options::OPT_ftrapping_math, + options::OPT_fno_trapping_math)) + if (A->getOption().getID() != options::OPT_fno_unsafe_math_optimizations && + A->getOption().getID() != options::OPT_ftrapping_math) + TrappingMath = false; + if (!MathErrno && AssociativeMath && ReciprocalMath && !SignedZeros && + !TrappingMath) + CmdArgs.push_back("-menable-unsafe-fp-math"); + + // We separately look for the '-ffast-math' flag, and if we find it, tell the + // frontend to provide the appropriate preprocessor macros. This is distinct + // from enabling any optimizations as it induces a language change which must + // survive serialization and deserialization, etc. + if (Args.hasArg(options::OPT_ffast_math)) + CmdArgs.push_back("-ffast-math"); // Decide whether to use verbose asm. Verbose assembly is the default on // toolchains which have the integrated assembler on by default. @@ -1397,8 +1748,14 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, case llvm::Triple::x86_64: AddX86TargetArgs(Args, CmdArgs); break; + + case llvm::Triple::hexagon: + AddHexagonTargetArgs(Args, CmdArgs); + break; } + + // Pass the linker version in use. if (Arg *A = Args.getLastArg(options::OPT_mlinker_version_EQ)) { CmdArgs.push_back("-target-linker-version"); @@ -1411,21 +1768,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, !getToolChain().getTriple().isOSDarwin())) CmdArgs.push_back("-momit-leaf-frame-pointer"); - // -fno-math-errno is default. - if (Args.hasFlag(options::OPT_fmath_errno, - options::OPT_fno_math_errno, - false)) - CmdArgs.push_back("-fmath-errno"); - // Explicitly error on some things we know we don't support and can't just // ignore. types::ID InputType = Inputs[0].getType(); if (!Args.hasArg(options::OPT_fallow_unsupported)) { Arg *Unsupported; - if ((Unsupported = Args.getLastArg(options::OPT_iframework))) - D.Diag(diag::err_drv_clang_unsupported) - << Unsupported->getOption().getName(); - if (types::isCXX(InputType) && getToolChain().getTriple().isOSDarwin() && getToolChain().getTriple().getArch() == llvm::Triple::x86) { @@ -1456,8 +1803,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // wrong. Args.ClaimAllArgs(options::OPT_g_Group); if (Arg *A = Args.getLastArg(options::OPT_g_Group)) - if (!A->getOption().matches(options::OPT_g0)) + if (!A->getOption().matches(options::OPT_g0)) { CmdArgs.push_back("-g"); + } Args.AddAllArgs(CmdArgs, options::OPT_ffunction_sections); Args.AddAllArgs(CmdArgs, options::OPT_fdata_sections); @@ -1496,10 +1844,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_working_directory); + bool ARCMTEnabled = false; if (!Args.hasArg(options::OPT_fno_objc_arc)) { if (const Arg *A = Args.getLastArg(options::OPT_ccc_arcmt_check, options::OPT_ccc_arcmt_modify, options::OPT_ccc_arcmt_migrate)) { + ARCMTEnabled = true; switch (A->getOption().getID()) { default: llvm_unreachable("missed a case"); @@ -1511,7 +1861,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, break; case options::OPT_ccc_arcmt_migrate: CmdArgs.push_back("-arcmt-migrate"); - CmdArgs.push_back("-arcmt-migrate-directory"); + CmdArgs.push_back("-mt-migrate-directory"); CmdArgs.push_back(A->getValue(Args)); Args.AddLastArg(CmdArgs, options::OPT_arcmt_migrate_report_output); @@ -1521,12 +1871,31 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } + if (const Arg *A = Args.getLastArg(options::OPT_ccc_objcmt_migrate)) { + if (ARCMTEnabled) { + D.Diag(diag::err_drv_argument_not_allowed_with) + << A->getAsString(Args) << "-ccc-arcmt-migrate"; + } + CmdArgs.push_back("-mt-migrate-directory"); + CmdArgs.push_back(A->getValue(Args)); + + if (!Args.hasArg(options::OPT_objcmt_migrate_literals, + options::OPT_objcmt_migrate_subscripting)) { + // None specified, means enable them all. + CmdArgs.push_back("-objcmt-migrate-literals"); + CmdArgs.push_back("-objcmt-migrate-subscripting"); + } else { + Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_literals); + Args.AddLastArg(CmdArgs, options::OPT_objcmt_migrate_subscripting); + } + } + // Add preprocessing options like -I, -D, etc. if we are using the // preprocessor. // // FIXME: Support -fpreprocessed if (types::getPreprocessedType(InputType) != types::TY_INVALID) - AddPreprocessingOptions(D, Args, CmdArgs, Output, Inputs); + AddPreprocessingOptions(C, D, Args, CmdArgs, Output, Inputs); // Don't warn about "clang -c -DPIC -fPIC test.i" because libtool.m4 assumes // that "The compiler can only warn and ignore the option if not recognized". @@ -1611,11 +1980,30 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (ShouldDisableCFI(Args, getToolChain())) CmdArgs.push_back("-fno-dwarf2-cfi-asm"); - if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_)) { + if (ShouldDisableDwarfDirectory(Args, getToolChain())) + CmdArgs.push_back("-fno-dwarf-directory-asm"); + + if (const char *pwd = ::getenv("PWD")) { + // GCC also verifies that stat(pwd) and stat(".") have the same inode + // number. Not doing those because stats are slow, but we could. + if (llvm::sys::path::is_absolute(pwd)) { + std::string CompDir = pwd; + CmdArgs.push_back("-fdebug-compilation-dir"); + CmdArgs.push_back(Args.MakeArgString(CompDir)); + } + } + + if (Arg *A = Args.getLastArg(options::OPT_ftemplate_depth_, + options::OPT_ftemplate_depth_EQ)) { CmdArgs.push_back("-ftemplate-depth"); CmdArgs.push_back(A->getValue(Args)); } + if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_depth_EQ)) { + CmdArgs.push_back("-fconstexpr-depth"); + CmdArgs.push_back(A->getValue(Args)); + } + if (Arg *A = Args.getLastArg(options::OPT_Wlarge_by_value_copy_EQ, options::OPT_Wlarge_by_value_copy_def)) { CmdArgs.push_back("-Wlarge-by-value-copy"); @@ -1654,6 +2042,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue(Args)); } + if (Arg *A = Args.getLastArg(options::OPT_fconstexpr_backtrace_limit_EQ)) { + CmdArgs.push_back("-fconstexpr-backtrace-limit"); + CmdArgs.push_back(A->getValue(Args)); + } + // Pass -fmessage-length=. CmdArgs.push_back("-fmessage-length"); if (Arg *A = Args.getLastArg(options::OPT_fmessage_length_EQ)) { @@ -1673,9 +2066,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fvisibility_inlines_hidden); // -fhosted is default. - if (KernelOrKext || Args.hasFlag(options::OPT_ffreestanding, - options::OPT_fhosted, - false)) + if (Args.hasFlag(options::OPT_ffreestanding, options::OPT_fhosted, false) || + KernelOrKext) CmdArgs.push_back("-ffreestanding"); // Forward -f (flag) options which we can pass directly. @@ -1684,9 +2076,28 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_fformat_extensions); Args.AddLastArg(CmdArgs, options::OPT_fheinous_gnu_extensions); Args.AddLastArg(CmdArgs, options::OPT_flimit_debug_info); + Args.AddLastArg(CmdArgs, options::OPT_fno_limit_debug_info); + Args.AddLastArg(CmdArgs, options::OPT_fno_operator_names); + Args.AddLastArg(CmdArgs, options::OPT_faltivec); + + // Report and error for -faltivec on anything other then PowerPC. + if (const Arg *A = Args.getLastArg(options::OPT_faltivec)) + if (!(getToolChain().getTriple().getArch() == llvm::Triple::ppc || + getToolChain().getTriple().getArch() == llvm::Triple::ppc64)) + D.Diag(diag::err_drv_argument_only_allowed_with) + << A->getAsString(Args) << "ppc/ppc64"; + if (getToolChain().SupportsProfiling()) Args.AddLastArg(CmdArgs, options::OPT_pg); + if (Args.hasFlag(options::OPT_faddress_sanitizer, + options::OPT_fno_address_sanitizer, false)) + CmdArgs.push_back("-faddress-sanitizer"); + + if (Args.hasFlag(options::OPT_fthread_sanitizer, + options::OPT_fno_thread_sanitizer, false)) + CmdArgs.push_back("-fthread-sanitizer"); + // -flax-vector-conversions is default. if (!Args.hasFlag(options::OPT_flax_vector_conversions, options::OPT_fno_lax_vector_conversions)) @@ -1706,12 +2117,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back(A->getValue(Args)); } - // Forward -ftrap_function= options to the backend. - if (Arg *A = Args.getLastArg(options::OPT_ftrap_function_EQ)) { - StringRef FuncName = A->getValue(Args); - CmdArgs.push_back("-backend-option"); - CmdArgs.push_back(Args.MakeArgString("-trap-func=" + FuncName)); - } + Args.AddLastArg(CmdArgs, options::OPT_ftrap_function_EQ); // -fno-strict-overflow implies -fwrapv if it isn't disabled, but // -fstrict-overflow won't turn off an explicitly enabled -fwrapv. @@ -1748,10 +2154,20 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } // Translate -mstackrealign - if (Args.hasArg(options::OPT_mstackrealign)) { + if (Args.hasFlag(options::OPT_mstackrealign, options::OPT_mno_stackrealign, + false)) { CmdArgs.push_back("-backend-option"); CmdArgs.push_back("-force-align-stack"); } + if (!Args.hasFlag(options::OPT_mno_stackrealign, options::OPT_mstackrealign, + false)) { + CmdArgs.push_back(Args.MakeArgString("-mstackrealign")); + } + + if (Args.hasArg(options::OPT_mstack_alignment)) { + StringRef alignment = Args.getLastArgValue(options::OPT_mstack_alignment); + CmdArgs.push_back(Args.MakeArgString("-mstack-alignment=" + alignment)); + } // Forward -f options with positive and negative forms; we translate // these by hand. @@ -1761,6 +2177,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fapple-kext"); if (!Args.hasArg(options::OPT_fbuiltin)) CmdArgs.push_back("-fno-builtin"); + Args.ClaimAllArgs(options::OPT_fno_builtin); } // -fbuiltin is default. else if (!Args.hasFlag(options::OPT_fbuiltin, options::OPT_fno_builtin)) @@ -1783,6 +2200,17 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fblocks-runtime-optional"); } + // -fmodules enables modules (off by default). However, for C++/Objective-C++, + // users must also pass -fcxx-modules. The latter flag will disappear once the + // modules implementation is solid for C++/Objective-C++ programs as well. + if (Args.hasFlag(options::OPT_fmodules, options::OPT_fno_modules, false)) { + bool AllowedInCXX = Args.hasFlag(options::OPT_fcxx_modules, + options::OPT_fno_cxx_modules, + false); + if (AllowedInCXX || !types::isCXX(InputType)) + CmdArgs.push_back("-fmodules"); + } + // -faccess-control is default. if (Args.hasFlag(options::OPT_fno_access_control, options::OPT_faccess_control, @@ -1796,14 +2224,15 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fno-elide-constructors"); // -frtti is default. - if (KernelOrKext || - !Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti)) + if (!Args.hasFlag(options::OPT_frtti, options::OPT_fno_rtti) || + KernelOrKext) CmdArgs.push_back("-fno-rtti"); - // -fshort-enums=0 is default. - // FIXME: Are there targers where -fshort-enums is on by default ? + // -fshort-enums=0 is default for all architectures except Hexagon. if (Args.hasFlag(options::OPT_fshort_enums, - options::OPT_fno_short_enums, false)) + options::OPT_fno_short_enums, + getToolChain().getTriple().getArch() == + llvm::Triple::hexagon)) CmdArgs.push_back("-fshort-enums"); // -fsigned-char is default. @@ -1817,10 +2246,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fno-threadsafe-statics"); // -fuse-cxa-atexit is default. - if (KernelOrKext || - !Args.hasFlag(options::OPT_fuse_cxa_atexit, options::OPT_fno_use_cxa_atexit, - getToolChain().getTriple().getOS() != llvm::Triple::Cygwin && - getToolChain().getTriple().getOS() != llvm::Triple::MinGW32)) + if (!Args.hasFlag(options::OPT_fuse_cxa_atexit, + options::OPT_fno_use_cxa_atexit, + getToolChain().getTriple().getOS() != llvm::Triple::Cygwin && + getToolChain().getTriple().getOS() != llvm::Triple::MinGW32 && + getToolChain().getTriple().getArch() != llvm::Triple::hexagon) || + KernelOrKext) CmdArgs.push_back("-fno-use-cxa-atexit"); // -fms-extensions=0 is default. @@ -1829,8 +2260,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fms-extensions"); // -fms-compatibility=0 is default. - if (Args.hasFlag(options::OPT_fms_compatibility, options::OPT_fno_ms_compatibility, - getToolChain().getTriple().getOS() == llvm::Triple::Win32)) + if (Args.hasFlag(options::OPT_fms_compatibility, + options::OPT_fno_ms_compatibility, + (getToolChain().getTriple().getOS() == llvm::Triple::Win32 && + Args.hasFlag(options::OPT_fms_extensions, + options::OPT_fno_ms_extensions, + true)))) CmdArgs.push_back("-fms-compatibility"); // -fmsc-version=1300 is default. @@ -1868,11 +2303,18 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, false)) CmdArgs.push_back("-fgnu89-inline"); + if (Args.hasArg(options::OPT_fno_inline)) + CmdArgs.push_back("-fno-inline"); + + if (Args.hasArg(options::OPT_fno_inline_functions)) + CmdArgs.push_back("-fno-inline-functions"); + // -fobjc-nonfragile-abi=0 is default. ObjCRuntime objCRuntime; unsigned objcABIVersion = 0; bool NeXTRuntimeIsDefault - = (IsRewriter || getToolChain().getTriple().isOSDarwin()); + = (IsRewriter || IsModernRewriter || + getToolChain().getTriple().isOSDarwin()); if (Args.hasFlag(options::OPT_fnext_runtime, options::OPT_fgnu_runtime, NeXTRuntimeIsDefault)) { objCRuntime.setKind(ObjCRuntime::NeXT); @@ -1906,8 +2348,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, D.Diag(diag::err_drv_clang_unsupported) << A->getAsString(Args); } else { // Otherwise, determine if we are using the non-fragile ABI. - bool NonFragileABIIsDefault - = (!IsRewriter && getToolChain().IsObjCNonFragileABIDefault()); + bool NonFragileABIIsDefault = + (IsModernRewriter || + (!IsRewriter && getToolChain().IsObjCNonFragileABIDefault())); if (Args.hasFlag(options::OPT_fobjc_nonfragile_abi, options::OPT_fno_objc_nonfragile_abi, NonFragileABIIsDefault)) { @@ -1950,10 +2393,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, } } - // -fobjc-default-synthesize-properties=0 is default. - if (Args.hasFlag(options::OPT_fobjc_default_synthesize_properties, - options::OPT_fno_objc_default_synthesize_properties, - getToolChain().IsObjCDefaultSynthPropertiesDefault())) { + // -fobjc-default-synthesize-properties=1 is default. This only has an effect + // if the nonfragile objc abi is used. + if (getToolChain().IsObjCDefaultSynthPropertiesDefault()) { CmdArgs.push_back("-fobjc-default-synthesize-properties"); } @@ -1961,6 +2403,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // NOTE: This logic is duplicated in ToolChains.cpp. bool ARC = isObjCAutoRefCount(Args); if (ARC) { + if (!getToolChain().SupportsObjCARC()) + D.Diag(diag::err_arc_unsupported); + CmdArgs.push_back("-fobjc-arc"); // FIXME: It seems like this entire block, and several around it should be @@ -1983,7 +2428,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // -fobjc-infer-related-result-type is the default, except in the Objective-C // rewriter. - if (IsRewriter) + if (IsRewriter || IsModernRewriter) CmdArgs.push_back("-fno-objc-infer-related-result-type"); // Handle -fobjc-gc and -fobjc-gc-only. They are exclusive, and -fobjc-gc-only @@ -2006,7 +2451,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Add exception args. addExceptionArgs(Args, InputType, getToolChain().getTriple(), - KernelOrKext, IsRewriter, objcABIVersion, CmdArgs); + KernelOrKext, objcABIVersion, CmdArgs); if (getToolChain().UseSjLjExceptions()) CmdArgs.push_back("-fsjlj-exceptions"); @@ -2057,6 +2502,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.hasArg(options::OPT_fapple_kext)) { if (!Args.hasArg(options::OPT_fcommon)) CmdArgs.push_back("-fno-common"); + Args.ClaimAllArgs(options::OPT_fno_common); } // -fcommon is default, only pass non-default. @@ -2086,11 +2532,6 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, options::OPT_fno_diagnostics_fixit_info)) CmdArgs.push_back("-fno-diagnostics-fixit-info"); - // Enable -fdiagnostics-show-name by default. - if (Args.hasFlag(options::OPT_fdiagnostics_show_name, - options::OPT_fno_diagnostics_show_name, false)) - CmdArgs.push_back("-fdiagnostics-show-name"); - // Enable -fdiagnostics-show-option by default. if (Args.hasFlag(options::OPT_fdiagnostics_show_option, options::OPT_fno_diagnostics_show_option)) @@ -2164,6 +2605,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, D.Diag(diag::warn_drv_clang_unsupported) << A->getAsString(Args); } + if (Args.hasFlag(options::OPT_fapple_pragma_pack, + options::OPT_fno_apple_pragma_pack, false)) + CmdArgs.push_back("-fapple-pragma-pack"); + // Default to -fno-builtin-str{cat,cpy} on Darwin for ARM. // // FIXME: This is disabled until clang -cc1 supports -fno-builtin-foo. PR4941. @@ -2189,6 +2634,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.AddLastArg(CmdArgs, options::OPT_dM); Args.AddLastArg(CmdArgs, options::OPT_dD); + + // Handle serialized diagnostics. + if (Arg *A = Args.getLastArg(options::OPT__serialize_diags)) { + CmdArgs.push_back("-serialize-diagnostic-file"); + CmdArgs.push_back(Args.MakeArgString(A->getValue(Args))); + } // Forward -Xclang arguments to -cc1, and -mllvm arguments to the LLVM option // parser. @@ -2237,7 +2688,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, ie = Args.end(); it != ie; ++it) (*it)->render(Args, OriginalArgs); - llvm::SmallString<256> Flags; + SmallString<256> Flags; Flags += Exec; for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) { Flags += " "; @@ -2271,6 +2722,24 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, Args.ClaimAllArgs(options::OPT_emit_llvm); } +void ClangAs::AddARMTargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + const Driver &D = getToolChain().getDriver(); + llvm::Triple Triple = getToolChain().getTriple(); + + // Set the CPU based on -march= and -mcpu=. + CmdArgs.push_back("-target-cpu"); + CmdArgs.push_back(getARMTargetCPU(Args, Triple)); + + // Honor -mfpu=. + if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) + addFPUArgs(D, A, Args, CmdArgs); + + // Honor -mfpmath=. + if (const Arg *A = Args.getLastArg(options::OPT_mfpmath_EQ)) + addFPMathArgs(D, A, Args, CmdArgs, getARMTargetCPU(Args, Triple)); +} + void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -2307,10 +2776,54 @@ void ClangAs::ConstructJob(Compilation &C, const JobAction &JA, if (UseRelaxAll(C, Args)) CmdArgs.push_back("-relax-all"); + // Add target specific cpu and features flags. + switch(getToolChain().getTriple().getArch()) { + default: + break; + + case llvm::Triple::arm: + case llvm::Triple::thumb: + AddARMTargetArgs(Args, CmdArgs); + break; + } + // Ignore explicit -force_cpusubtype_ALL option. (void) Args.hasArg(options::OPT_force__cpusubtype__ALL); - // FIXME: Add -g support, once we have it. + // Determine the original source input. + const Action *SourceAction = &JA; + while (SourceAction->getKind() != Action::InputClass) { + assert(!SourceAction->getInputs().empty() && "unexpected root action!"); + SourceAction = SourceAction->getInputs()[0]; + } + + // Forward -g, assuming we are dealing with an actual assembly file. + if (SourceAction->getType() == types::TY_Asm || + SourceAction->getType() == types::TY_PP_Asm) { + Args.ClaimAllArgs(options::OPT_g_Group); + if (Arg *A = Args.getLastArg(options::OPT_g_Group)) + if (!A->getOption().matches(options::OPT_g0)) + CmdArgs.push_back("-g"); + } + + // Optionally embed the -cc1as level arguments into the debug info, for build + // analysis. + if (getToolChain().UseDwarfDebugFlags()) { + ArgStringList OriginalArgs; + for (ArgList::const_iterator it = Args.begin(), + ie = Args.end(); it != ie; ++it) + (*it)->render(Args, OriginalArgs); + + SmallString<256> Flags; + const char *Exec = getToolChain().getDriver().getClangProgramPath(); + Flags += Exec; + for (unsigned i = 0, e = OriginalArgs.size(); i != e; ++i) { + Flags += " "; + Flags += OriginalArgs[i]; + } + CmdArgs.push_back("-dwarf-debug-flags"); + CmdArgs.push_back(Args.MakeArgString(Flags.str())); + } // FIXME: Add -static support, once we have it. @@ -2389,6 +2902,8 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-fsyntax-only"); } + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, + options::OPT_Xassembler); // Only pass -x if gcc will understand it; otherwise hope gcc // understands the suffix correctly. The main use case this would go @@ -2437,12 +2952,7 @@ void gcc::Common::ConstructJob(Compilation &C, const JobAction &JA, if (!customGCCName.empty()) GCCName = customGCCName.c_str(); else if (D.CCCIsCXX) { -#ifdef IS_CYGWIN15 - // FIXME: Detect the version of Cygwin at runtime? - GCCName = "g++-4"; -#else GCCName = "g++"; -#endif } else GCCName = "gcc"; @@ -2488,6 +2998,155 @@ void gcc::Link::RenderExtraToolArgs(const JobAction &JA, // The types are (hopefully) good enough. } +// Hexagon tools start. +void hexagon::Assemble::RenderExtraToolArgs(const JobAction &JA, + ArgStringList &CmdArgs) const { + +} +void hexagon::Assemble::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + + const Driver &D = getToolChain().getDriver(); + ArgStringList CmdArgs; + + std::string MarchString = "-march="; + MarchString += getHexagonTargetCPU(Args); + CmdArgs.push_back(Args.MakeArgString(MarchString)); + + RenderExtraToolArgs(JA, CmdArgs); + + if (Output.isFilename()) { + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + } else { + assert(Output.isNothing() && "Unexpected output"); + CmdArgs.push_back("-fsyntax-only"); + } + + + // Only pass -x if gcc will understand it; otherwise hope gcc + // understands the suffix correctly. The main use case this would go + // wrong in is for linker inputs if they happened to have an odd + // suffix; really the only way to get this to happen is a command + // like '-x foobar a.c' which will treat a.c like a linker input. + // + // FIXME: For the linker case specifically, can we safely convert + // inputs into '-Wl,' options? + for (InputInfoList::const_iterator + it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { + const InputInfo &II = *it; + + // Don't try to pass LLVM or AST inputs to a generic gcc. + if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR || + II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC) + D.Diag(clang::diag::err_drv_no_linker_llvm_support) + << getToolChain().getTripleString(); + else if (II.getType() == types::TY_AST) + D.Diag(clang::diag::err_drv_no_ast_support) + << getToolChain().getTripleString(); + + if (II.isFilename()) + CmdArgs.push_back(II.getFilename()); + else + // Don't render as input, we need gcc to do the translations. FIXME: Pranav: What is this ? + II.getInputArg().render(Args, CmdArgs); + } + + const char *GCCName = "hexagon-as"; + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + +} +void hexagon::Link::RenderExtraToolArgs(const JobAction &JA, + ArgStringList &CmdArgs) const { + // The types are (hopefully) good enough. +} + +void hexagon::Link::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + + const Driver &D = getToolChain().getDriver(); + ArgStringList CmdArgs; + + for (ArgList::const_iterator + it = Args.begin(), ie = Args.end(); it != ie; ++it) { + Arg *A = *it; + if (A->getOption().hasForwardToGCC()) { + // Don't forward any -g arguments to assembly steps. + if (isa<AssembleJobAction>(JA) && + A->getOption().matches(options::OPT_g_Group)) + continue; + + // It is unfortunate that we have to claim here, as this means + // we will basically never report anything interesting for + // platforms using a generic gcc, even if we are just using gcc + // to get to the assembler. + A->claim(); + A->render(Args, CmdArgs); + } + } + + RenderExtraToolArgs(JA, CmdArgs); + + // Add Arch Information + Arg *A; + if ((A = getLastHexagonArchArg(Args))) { + if (A->getOption().matches(options::OPT_m_Joined)) + A->render(Args, CmdArgs); + else + CmdArgs.push_back (Args.MakeArgString("-m" + getHexagonTargetCPU(Args))); + } + else { + CmdArgs.push_back (Args.MakeArgString("-m" + getHexagonTargetCPU(Args))); + } + + CmdArgs.push_back("-mqdsp6-compat"); + + const char *GCCName; + if (C.getDriver().CCCIsCXX) + GCCName = "hexagon-g++"; + else + GCCName = "hexagon-gcc"; + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath(GCCName)); + + if (Output.isFilename()) { + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + } + + for (InputInfoList::const_iterator + it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { + const InputInfo &II = *it; + + // Don't try to pass LLVM or AST inputs to a generic gcc. + if (II.getType() == types::TY_LLVM_IR || II.getType() == types::TY_LTO_IR || + II.getType() == types::TY_LLVM_BC || II.getType() == types::TY_LTO_BC) + D.Diag(clang::diag::err_drv_no_linker_llvm_support) + << getToolChain().getTripleString(); + else if (II.getType() == types::TY_AST) + D.Diag(clang::diag::err_drv_no_ast_support) + << getToolChain().getTripleString(); + + if (II.isFilename()) + CmdArgs.push_back(II.getFilename()); + else + // Don't render as input, we need gcc to do the translations. FIXME: Pranav: What is this ? + II.getInputArg().render(Args, CmdArgs); + } + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); + +} +// Hexagon tools end. + + const char *darwin::CC1::getCC1Name(types::ID Type) const { switch (Type) { default: @@ -2510,6 +3169,8 @@ const char *darwin::CC1::getCC1Name(types::ID Type) const { } } +void darwin::CC1::anchor() {} + const char *darwin::CC1::getBaseInputName(const ArgList &Args, const InputInfoList &Inputs) { return Args.MakeArgString( @@ -2548,13 +3209,27 @@ void darwin::CC1::RemoveCC1UnsupportedArgs(ArgStringList &CmdArgs) const { StringRef Option = *it; bool RemoveOption = false; - // Remove -faltivec - if (Option.equals("-faltivec")) { - it = CmdArgs.erase(it); + // Erase both -fmodule-cache-path and its argument. + if (Option.equals("-fmodule-cache-path") && it+2 != ie) { + it = CmdArgs.erase(it, it+2); ie = CmdArgs.end(); continue; } + // Remove unsupported -f options. + if (Option.startswith("-f")) { + // Remove -f/-fno- to reduce the number of cases. + if (Option.startswith("-fno-")) + Option = Option.substr(5); + else + Option = Option.substr(2); + RemoveOption = llvm::StringSwitch<bool>(Option) + .Case("altivec", true) + .Case("modules", true) + .Case("diagnostics-show-note-include-stack", true) + .Default(false); + } + // Handle machine specific options. if (Option.startswith("-m")) { RemoveOption = llvm::StringSwitch<bool>(Option) @@ -2595,6 +3270,7 @@ void darwin::CC1::RemoveCC1UnsupportedArgs(ArgStringList &CmdArgs) const { .Case("c++11-narrowing", true) .Case("conditional-uninitialized", true) .Case("constant-conversion", true) + .Case("conversion-null", true) .Case("CFString-literal", true) .Case("constant-logical-operand", true) .Case("custom-atomic-properties", true) @@ -3000,9 +3676,11 @@ void darwin::Compile::ConstructJob(Compilation &C, const JobAction &JA, assert(Inputs.size() == 1 && "Unexpected number of inputs!"); + // Silence warning about unused --serialize-diagnostics + Args.ClaimAllArgs(options::OPT__serialize_diags); + types::ID InputType = Inputs[0].getType(); - const Arg *A; - if ((A = Args.getLastArg(options::OPT_traditional))) + if (const Arg *A = Args.getLastArg(options::OPT_traditional)) D.Diag(diag::err_drv_argument_only_allowed_with) << A->getAsString(Args) << "-E"; @@ -3119,7 +3797,7 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_gstabs)) CmdArgs.push_back("--gstabs"); else if (Args.hasArg(options::OPT_g_Group)) - CmdArgs.push_back("--gdwarf2"); + CmdArgs.push_back("-g"); } // Derived from asm spec. @@ -3154,6 +3832,8 @@ void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } +void darwin::DarwinTool::anchor() {} + void darwin::DarwinTool::AddDarwinArch(const ArgList &Args, ArgStringList &CmdArgs) const { StringRef ArchName = getDarwinToolChain().getDarwinArchName(Args); @@ -3185,13 +3865,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, // Newer linkers support -demangle, pass it if supported and not disabled by // the user. - // - // FIXME: We temporarily avoid passing -demangle to any iOS linker, because - // unfortunately we can't be guaranteed that the linker version used there - // will match the linker version detected at configure time. We need the - // universal driver. - if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle) && - !DarwinTC.isTargetIPhoneOS()) { + if (Version[0] >= 100 && !Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) { // Don't pass -demangle to ld_classic. // // FIXME: This is a temporary workaround, ld should be handling this. @@ -3291,8 +3965,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, Args.AddAllArgs(CmdArgs, options::OPT_init); // Add the deployment target. - unsigned TargetVersion[3]; - DarwinTC.getTargetVersion(TargetVersion); + VersionTuple TargetVersion = DarwinTC.getTargetVersion(); // If we had an explicit -mios-simulator-version-min argument, honor that, // otherwise use the traditional deployment targets. We can't just check the @@ -3307,9 +3980,7 @@ void darwin::Link::AddLinkArgs(Compilation &C, CmdArgs.push_back("-iphoneos_version_min"); else CmdArgs.push_back("-macosx_version_min"); - CmdArgs.push_back(Args.MakeArgString(Twine(TargetVersion[0]) + "." + - Twine(TargetVersion[1]) + "." + - Twine(TargetVersion[2]))); + CmdArgs.push_back(Args.MakeArgString(TargetVersion.getAsString())); Args.AddLastArg(CmdArgs, options::OPT_nomultidefs); Args.AddLastArg(CmdArgs, options::OPT_multi__module); @@ -3492,7 +4163,7 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("-lcrt1.o"); else if (getDarwinToolChain().isMacosxVersionLT(10, 6)) CmdArgs.push_back("-lcrt1.10.5.o"); - else + else if (getDarwinToolChain().isMacosxVersionLT(10, 8)) CmdArgs.push_back("-lcrt1.10.6.o"); // darwin_crt2 spec is empty. @@ -3513,20 +4184,42 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, Args.AddAllArgs(CmdArgs, options::OPT_L); + // If we're building a dynamic lib with -faddress-sanitizer, unresolved + // symbols may appear. Mark all of them as dynamic_lookup. + // Linking executables is handled in lib/Driver/ToolChains.cpp. + if (Args.hasFlag(options::OPT_faddress_sanitizer, + options::OPT_fno_address_sanitizer, false)) { + if (Args.hasArg(options::OPT_dynamiclib) || + Args.hasArg(options::OPT_bundle)) { + CmdArgs.push_back("-undefined"); + CmdArgs.push_back("dynamic_lookup"); + } + } + if (Args.hasArg(options::OPT_fopenmp)) // This is more complicated in gcc... CmdArgs.push_back("-lgomp"); getDarwinToolChain().AddLinkSearchPathArgs(Args, CmdArgs); - // In ARC, if we don't have runtime support, link in the runtime - // stubs. We have to do this *before* adding any of the normal - // linker inputs so that its initializer gets run first. - if (isObjCAutoRefCount(Args)) { - ObjCRuntime runtime; - getDarwinToolChain().configureObjCRuntime(runtime); - if (!runtime.HasARC) - getDarwinToolChain().AddLinkARCArgs(Args, CmdArgs); + if (isObjCRuntimeLinked(Args)) { + // Avoid linking compatibility stubs on i386 mac. + if (!getDarwinToolChain().isTargetMacOS() || + getDarwinToolChain().getArchName() != "i386") { + // If we don't have ARC or subscripting runtime support, link in the + // runtime stubs. We have to do this *before* adding any of the normal + // linker inputs so that its initializer gets run first. + ObjCRuntime runtime; + getDarwinToolChain().configureObjCRuntime(runtime); + // We use arclite library for both ARC and subscripting support. + if ((!runtime.HasARC && isObjCAutoRefCount(Args)) || + !runtime.HasSubscripting) + getDarwinToolChain().AddLinkARCArgs(Args, CmdArgs); + CmdArgs.push_back("-framework"); + CmdArgs.push_back("Foundation"); + } + // Link libobj. + CmdArgs.push_back("-lobjc"); } AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); @@ -3557,8 +4250,6 @@ void darwin::Link::ConstructJob(Compilation &C, const JobAction &JA, // endfile_spec is empty. } - addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); - Args.AddAllArgs(CmdArgs, options::OPT_T_Group); Args.AddAllArgs(CmdArgs, options::OPT_F); @@ -3618,6 +4309,9 @@ void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, const char *LinkingOutput) const { ArgStringList CmdArgs; CmdArgs.push_back("--verify"); + CmdArgs.push_back("--debug-info"); + CmdArgs.push_back("--eh-frame"); + CmdArgs.push_back("--quiet"); assert(Inputs.size() == 1 && "Unable to handle multiple inputs."); const InputInfo &Input = Inputs[0]; @@ -3631,6 +4325,137 @@ void darwin::VerifyDebug::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } +void solaris::Assemble::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + ArgStringList CmdArgs; + + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, + options::OPT_Xassembler); + + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + + for (InputInfoList::const_iterator + it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { + const InputInfo &II = *it; + CmdArgs.push_back(II.getFilename()); + } + + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath("as")); + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); +} + + +void solaris::Link::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + // FIXME: Find a real GCC, don't hard-code versions here + std::string GCCLibPath = "/usr/gcc/4.5/lib/gcc/"; + const llvm::Triple &T = getToolChain().getTriple(); + std::string LibPath = "/usr/lib/"; + llvm::Triple::ArchType Arch = T.getArch(); + switch (Arch) { + case llvm::Triple::x86: + GCCLibPath += ("i386-" + T.getVendorName() + "-" + + T.getOSName()).str() + "/4.5.2/"; + break; + case llvm::Triple::x86_64: + GCCLibPath += ("i386-" + T.getVendorName() + "-" + + T.getOSName()).str(); + GCCLibPath += "/4.5.2/amd64/"; + LibPath += "amd64/"; + break; + default: + assert(0 && "Unsupported architecture"); + } + + ArgStringList CmdArgs; + + // Demangle C++ names in errors + CmdArgs.push_back("-C"); + + if ((!Args.hasArg(options::OPT_nostdlib)) && + (!Args.hasArg(options::OPT_shared))) { + CmdArgs.push_back("-e"); + CmdArgs.push_back("_start"); + } + + if (Args.hasArg(options::OPT_static)) { + CmdArgs.push_back("-Bstatic"); + CmdArgs.push_back("-dn"); + } else { + CmdArgs.push_back("-Bdynamic"); + if (Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back("-shared"); + } else { + CmdArgs.push_back("--dynamic-linker"); + CmdArgs.push_back(Args.MakeArgString(LibPath + "ld.so.1")); + } + } + + if (Output.isFilename()) { + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + } else { + assert(Output.isNothing() && "Invalid output."); + } + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + if (!Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back(Args.MakeArgString(LibPath + "crt1.o")); + CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o")); + CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o")); + CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o")); + } else { + CmdArgs.push_back(Args.MakeArgString(LibPath + "crti.o")); + CmdArgs.push_back(Args.MakeArgString(LibPath + "values-Xa.o")); + CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtbegin.o")); + } + if (getToolChain().getDriver().CCCIsCXX) + CmdArgs.push_back(Args.MakeArgString(LibPath + "cxa_finalize.o")); + } + + CmdArgs.push_back(Args.MakeArgString("-L" + GCCLibPath)); + + Args.AddAllArgs(CmdArgs, options::OPT_L); + Args.AddAllArgs(CmdArgs, options::OPT_T_Group); + Args.AddAllArgs(CmdArgs, options::OPT_e); + Args.AddAllArgs(CmdArgs, options::OPT_r); + + AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + if (getToolChain().getDriver().CCCIsCXX) + getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); + CmdArgs.push_back("-lgcc_s"); + if (!Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back("-lgcc"); + CmdArgs.push_back("-lc"); + CmdArgs.push_back("-lm"); + } + } + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + CmdArgs.push_back(Args.MakeArgString(GCCLibPath + "crtend.o")); + } + CmdArgs.push_back(Args.MakeArgString(LibPath + "crtn.o")); + + addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); + + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath("ld")); + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); +} + void auroraux::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -3806,8 +4631,12 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { if (!Args.hasArg(options::OPT_shared)) { - CmdArgs.push_back(Args.MakeArgString( - getToolChain().GetFilePath("crt0.o"))); + if (Args.hasArg(options::OPT_pg)) + CmdArgs.push_back(Args.MakeArgString( + getToolChain().GetFilePath("gcrt0.o"))); + else + CmdArgs.push_back(Args.MakeArgString( + getToolChain().GetFilePath("crt0.o"))); CmdArgs.push_back(Args.MakeArgString( getToolChain().GetFilePath("crtbegin.o"))); } else { @@ -3832,7 +4661,10 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, !Args.hasArg(options::OPT_nodefaultlibs)) { if (D.CCCIsCXX) { getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); - CmdArgs.push_back("-lm"); + if (Args.hasArg(options::OPT_pg)) + CmdArgs.push_back("-lm_p"); + else + CmdArgs.push_back("-lm"); } // FIXME: For some reason GCC passes -lgcc before adding @@ -3841,8 +4673,12 @@ void openbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_pthread)) CmdArgs.push_back("-lpthread"); - if (!Args.hasArg(options::OPT_shared)) - CmdArgs.push_back("-lc"); + if (!Args.hasArg(options::OPT_shared)) { + if (Args.hasArg(options::OPT_pg)) + CmdArgs.push_back("-lc_p"); + else + CmdArgs.push_back("-lc"); + } CmdArgs.push_back("-lgcc"); } @@ -4062,11 +4898,9 @@ void netbsd::Assemble::ConstructJob(Compilation &C, const JobAction &JA, // When building 32-bit code on NetBSD/amd64, we have to explicitly // instruct as in the base system to assemble 32-bit code. - if (ToolTriple.getArch() == llvm::Triple::x86_64 && - getToolChain().getArch() == llvm::Triple::x86) + if (getToolChain().getArch() == llvm::Triple::x86) CmdArgs.push_back("--32"); - // Set byte order explicitly if (getToolChain().getArchName() == "mips") CmdArgs.push_back("-EB"); @@ -4116,8 +4950,7 @@ void netbsd::Link::ConstructJob(Compilation &C, const JobAction &JA, // When building 32-bit code on NetBSD/amd64, we have to explicitly // instruct ld in the base system to link 32-bit code. - if (ToolTriple.getArch() == llvm::Triple::x86_64 && - getToolChain().getArch() == llvm::Triple::x86) { + if (getToolChain().getArch() == llvm::Triple::x86) { CmdArgs.push_back("-m"); CmdArgs.push_back("elf_i386"); } @@ -4218,12 +5051,49 @@ void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("--32"); } else if (getToolChain().getArch() == llvm::Triple::x86_64) { CmdArgs.push_back("--64"); + } else if (getToolChain().getArch() == llvm::Triple::ppc) { + CmdArgs.push_back("-a32"); + CmdArgs.push_back("-mppc"); + CmdArgs.push_back("-many"); + } else if (getToolChain().getArch() == llvm::Triple::ppc64) { + CmdArgs.push_back("-a64"); + CmdArgs.push_back("-mppc64"); + CmdArgs.push_back("-many"); } else if (getToolChain().getArch() == llvm::Triple::arm) { StringRef MArch = getToolChain().getArchName(); if (MArch == "armv7" || MArch == "armv7a" || MArch == "armv7-a") CmdArgs.push_back("-mfpu=neon"); + } else if (getToolChain().getArch() == llvm::Triple::mips || + getToolChain().getArch() == llvm::Triple::mipsel || + getToolChain().getArch() == llvm::Triple::mips64 || + getToolChain().getArch() == llvm::Triple::mips64el) { + StringRef CPUName; + StringRef ABIName; + getMipsCPUAndABI(Args, getToolChain(), CPUName, ABIName); + + CmdArgs.push_back("-march"); + CmdArgs.push_back(CPUName.data()); + + // Convert ABI name to the GNU tools acceptable variant. + if (ABIName == "o32") + ABIName = "32"; + else if (ABIName == "n64") + ABIName = "64"; + + CmdArgs.push_back("-mabi"); + CmdArgs.push_back(ABIName.data()); + + if (getToolChain().getArch() == llvm::Triple::mips || + getToolChain().getArch() == llvm::Triple::mips64) + CmdArgs.push_back("-EB"); + else + CmdArgs.push_back("-EL"); } + Args.AddLastArg(CmdArgs, options::OPT_march_EQ); + Args.AddLastArg(CmdArgs, options::OPT_mcpu_EQ); + Args.AddLastArg(CmdArgs, options::OPT_mfpu_EQ); + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); @@ -4241,6 +5111,30 @@ void linuxtools::Assemble::ConstructJob(Compilation &C, const JobAction &JA, C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } +static void AddLibgcc(const Driver &D, ArgStringList &CmdArgs, + const ArgList &Args) { + bool StaticLibgcc = Args.hasArg(options::OPT_static) || + Args.hasArg(options::OPT_static_libgcc); + if (!D.CCCIsCXX) + CmdArgs.push_back("-lgcc"); + + if (StaticLibgcc) { + if (D.CCCIsCXX) + CmdArgs.push_back("-lgcc"); + } else { + if (!D.CCCIsCXX) + CmdArgs.push_back("--as-needed"); + CmdArgs.push_back("-lgcc_s"); + if (!D.CCCIsCXX) + CmdArgs.push_back("--no-as-needed"); + } + + if (StaticLibgcc) + CmdArgs.push_back("-lgcc_eh"); + else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX) + CmdArgs.push_back("-lgcc"); +} + void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -4290,6 +5184,14 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("elf32ppclinux"); else if (ToolChain.getArch() == llvm::Triple::ppc64) CmdArgs.push_back("elf64ppc"); + else if (ToolChain.getArch() == llvm::Triple::mips) + CmdArgs.push_back("elf32btsmip"); + else if (ToolChain.getArch() == llvm::Triple::mipsel) + CmdArgs.push_back("elf32ltsmip"); + else if (ToolChain.getArch() == llvm::Triple::mips64) + CmdArgs.push_back("elf64btsmip"); + else if (ToolChain.getArch() == llvm::Triple::mips64el) + CmdArgs.push_back("elf64ltsmip"); else CmdArgs.push_back("elf_x86_64"); @@ -4313,6 +5215,12 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, else if (ToolChain.getArch() == llvm::Triple::arm || ToolChain.getArch() == llvm::Triple::thumb) CmdArgs.push_back("/lib/ld-linux.so.3"); + else if (ToolChain.getArch() == llvm::Triple::mips || + ToolChain.getArch() == llvm::Triple::mipsel) + CmdArgs.push_back("/lib/ld.so.1"); + else if (ToolChain.getArch() == llvm::Triple::mips64 || + ToolChain.getArch() == llvm::Triple::mips64el) + CmdArgs.push_back("/lib64/ld.so.1"); else if (ToolChain.getArch() == llvm::Triple::ppc) CmdArgs.push_back("/lib/ld.so.1"); else if (ToolChain.getArch() == llvm::Triple::ppc64) @@ -4356,35 +5264,36 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, i != e; ++i) CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i)); + // Tell the linker to load the plugin. This has to come before AddLinkerInputs + // as gold requires -plugin to come before any -plugin-opt that -Wl might + // forward. + if (D.IsUsingLTO(Args) || Args.hasArg(options::OPT_use_gold_plugin)) { + CmdArgs.push_back("-plugin"); + std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so"; + CmdArgs.push_back(Args.MakeArgString(Plugin)); + } + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs); if (D.CCCIsCXX && !Args.hasArg(options::OPT_nostdlib)) { + bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && + !Args.hasArg(options::OPT_static); + if (OnlyLibstdcxxStatic) + CmdArgs.push_back("-Bstatic"); ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); + if (OnlyLibstdcxxStatic) + CmdArgs.push_back("-Bdynamic"); CmdArgs.push_back("-lm"); } + // Call this before we add the C run-time. + addAsanRTLinux(getToolChain(), Args, CmdArgs); + if (!Args.hasArg(options::OPT_nostdlib)) { if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("--start-group"); - if (!D.CCCIsCXX) - CmdArgs.push_back("-lgcc"); - - if (Args.hasArg(options::OPT_static)) { - if (D.CCCIsCXX) - CmdArgs.push_back("-lgcc"); - } else { - if (!D.CCCIsCXX) - CmdArgs.push_back("--as-needed"); - CmdArgs.push_back("-lgcc_s"); - if (!D.CCCIsCXX) - CmdArgs.push_back("--no-as-needed"); - } - - if (Args.hasArg(options::OPT_static)) - CmdArgs.push_back("-lgcc_eh"); - else if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX) - CmdArgs.push_back("-lgcc"); + AddLibgcc(D, CmdArgs, Args); if (Args.hasArg(options::OPT_pthread) || Args.hasArg(options::OPT_pthreads)) @@ -4394,19 +5303,8 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("--end-group"); - else { - if (!D.CCCIsCXX) - CmdArgs.push_back("-lgcc"); - - if (!D.CCCIsCXX) - CmdArgs.push_back("--as-needed"); - CmdArgs.push_back("-lgcc_s"); - if (!D.CCCIsCXX) - CmdArgs.push_back("--no-as-needed"); - - if (!Args.hasArg(options::OPT_shared) && D.CCCIsCXX) - CmdArgs.push_back("-lgcc"); - } + else + AddLibgcc(D, CmdArgs, Args); if (!Args.hasArg(options::OPT_nostartfiles)) { @@ -4423,12 +5321,6 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); - if (Args.hasArg(options::OPT_use_gold_plugin)) { - CmdArgs.push_back("-plugin"); - std::string Plugin = ToolChain.getDriver().Dir + "/../lib/LLVMgold.so"; - CmdArgs.push_back(Args.MakeArgString(Plugin)); - } - C.addCommand(new Command(JA, *this, ToolChain.Linker.c_str(), CmdArgs)); } @@ -4452,7 +5344,7 @@ void minix::Assemble::ConstructJob(Compilation &C, const JobAction &JA, } const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("gas")); + Args.MakeArgString(getToolChain().GetProgramPath("as")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } @@ -4472,9 +5364,12 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA, } if (!Args.hasArg(options::OPT_nostdlib) && - !Args.hasArg(options::OPT_nostartfiles)) - CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath( - "/usr/gnu/lib/crtso.o"))); + !Args.hasArg(options::OPT_nostartfiles)) { + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crt1.o"))); + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crti.o"))); + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtbegin.o"))); + CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath("crtn.o"))); + } Args.AddAllArgs(CmdArgs, options::OPT_L); Args.AddAllArgs(CmdArgs, options::OPT_T_Group); @@ -4482,33 +5377,28 @@ void minix::Link::ConstructJob(Compilation &C, const JobAction &JA, AddLinkerInputs(getToolChain(), Inputs, Args, CmdArgs); + addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); + if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nodefaultlibs)) { if (D.CCCIsCXX) { getToolChain().AddCXXStdlibLibArgs(Args, CmdArgs); CmdArgs.push_back("-lm"); } - - if (Args.hasArg(options::OPT_pthread)) - CmdArgs.push_back("-lpthread"); - CmdArgs.push_back("-lc"); - CmdArgs.push_back("-lgcc"); - CmdArgs.push_back("-L/usr/gnu/lib"); - // FIXME: fill in the correct search path for the final - // support libraries. - CmdArgs.push_back("-L/usr/gnu/lib/gcc/i686-pc-minix/4.4.3"); } if (!Args.hasArg(options::OPT_nostdlib) && !Args.hasArg(options::OPT_nostartfiles)) { - CmdArgs.push_back(Args.MakeArgString(getToolChain().GetFilePath( - "/usr/gnu/lib/libend.a"))); + if (Args.hasArg(options::OPT_pthread)) + CmdArgs.push_back("-lpthread"); + CmdArgs.push_back("-lc"); + CmdArgs.push_back("-lCompilerRT-Generic"); + CmdArgs.push_back("-L/usr/pkg/compiler-rt/lib"); + CmdArgs.push_back( + Args.MakeArgString(getToolChain().GetFilePath("crtend.o"))); } - addProfileRT(getToolChain(), Args, CmdArgs, getToolChain().getTriple()); - - const char *Exec = - Args.MakeArgString(getToolChain().GetProgramPath("/usr/gnu/bin/gld")); + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("ld")); C.addCommand(new Command(JA, *this, Exec, CmdArgs)); } diff --git a/contrib/llvm/tools/clang/lib/Driver/Tools.h b/contrib/llvm/tools/clang/lib/Driver/Tools.h index a4f732e..651a8f2 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Tools.h +++ b/contrib/llvm/tools/clang/lib/Driver/Tools.h @@ -29,7 +29,8 @@ namespace tools { /// \brief Clang compiler tool. class LLVM_LIBRARY_VISIBILITY Clang : public Tool { - void AddPreprocessingOptions(const Driver &D, + void AddPreprocessingOptions(Compilation &C, + const Driver &D, const ArgList &Args, ArgStringList &CmdArgs, const InputInfo &Output, @@ -40,6 +41,7 @@ namespace tools { void AddMIPSTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const; void AddSparcTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const; void AddX86TargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const; + void AddHexagonTargetArgs (const ArgList &Args, ArgStringList &CmdArgs) const; public: Clang(const ToolChain &TC) : Tool("clang", "clang frontend", TC) {} @@ -57,6 +59,7 @@ namespace tools { /// \brief Clang integrated assembler tool. class LLVM_LIBRARY_VISIBILITY ClangAs : public Tool { + void AddARMTargetArgs(const ArgList &Args, ArgStringList &CmdArgs) const; public: ClangAs(const ToolChain &TC) : Tool("clang::as", "clang integrated assembler", TC) {} @@ -145,14 +148,54 @@ namespace gcc { "linker (via gcc)", TC) {} virtual bool hasIntegratedCPP() const { return false; } + virtual bool isLinkJob() const { return true; } virtual void RenderExtraToolArgs(const JobAction &JA, ArgStringList &CmdArgs) const; }; } // end namespace gcc +namespace hexagon { + // For Hexagon, we do not need to instantiate tools for PreProcess, PreCompile and Compile. + // We simply use "clang -cc1" for those actions. + class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { + public: + Assemble(const ToolChain &TC) : Tool("hexagon::Assemble", + "hexagon-as", TC) {} + + virtual bool hasIntegratedCPP() const { return false; } + + virtual void RenderExtraToolArgs(const JobAction &JA, + ArgStringList &CmdArgs) const; + virtual void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &TCArgs, + const char *LinkingOutput) const; + }; + + class LLVM_LIBRARY_VISIBILITY Link : public Tool { + public: + Link(const ToolChain &TC) : Tool("hexagon::Link", + "hexagon-ld", TC) {} + + virtual bool hasIntegratedCPP() const { return false; } + virtual bool isLinkJob() const { return true; } + + virtual void RenderExtraToolArgs(const JobAction &JA, + ArgStringList &CmdArgs) const; + virtual void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &TCArgs, + const char *LinkingOutput) const; + }; +} // end namespace hexagon. + + namespace darwin { class LLVM_LIBRARY_VISIBILITY DarwinTool : public Tool { + virtual void anchor(); protected: void AddDarwinArch(const ArgList &Args, ArgStringList &CmdArgs) const; @@ -166,6 +209,7 @@ namespace darwin { }; class LLVM_LIBRARY_VISIBILITY CC1 : public DarwinTool { + virtual void anchor(); public: static const char *getBaseInputName(const ArgList &Args, const InputInfoList &Input); @@ -243,6 +287,7 @@ namespace darwin { Link(const ToolChain &TC) : DarwinTool("darwin::Link", "linker", TC) {} virtual bool hasIntegratedCPP() const { return false; } + virtual bool isLinkJob() const { return true; } virtual void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, @@ -314,6 +359,7 @@ namespace openbsd { Link(const ToolChain &TC) : Tool("openbsd::Link", "linker", TC) {} virtual bool hasIntegratedCPP() const { return false; } + virtual bool isLinkJob() const { return true; } virtual void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, @@ -343,6 +389,7 @@ namespace freebsd { Link(const ToolChain &TC) : Tool("freebsd::Link", "linker", TC) {} virtual bool hasIntegratedCPP() const { return false; } + virtual bool isLinkJob() const { return true; } virtual void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, @@ -355,12 +402,10 @@ namespace freebsd { /// netbsd -- Directly call GNU Binutils assembler and linker namespace netbsd { class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { - private: - const llvm::Triple ToolTriple; public: - Assemble(const ToolChain &TC, const llvm::Triple &ToolTriple) - : Tool("netbsd::Assemble", "assembler", TC), ToolTriple(ToolTriple) {} + Assemble(const ToolChain &TC) + : Tool("netbsd::Assemble", "assembler", TC) {} virtual bool hasIntegratedCPP() const { return false; } @@ -371,14 +416,13 @@ namespace netbsd { const char *LinkingOutput) const; }; class LLVM_LIBRARY_VISIBILITY Link : public Tool { - private: - const llvm::Triple ToolTriple; public: - Link(const ToolChain &TC, const llvm::Triple &ToolTriple) - : Tool("netbsd::Link", "linker", TC), ToolTriple(ToolTriple) {} + Link(const ToolChain &TC) + : Tool("netbsd::Link", "linker", TC) {} virtual bool hasIntegratedCPP() const { return false; } + virtual bool isLinkJob() const { return true; } virtual void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, @@ -408,6 +452,7 @@ namespace linuxtools { Link(const ToolChain &TC) : Tool("linux::Link", "linker", TC) {} virtual bool hasIntegratedCPP() const { return false; } + virtual bool isLinkJob() const { return true; } virtual void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, @@ -436,6 +481,7 @@ namespace minix { Link(const ToolChain &TC) : Tool("minix::Link", "linker", TC) {} virtual bool hasIntegratedCPP() const { return false; } + virtual bool isLinkJob() const { return true; } virtual void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, @@ -445,6 +491,36 @@ namespace minix { }; } // end namespace minix + /// solaris -- Directly call Solaris assembler and linker +namespace solaris { + class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { + public: + Assemble(const ToolChain &TC) : Tool("solaris::Assemble", "assembler", + TC) {} + + virtual bool hasIntegratedCPP() const { return false; } + + virtual void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &TCArgs, + const char *LinkingOutput) const; + }; + class LLVM_LIBRARY_VISIBILITY Link : public Tool { + public: + Link(const ToolChain &TC) : Tool("solaris::Link", "linker", TC) {} + + virtual bool hasIntegratedCPP() const { return false; } + virtual bool isLinkJob() const { return true; } + + virtual void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &TCArgs, + const char *LinkingOutput) const; + }; +} // end namespace solaris + /// auroraux -- Directly call GNU Binutils assembler and linker namespace auroraux { class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { @@ -465,6 +541,7 @@ namespace auroraux { Link(const ToolChain &TC) : Tool("auroraux::Link", "linker", TC) {} virtual bool hasIntegratedCPP() const { return false; } + virtual bool isLinkJob() const { return true; } virtual void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, @@ -494,6 +571,7 @@ namespace dragonfly { Link(const ToolChain &TC) : Tool("dragonfly::Link", "linker", TC) {} virtual bool hasIntegratedCPP() const { return false; } + virtual bool isLinkJob() const { return true; } virtual void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, @@ -510,6 +588,7 @@ namespace visualstudio { Link(const ToolChain &TC) : Tool("visualstudio::Link", "linker", TC) {} virtual bool hasIntegratedCPP() const { return false; } + virtual bool isLinkJob() const { return true; } virtual void ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, diff --git a/contrib/llvm/tools/clang/lib/Driver/Types.cpp b/contrib/llvm/tools/clang/lib/Driver/Types.cpp index d61ab68..50742fe 100644 --- a/contrib/llvm/tools/clang/lib/Driver/Types.cpp +++ b/contrib/llvm/tools/clang/lib/Driver/Types.cpp @@ -102,6 +102,7 @@ bool types::isOnlyAcceptedByClang(ID Id) { case TY_LLVM_IR: case TY_LLVM_BC: case TY_RewrittenObjC: + case TY_RewrittenLegacyObjC: return true; } } diff --git a/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp b/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp new file mode 100644 index 0000000..6827034 --- /dev/null +++ b/contrib/llvm/tools/clang/lib/Driver/WindowsToolChain.cpp @@ -0,0 +1,368 @@ +//===--- ToolChains.cpp - ToolChain Implementations -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "ToolChains.h" + +#include "clang/Driver/Arg.h" +#include "clang/Driver/ArgList.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/Options.h" +#include "clang/Basic/Version.h" +#include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Path.h" + +// Include the necessary headers to interface with the Windows registry and +// environment. +#ifdef _MSC_VER + #define WIN32_LEAN_AND_MEAN + #define NOGDI + #define NOMINMAX + #include <Windows.h> +#endif + +using namespace clang::driver; +using namespace clang::driver::toolchains; +using namespace clang; + +Windows::Windows(const Driver &D, const llvm::Triple& Triple) + : ToolChain(D, Triple) { +} + +Tool &Windows::SelectTool(const Compilation &C, const JobAction &JA, + const ActionList &Inputs) const { + Action::ActionClass Key; + if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) + Key = Action::AnalyzeJobClass; + else + Key = JA.getKind(); + + bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as, + options::OPT_no_integrated_as, + IsIntegratedAssemblerDefault()); + + Tool *&T = Tools[Key]; + if (!T) { + switch (Key) { + case Action::InputClass: + case Action::BindArchClass: + case Action::LipoJobClass: + case Action::DsymutilJobClass: + case Action::VerifyJobClass: + llvm_unreachable("Invalid tool kind."); + case Action::PreprocessJobClass: + case Action::PrecompileJobClass: + case Action::AnalyzeJobClass: + case Action::MigrateJobClass: + case Action::CompileJobClass: + T = new tools::Clang(*this); break; + case Action::AssembleJobClass: + if (!UseIntegratedAs && getTriple().getEnvironment() == llvm::Triple::MachO) + T = new tools::darwin::Assemble(*this); + else + T = new tools::ClangAs(*this); + break; + case Action::LinkJobClass: + T = new tools::visualstudio::Link(*this); break; + } + } + + return *T; +} + +bool Windows::IsIntegratedAssemblerDefault() const { + return true; +} + +bool Windows::IsUnwindTablesDefault() const { + // FIXME: Gross; we should probably have some separate target + // definition, possibly even reusing the one in clang. + return getArchName() == "x86_64"; +} + +const char *Windows::GetDefaultRelocationModel() const { + return "static"; +} + +const char *Windows::GetForcedPicModel() const { + if (getArchName() == "x86_64") + return "pic"; + return 0; +} + +// FIXME: This probably should goto to some platform utils place. +#ifdef _MSC_VER + +/// \brief Read registry string. +/// This also supports a means to look for high-versioned keys by use +/// of a $VERSION placeholder in the key path. +/// $VERSION in the key path is a placeholder for the version number, +/// causing the highest value path to be searched for and used. +/// I.e. "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION". +/// There can be additional characters in the component. Only the numberic +/// characters are compared. +static bool getSystemRegistryString(const char *keyPath, const char *valueName, + char *value, size_t maxLength) { + HKEY hRootKey = NULL; + HKEY hKey = NULL; + const char* subKey = NULL; + DWORD valueType; + DWORD valueSize = maxLength - 1; + long lResult; + bool returnValue = false; + + if (strncmp(keyPath, "HKEY_CLASSES_ROOT\\", 18) == 0) { + hRootKey = HKEY_CLASSES_ROOT; + subKey = keyPath + 18; + } else if (strncmp(keyPath, "HKEY_USERS\\", 11) == 0) { + hRootKey = HKEY_USERS; + subKey = keyPath + 11; + } else if (strncmp(keyPath, "HKEY_LOCAL_MACHINE\\", 19) == 0) { + hRootKey = HKEY_LOCAL_MACHINE; + subKey = keyPath + 19; + } else if (strncmp(keyPath, "HKEY_CURRENT_USER\\", 18) == 0) { + hRootKey = HKEY_CURRENT_USER; + subKey = keyPath + 18; + } else { + return false; + } + + const char *placeHolder = strstr(subKey, "$VERSION"); + char bestName[256]; + bestName[0] = '\0'; + // If we have a $VERSION placeholder, do the highest-version search. + if (placeHolder) { + const char *keyEnd = placeHolder - 1; + const char *nextKey = placeHolder; + // Find end of previous key. + while ((keyEnd > subKey) && (*keyEnd != '\\')) + keyEnd--; + // Find end of key containing $VERSION. + while (*nextKey && (*nextKey != '\\')) + nextKey++; + size_t partialKeyLength = keyEnd - subKey; + char partialKey[256]; + if (partialKeyLength > sizeof(partialKey)) + partialKeyLength = sizeof(partialKey); + strncpy(partialKey, subKey, partialKeyLength); + partialKey[partialKeyLength] = '\0'; + HKEY hTopKey = NULL; + lResult = RegOpenKeyEx(hRootKey, partialKey, 0, KEY_READ, &hTopKey); + if (lResult == ERROR_SUCCESS) { + char keyName[256]; + int bestIndex = -1; + double bestValue = 0.0; + DWORD index, size = sizeof(keyName) - 1; + for (index = 0; RegEnumKeyEx(hTopKey, index, keyName, &size, NULL, + NULL, NULL, NULL) == ERROR_SUCCESS; index++) { + const char *sp = keyName; + while (*sp && !isdigit(*sp)) + sp++; + if (!*sp) + continue; + const char *ep = sp + 1; + while (*ep && (isdigit(*ep) || (*ep == '.'))) + ep++; + char numBuf[32]; + strncpy(numBuf, sp, sizeof(numBuf) - 1); + numBuf[sizeof(numBuf) - 1] = '\0'; + double value = strtod(numBuf, NULL); + if (value > bestValue) { + bestIndex = (int)index; + bestValue = value; + strcpy(bestName, keyName); + } + size = sizeof(keyName) - 1; + } + // If we found the highest versioned key, open the key and get the value. + if (bestIndex != -1) { + // Append rest of key. + strncat(bestName, nextKey, sizeof(bestName) - 1); + bestName[sizeof(bestName) - 1] = '\0'; + // Open the chosen key path remainder. + lResult = RegOpenKeyEx(hTopKey, bestName, 0, KEY_READ, &hKey); + if (lResult == ERROR_SUCCESS) { + lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType, + (LPBYTE)value, &valueSize); + if (lResult == ERROR_SUCCESS) + returnValue = true; + RegCloseKey(hKey); + } + } + RegCloseKey(hTopKey); + } + } else { + lResult = RegOpenKeyEx(hRootKey, subKey, 0, KEY_READ, &hKey); + if (lResult == ERROR_SUCCESS) { + lResult = RegQueryValueEx(hKey, valueName, NULL, &valueType, + (LPBYTE)value, &valueSize); + if (lResult == ERROR_SUCCESS) + returnValue = true; + RegCloseKey(hKey); + } + } + return returnValue; +} + +/// \brief Get Windows SDK installation directory. +static bool getWindowsSDKDir(std::string &path) { + char windowsSDKInstallDir[256]; + // Try the Windows registry. + bool hasSDKDir = getSystemRegistryString( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Microsoft SDKs\\Windows\\$VERSION", + "InstallationFolder", + windowsSDKInstallDir, + sizeof(windowsSDKInstallDir) - 1); + // If we have both vc80 and vc90, pick version we were compiled with. + if (hasSDKDir && windowsSDKInstallDir[0]) { + path = windowsSDKInstallDir; + return true; + } + return false; +} + + // Get Visual Studio installation directory. +static bool getVisualStudioDir(std::string &path) { + // First check the environment variables that vsvars32.bat sets. + const char* vcinstalldir = getenv("VCINSTALLDIR"); + if (vcinstalldir) { + char *p = const_cast<char *>(strstr(vcinstalldir, "\\VC")); + if (p) + *p = '\0'; + path = vcinstalldir; + return true; + } + + char vsIDEInstallDir[256]; + char vsExpressIDEInstallDir[256]; + // Then try the windows registry. + bool hasVCDir = getSystemRegistryString( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\$VERSION", + "InstallDir", vsIDEInstallDir, sizeof(vsIDEInstallDir) - 1); + bool hasVCExpressDir = getSystemRegistryString( + "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VCExpress\\$VERSION", + "InstallDir", vsExpressIDEInstallDir, sizeof(vsExpressIDEInstallDir) - 1); + // If we have both vc80 and vc90, pick version we were compiled with. + if (hasVCDir && vsIDEInstallDir[0]) { + char *p = (char*)strstr(vsIDEInstallDir, "\\Common7\\IDE"); + if (p) + *p = '\0'; + path = vsIDEInstallDir; + return true; + } + + if (hasVCExpressDir && vsExpressIDEInstallDir[0]) { + char *p = (char*)strstr(vsExpressIDEInstallDir, "\\Common7\\IDE"); + if (p) + *p = '\0'; + path = vsExpressIDEInstallDir; + return true; + } + + // Try the environment. + const char *vs100comntools = getenv("VS100COMNTOOLS"); + const char *vs90comntools = getenv("VS90COMNTOOLS"); + const char *vs80comntools = getenv("VS80COMNTOOLS"); + const char *vscomntools = NULL; + + // Try to find the version that we were compiled with + if(false) {} + #if (_MSC_VER >= 1600) // VC100 + else if(vs100comntools) { + vscomntools = vs100comntools; + } + #elif (_MSC_VER == 1500) // VC80 + else if(vs90comntools) { + vscomntools = vs90comntools; + } + #elif (_MSC_VER == 1400) // VC80 + else if(vs80comntools) { + vscomntools = vs80comntools; + } + #endif + // Otherwise find any version we can + else if (vs100comntools) + vscomntools = vs100comntools; + else if (vs90comntools) + vscomntools = vs90comntools; + else if (vs80comntools) + vscomntools = vs80comntools; + + if (vscomntools && *vscomntools) { + const char *p = strstr(vscomntools, "\\Common7\\Tools"); + path = p ? std::string(vscomntools, p) : vscomntools; + return true; + } + return false; +} + +#endif // _MSC_VER + +void Windows::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdinc)) + return; + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { + llvm::sys::Path P(getDriver().ResourceDir); + P.appendComponent("include"); + addSystemInclude(DriverArgs, CC1Args, P.str()); + } + + if (DriverArgs.hasArg(options::OPT_nostdlibinc)) + return; + +#ifdef _MSC_VER + // Honor %INCLUDE%. It should know essential search paths with vcvarsall.bat. + if (const char *cl_include_dir = getenv("INCLUDE")) { + SmallVector<StringRef, 8> Dirs; + StringRef(cl_include_dir).split(Dirs, ";"); + int n = 0; + for (SmallVectorImpl<StringRef>::iterator I = Dirs.begin(), E = Dirs.end(); + I != E; ++I) { + StringRef d = *I; + if (d.size() == 0) + continue; + ++n; + addSystemInclude(DriverArgs, CC1Args, d); + } + if (n) return; + } + + std::string VSDir; + std::string WindowsSDKDir; + + // When built with access to the proper Windows APIs, try to actually find + // the correct include paths first. + if (getVisualStudioDir(VSDir)) { + addSystemInclude(DriverArgs, CC1Args, VSDir + "\\VC\\include"); + if (getWindowsSDKDir(WindowsSDKDir)) + addSystemInclude(DriverArgs, CC1Args, WindowsSDKDir + "\\include"); + else + addSystemInclude(DriverArgs, CC1Args, + VSDir + "\\VC\\PlatformSDK\\Include"); + return; + } +#endif // _MSC_VER + + // As a fallback, select default install paths. + const StringRef Paths[] = { + "C:/Program Files/Microsoft Visual Studio 10.0/VC/include", + "C:/Program Files/Microsoft Visual Studio 9.0/VC/include", + "C:/Program Files/Microsoft Visual Studio 9.0/VC/PlatformSDK/Include", + "C:/Program Files/Microsoft Visual Studio 8/VC/include", + "C:/Program Files/Microsoft Visual Studio 8/VC/PlatformSDK/Include" + }; + addSystemIncludes(DriverArgs, CC1Args, Paths); +} + +void Windows::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + // FIXME: There should probably be logic here to find libc++ on Windows. +} |