From: Nick Lewycky Date: Thu, 15 Nov 2012 05:36:36 +0000 (+0000) Subject: Revert r167567, restoring the ability of clang to run gcc in cases where it X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=5cc9ebb7232383476d0dded69104838e6a15eb70;p=platform%2Fupstream%2Fllvm.git Revert r167567, restoring the ability of clang to run gcc in cases where it can't handle the input file type. This resulted in PR14338. llvm-svn: 168024 --- diff --git a/clang/include/clang/Driver/Driver.h b/clang/include/clang/Driver/Driver.h index 8d752a4..b752ce6 100644 --- a/clang/include/clang/Driver/Driver.h +++ b/clang/include/clang/Driver/Driver.h @@ -363,6 +363,11 @@ public: /// GCC goes to extra lengths here to be a bit more robust. std::string GetTemporaryPath(StringRef Prefix, const char *Suffix) const; + /// ShouldUseClangCompilar - Should the clang compiler be used to + /// handle this action. + bool ShouldUseClangCompiler(const Compilation &C, const JobAction &JA, + const llvm::Triple &ArchName) const; + bool IsUsingLTO(const ArgList &Args) const; private: diff --git a/clang/include/clang/Driver/Types.h b/clang/include/clang/Driver/Types.h index e6e4abc..d28ca88 100644 --- a/clang/include/clang/Driver/Types.h +++ b/clang/include/clang/Driver/Types.h @@ -56,6 +56,9 @@ namespace types { /// types). bool canLipoType(ID Id); + /// isAcceptedByClang - Can clang handle this input type. + bool isAcceptedByClang(ID Id); + /// isCXX - Is this a "C++" input (C++ and Obj-C++ sources and headers). bool isCXX(ID Id); diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index 464df333..68471ec 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1731,6 +1731,22 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, return *TC; } +bool Driver::ShouldUseClangCompiler(const Compilation &C, const JobAction &JA, + const llvm::Triple &Triple) const { + // Check if user requested no clang, or clang doesn't understand this type (we + // only handle single inputs for now). + if (JA.size() != 1 || + !types::isAcceptedByClang((*JA.begin())->getType())) + return false; + + // Otherwise make sure this is an action clang understands. + if (!isa(JA) && !isa(JA) && + !isa(JA)) + return false; + + return true; +} + /// GetReleaseVersion - Parse (([0-9]+)(.([0-9]+)(.([0-9]+)?))?)? and return the /// grouped values as integers. Numbers which are not provided are set to 0. /// diff --git a/clang/lib/Driver/ToolChains.cpp b/clang/lib/Driver/ToolChains.cpp index a347512..819907b 100644 --- a/clang/lib/Driver/ToolChains.cpp +++ b/clang/lib/Driver/ToolChains.cpp @@ -177,6 +177,12 @@ void Generic_ELF::anchor() {} Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const { Action::ActionClass Key = JA.getKind(); + + if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) { + // FIXME: This seems like a hacky way to choose clang frontend. + Key = Action::AnalyzeJobClass; + } + bool UseIntegratedAs = C.getArgs().hasFlag(options::OPT_integrated_as, options::OPT_no_integrated_as, IsIntegratedAssemblerDefault()); @@ -188,11 +194,13 @@ Tool &Darwin::SelectTool(const Compilation &C, const JobAction &JA, case Action::BindArchClass: llvm_unreachable("Invalid tool kind."); 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: - T = new tools::Clang(*this); break; + T = new tools::darwin::Compile(*this); break; case Action::AssembleJobClass: { if (UseIntegratedAs) T = new tools::ClangAs(*this); @@ -1326,7 +1334,11 @@ Generic_GCC::~Generic_GCC() { Tool &Generic_GCC::SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const { - Action::ActionClass Key = JA.getKind(); + Action::ActionClass Key; + if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) + Key = Action::AnalyzeJobClass; + else + Key = JA.getKind(); Tool *&T = Tools[Key]; if (!T) { @@ -1335,11 +1347,14 @@ Tool &Generic_GCC::SelectTool(const Compilation &C, case Action::BindArchClass: llvm_unreachable("Invalid tool kind."); case Action::PreprocessJobClass: + T = new tools::gcc::Preprocess(*this); break; case Action::PrecompileJobClass: + T = new tools::gcc::Precompile(*this); break; case Action::AnalyzeJobClass: case Action::MigrateJobClass: - case Action::CompileJobClass: T = new tools::Clang(*this); break; + case Action::CompileJobClass: + T = new tools::gcc::Compile(*this); break; case Action::AssembleJobClass: T = new tools::gcc::Assemble(*this); break; case Action::LinkJobClass: @@ -1389,18 +1404,27 @@ Hexagon_TC::~Hexagon_TC() { Tool &Hexagon_TC::SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const { - Action::ActionClass Key = JA.getKind(); + 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::PreprocessJobClass: - case Action::PrecompileJobClass: case Action::AnalyzeJobClass: - case Action::MigrateJobClass: - case Action::CompileJobClass: T = new tools::Clang(*this); break; case Action::AssembleJobClass: T = new tools::hexagon::Assemble(*this); break; @@ -1484,7 +1508,12 @@ OpenBSD::OpenBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Arg Tool &OpenBSD::SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const { - Action::ActionClass Key = JA.getKind(); + 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()); @@ -1519,7 +1548,12 @@ Bitrig::Bitrig(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) Tool &Bitrig::SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const { - Action::ActionClass Key = JA.getKind(); + 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()); @@ -1606,7 +1640,12 @@ FreeBSD::FreeBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Arg Tool &FreeBSD::SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const { - Action::ActionClass Key = JA.getKind(); + 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()); @@ -1650,7 +1689,12 @@ NetBSD::NetBSD(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) Tool &NetBSD::SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const { - Action::ActionClass Key = JA.getKind(); + 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()); @@ -1685,7 +1729,11 @@ Minix::Minix(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) Tool &Minix::SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const { - Action::ActionClass Key = JA.getKind(); + Action::ActionClass Key; + if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) + Key = Action::AnalyzeJobClass; + else + Key = JA.getKind(); Tool *&T = Tools[Key]; if (!T) { @@ -1722,7 +1770,11 @@ AuroraUX::AuroraUX(const Driver &D, const llvm::Triple& Triple, Tool &AuroraUX::SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const { - Action::ActionClass Key = JA.getKind(); + Action::ActionClass Key; + if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) + Key = Action::AnalyzeJobClass; + else + Key = JA.getKind(); Tool *&T = Tools[Key]; if (!T) { @@ -1755,7 +1807,11 @@ Solaris::Solaris(const Driver &D, const llvm::Triple& Triple, Tool &Solaris::SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const { - Action::ActionClass Key = JA.getKind(); + Action::ActionClass Key; + if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) + Key = Action::AnalyzeJobClass; + else + Key = JA.getKind(); Tool *&T = Tools[Key]; if (!T) { @@ -2128,7 +2184,12 @@ bool Linux::HasNativeLLVMSupport() const { Tool &Linux::SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const { - Action::ActionClass Key = JA.getKind(); + 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()); @@ -2346,7 +2407,11 @@ DragonFly::DragonFly(const Driver &D, const llvm::Triple& Triple, const ArgList Tool &DragonFly::SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const { - Action::ActionClass Key = JA.getKind(); + Action::ActionClass Key; + if (getDriver().ShouldUseClangCompiler(C, JA, getTriple())) + Key = Action::AnalyzeJobClass; + else + Key = JA.getKind(); Tool *&T = Tools[Key]; if (!T) { diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 9ab35ff..b1e450d 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -257,7 +257,7 @@ void Clang::AddPreprocessingOptions(Compilation &C, A->getOption().matches(options::OPT_MM)) { DepFile = "-"; } else { - DepFile = getDependencyFileName(Args, Inputs); + DepFile = darwin::CC1::getDependencyFileName(Args, Inputs); C.addFailureResultFile(DepFile); } CmdArgs.push_back("-dependency-file"); @@ -1713,10 +1713,10 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, // Set the main file name, so that debug info works even with // -save-temps. CmdArgs.push_back("-main-file-name"); - CmdArgs.push_back(getBaseInputName(Args, Inputs)); + CmdArgs.push_back(darwin::CC1::getBaseInputName(Args, Inputs)); // Some flags which affect the language (via preprocessor - // defines). + // defines). See darwin::CC1::AddCPPArgs. if (Args.hasArg(options::OPT_static)) CmdArgs.push_back("-static-define"); @@ -3636,14 +3636,38 @@ llvm::Triple::ArchType darwin::getArchTypeForDarwinArchName(StringRef Str) { .Default(llvm::Triple::UnknownArch); } -const char *Clang::getBaseInputName(const ArgList &Args, - const InputInfoList &Inputs) { +const char *darwin::CC1::getCC1Name(types::ID Type) const { + switch (Type) { + default: + llvm_unreachable("Unexpected type for Darwin CC1 tool."); + case types::TY_Asm: + case types::TY_C: case types::TY_CHeader: + case types::TY_PP_C: case types::TY_PP_CHeader: + return "cc1"; + case types::TY_ObjC: case types::TY_ObjCHeader: + case types::TY_PP_ObjC: case types::TY_PP_ObjC_Alias: + case types::TY_PP_ObjCHeader: + return "cc1obj"; + case types::TY_CXX: case types::TY_CXXHeader: + case types::TY_PP_CXX: case types::TY_PP_CXXHeader: + return "cc1plus"; + case types::TY_ObjCXX: case types::TY_ObjCXXHeader: + case types::TY_PP_ObjCXX: case types::TY_PP_ObjCXX_Alias: + case types::TY_PP_ObjCXXHeader: + return "cc1objplus"; + } +} + +void darwin::CC1::anchor() {} + +const char *darwin::CC1::getBaseInputName(const ArgList &Args, + const InputInfoList &Inputs) { return Args.MakeArgString( llvm::sys::path::filename(Inputs[0].getBaseInput())); } -const char *Clang::getBaseInputStem(const ArgList &Args, - const InputInfoList &Inputs) { +const char *darwin::CC1::getBaseInputStem(const ArgList &Args, + const InputInfoList &Inputs) { const char *Str = getBaseInputName(Args, Inputs); if (const char *End = strrchr(Str, '.')) @@ -3652,8 +3676,9 @@ const char *Clang::getBaseInputStem(const ArgList &Args, return Str; } -const char *Clang::getDependencyFileName(const ArgList &Args, - const InputInfoList &Inputs) { +const char * +darwin::CC1::getDependencyFileName(const ArgList &Args, + const InputInfoList &Inputs) { // FIXME: Think about this more. std::string Res; @@ -3661,11 +3686,588 @@ const char *Clang::getDependencyFileName(const ArgList &Args, std::string Str(OutputOpt->getValue()); Res = Str.substr(0, Str.rfind('.')); } else { - Res = getBaseInputStem(Args, Inputs); + Res = darwin::CC1::getBaseInputStem(Args, Inputs); } return Args.MakeArgString(Res + ".d"); } +void darwin::CC1::RemoveCC1UnsupportedArgs(ArgStringList &CmdArgs) const { + for (ArgStringList::iterator it = CmdArgs.begin(), ie = CmdArgs.end(); + it != ie;) { + + StringRef Option = *it; + bool RemoveOption = false; + + // 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(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(Option) + .Case("-mthumb", true) + .Case("-mno-thumb", true) + .Case("-mno-fused-madd", true) + .Case("-mlong-branch", true) + .Case("-mlongcall", true) + .Case("-mcpu=G4", true) + .Case("-mcpu=G5", true) + .Default(false); + } + + // Handle warning options. + if (Option.startswith("-W")) { + // Remove -W/-Wno- to reduce the number of cases. + if (Option.startswith("-Wno-")) + Option = Option.substr(5); + else + Option = Option.substr(2); + + RemoveOption = llvm::StringSwitch(Option) + .Case("address-of-temporary", true) + .Case("ambiguous-member-template", true) + .Case("analyzer-incompatible-plugin", true) + .Case("array-bounds", true) + .Case("array-bounds-pointer-arithmetic", true) + .Case("bind-to-temporary-copy", true) + .Case("bitwise-op-parentheses", true) + .Case("bool-conversions", true) + .Case("builtin-macro-redefined", true) + .Case("c++-hex-floats", true) + .Case("c++0x-compat", true) + .Case("c++0x-extensions", true) + .Case("c++0x-narrowing", true) + .Case("c++11-compat", true) + .Case("c++11-extensions", true) + .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) + .Case("default-arg-special-member", true) + .Case("delegating-ctor-cycles", true) + .Case("delete-non-virtual-dtor", true) + .Case("deprecated-implementations", true) + .Case("deprecated-writable-strings", true) + .Case("distributed-object-modifiers", true) + .Case("duplicate-method-arg", true) + .Case("dynamic-class-memaccess", true) + .Case("enum-compare", true) + .Case("enum-conversion", true) + .Case("exit-time-destructors", true) + .Case("gnu", true) + .Case("gnu-designator", true) + .Case("header-hygiene", true) + .Case("idiomatic-parentheses", true) + .Case("ignored-qualifiers", true) + .Case("implicit-atomic-properties", true) + .Case("incompatible-pointer-types", true) + .Case("incomplete-implementation", true) + .Case("int-conversion", true) + .Case("initializer-overrides", true) + .Case("invalid-noreturn", true) + .Case("invalid-token-paste", true) + .Case("language-extension-token", true) + .Case("literal-conversion", true) + .Case("literal-range", true) + .Case("local-type-template-args", true) + .Case("logical-op-parentheses", true) + .Case("method-signatures", true) + .Case("microsoft", true) + .Case("mismatched-tags", true) + .Case("missing-method-return-type", true) + .Case("non-pod-varargs", true) + .Case("nonfragile-abi2", true) + .Case("null-arithmetic", true) + .Case("null-dereference", true) + .Case("out-of-line-declaration", true) + .Case("overriding-method-mismatch", true) + .Case("readonly-setter-attrs", true) + .Case("return-stack-address", true) + .Case("self-assign", true) + .Case("semicolon-before-method-body", true) + .Case("sentinel", true) + .Case("shift-overflow", true) + .Case("shift-sign-overflow", true) + .Case("sign-conversion", true) + .Case("sizeof-array-argument", true) + .Case("sizeof-pointer-memaccess", true) + .Case("string-compare", true) + .Case("super-class-method-mismatch", true) + .Case("tautological-compare", true) + .Case("typedef-redefinition", true) + .Case("typename-missing", true) + .Case("undefined-reinterpret-cast", true) + .Case("unknown-warning-option", true) + .Case("unnamed-type-template-args", true) + .Case("unneeded-internal-declaration", true) + .Case("unneeded-member-function", true) + .Case("unused-comparison", true) + .Case("unused-exception-parameter", true) + .Case("unused-member-function", true) + .Case("unused-result", true) + .Case("vector-conversions", true) + .Case("vla", true) + .Case("used-but-marked-unused", true) + .Case("weak-vtables", true) + .Default(false); + } // if (Option.startswith("-W")) + if (RemoveOption) { + it = CmdArgs.erase(it); + ie = CmdArgs.end(); + } else { + ++it; + } + } +} + +void darwin::CC1::AddCC1Args(const ArgList &Args, + ArgStringList &CmdArgs) const { + const Driver &D = getToolChain().getDriver(); + + CheckCodeGenerationOptions(D, Args); + + // Derived from cc1 spec. + if ((!Args.hasArg(options::OPT_mkernel) || + (getDarwinToolChain().isTargetIPhoneOS() && + !getDarwinToolChain().isIPhoneOSVersionLT(6, 0))) && + !Args.hasArg(options::OPT_static) && + !Args.hasArg(options::OPT_mdynamic_no_pic)) + CmdArgs.push_back("-fPIC"); + + if (getToolChain().getTriple().getArch() == llvm::Triple::arm || + getToolChain().getTriple().getArch() == llvm::Triple::thumb) { + if (!Args.hasArg(options::OPT_fbuiltin_strcat)) + CmdArgs.push_back("-fno-builtin-strcat"); + if (!Args.hasArg(options::OPT_fbuiltin_strcpy)) + CmdArgs.push_back("-fno-builtin-strcpy"); + } + + if (Args.hasArg(options::OPT_g_Flag) && + !Args.hasArg(options::OPT_fno_eliminate_unused_debug_symbols)) + CmdArgs.push_back("-feliminate-unused-debug-symbols"); +} + +void darwin::CC1::AddCC1OptionsArgs(const ArgList &Args, ArgStringList &CmdArgs, + const InputInfoList &Inputs, + const ArgStringList &OutputArgs) const { + const Driver &D = getToolChain().getDriver(); + + // Derived from cc1_options spec. + if (Args.hasArg(options::OPT_fast) || + Args.hasArg(options::OPT_fastf) || + Args.hasArg(options::OPT_fastcp)) + CmdArgs.push_back("-O3"); + + if (Arg *A = Args.getLastArg(options::OPT_pg)) + if (Args.hasArg(options::OPT_fomit_frame_pointer)) + D.Diag(diag::err_drv_argument_not_allowed_with) + << A->getAsString(Args) << "-fomit-frame-pointer"; + + AddCC1Args(Args, CmdArgs); + + if (!Args.hasArg(options::OPT_Q)) + CmdArgs.push_back("-quiet"); + + CmdArgs.push_back("-dumpbase"); + CmdArgs.push_back(darwin::CC1::getBaseInputName(Args, Inputs)); + + Args.AddAllArgs(CmdArgs, options::OPT_d_Group); + + Args.AddAllArgs(CmdArgs, options::OPT_m_Group); + Args.AddAllArgs(CmdArgs, options::OPT_a_Group); + + // FIXME: The goal is to use the user provided -o if that is our + // final output, otherwise to drive from the original input + // name. Find a clean way to go about this. + if ((Args.hasArg(options::OPT_c) || Args.hasArg(options::OPT_S)) && + Args.hasArg(options::OPT_o)) { + Arg *OutputOpt = Args.getLastArg(options::OPT_o); + CmdArgs.push_back("-auxbase-strip"); + CmdArgs.push_back(OutputOpt->getValue()); + } else { + CmdArgs.push_back("-auxbase"); + CmdArgs.push_back(darwin::CC1::getBaseInputStem(Args, Inputs)); + } + + Args.AddAllArgs(CmdArgs, options::OPT_g_Group); + + Args.AddAllArgs(CmdArgs, options::OPT_O); + // FIXME: -Wall is getting some special treatment. Investigate. + Args.AddAllArgs(CmdArgs, options::OPT_W_Group, options::OPT_pedantic_Group); + Args.AddLastArg(CmdArgs, options::OPT_w); + Args.AddAllArgs(CmdArgs, options::OPT_std_EQ, options::OPT_ansi, + options::OPT_trigraphs); + if (!Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) { + // Honor -std-default. + Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ, + "-std=", /*Joined=*/true); + } + + if (Args.hasArg(options::OPT_v)) + CmdArgs.push_back("-version"); + if (Args.hasArg(options::OPT_pg) && + getToolChain().SupportsProfiling()) + CmdArgs.push_back("-p"); + Args.AddLastArg(CmdArgs, options::OPT_p); + + // The driver treats -fsyntax-only specially. + if (getToolChain().getTriple().getArch() == llvm::Triple::arm || + getToolChain().getTriple().getArch() == llvm::Triple::thumb) { + // Removes -fbuiltin-str{cat,cpy}; these aren't recognized by cc1 but are + // used to inhibit the default -fno-builtin-str{cat,cpy}. + // + // FIXME: Should we grow a better way to deal with "removing" args? + for (arg_iterator it = Args.filtered_begin(options::OPT_f_Group, + options::OPT_fsyntax_only), + ie = Args.filtered_end(); it != ie; ++it) { + if (!(*it)->getOption().matches(options::OPT_fbuiltin_strcat) && + !(*it)->getOption().matches(options::OPT_fbuiltin_strcpy)) { + (*it)->claim(); + (*it)->render(Args, CmdArgs); + } + } + } else + Args.AddAllArgs(CmdArgs, options::OPT_f_Group, options::OPT_fsyntax_only); + + // Claim Clang only -f options, they aren't worth warning about. + Args.ClaimAllArgs(options::OPT_f_clang_Group); + + Args.AddAllArgs(CmdArgs, options::OPT_undef); + if (Args.hasArg(options::OPT_Qn)) + CmdArgs.push_back("-fno-ident"); + + // FIXME: This isn't correct. + //Args.AddLastArg(CmdArgs, options::OPT__help) + //Args.AddLastArg(CmdArgs, options::OPT__targetHelp) + + CmdArgs.append(OutputArgs.begin(), OutputArgs.end()); + + // FIXME: Still don't get what is happening here. Investigate. + Args.AddAllArgs(CmdArgs, options::OPT__param); + + if (Args.hasArg(options::OPT_fmudflap) || + Args.hasArg(options::OPT_fmudflapth)) { + CmdArgs.push_back("-fno-builtin"); + CmdArgs.push_back("-fno-merge-constants"); + } + + if (Args.hasArg(options::OPT_coverage)) { + CmdArgs.push_back("-fprofile-arcs"); + CmdArgs.push_back("-ftest-coverage"); + } + + if (types::isCXX(Inputs[0].getType())) + CmdArgs.push_back("-D__private_extern__=extern"); +} + +void darwin::CC1::AddCPPOptionsArgs(const ArgList &Args, ArgStringList &CmdArgs, + const InputInfoList &Inputs, + const ArgStringList &OutputArgs) const { + // Derived from cpp_options + AddCPPUniqueOptionsArgs(Args, CmdArgs, Inputs); + + CmdArgs.append(OutputArgs.begin(), OutputArgs.end()); + + AddCC1Args(Args, CmdArgs); + + // NOTE: The code below has some commonality with cpp_options, but + // in classic gcc style ends up sending things in different + // orders. This may be a good merge candidate once we drop pedantic + // compatibility. + + Args.AddAllArgs(CmdArgs, options::OPT_m_Group); + Args.AddAllArgs(CmdArgs, options::OPT_std_EQ, options::OPT_ansi, + options::OPT_trigraphs); + if (!Args.getLastArg(options::OPT_std_EQ, options::OPT_ansi)) { + // Honor -std-default. + Args.AddAllArgsTranslated(CmdArgs, options::OPT_std_default_EQ, + "-std=", /*Joined=*/true); + } + Args.AddAllArgs(CmdArgs, options::OPT_W_Group, options::OPT_pedantic_Group); + Args.AddLastArg(CmdArgs, options::OPT_w); + + // The driver treats -fsyntax-only specially. + Args.AddAllArgs(CmdArgs, options::OPT_f_Group, options::OPT_fsyntax_only); + + // Claim Clang only -f options, they aren't worth warning about. + Args.ClaimAllArgs(options::OPT_f_clang_Group); + + if (Args.hasArg(options::OPT_g_Group) && !Args.hasArg(options::OPT_g0) && + !Args.hasArg(options::OPT_fno_working_directory)) + CmdArgs.push_back("-fworking-directory"); + + Args.AddAllArgs(CmdArgs, options::OPT_O); + Args.AddAllArgs(CmdArgs, options::OPT_undef); + if (Args.hasArg(options::OPT_save_temps)) + CmdArgs.push_back("-fpch-preprocess"); +} + +void darwin::CC1::AddCPPUniqueOptionsArgs(const ArgList &Args, + ArgStringList &CmdArgs, + const InputInfoList &Inputs) const { + const Driver &D = getToolChain().getDriver(); + + CheckPreprocessingOptions(D, Args); + + // Derived from cpp_unique_options. + // -{C,CC} only with -E is checked in CheckPreprocessingOptions(). + Args.AddLastArg(CmdArgs, options::OPT_C); + Args.AddLastArg(CmdArgs, options::OPT_CC); + if (!Args.hasArg(options::OPT_Q)) + CmdArgs.push_back("-quiet"); + Args.AddAllArgs(CmdArgs, options::OPT_nostdinc); + Args.AddAllArgs(CmdArgs, options::OPT_nostdincxx); + Args.AddLastArg(CmdArgs, options::OPT_v); + Args.AddAllArgs(CmdArgs, options::OPT_I_Group, options::OPT_F); + Args.AddLastArg(CmdArgs, options::OPT_P); + + // FIXME: Handle %I properly. + if (getToolChain().getArch() == llvm::Triple::x86_64) { + CmdArgs.push_back("-imultilib"); + CmdArgs.push_back("x86_64"); + } + + if (Args.hasArg(options::OPT_MD)) { + CmdArgs.push_back("-MD"); + CmdArgs.push_back(darwin::CC1::getDependencyFileName(Args, Inputs)); + } + + if (Args.hasArg(options::OPT_MMD)) { + CmdArgs.push_back("-MMD"); + CmdArgs.push_back(darwin::CC1::getDependencyFileName(Args, Inputs)); + } + + Args.AddLastArg(CmdArgs, options::OPT_M); + Args.AddLastArg(CmdArgs, options::OPT_MM); + Args.AddAllArgs(CmdArgs, options::OPT_MF); + Args.AddLastArg(CmdArgs, options::OPT_MG); + Args.AddLastArg(CmdArgs, options::OPT_MP); + Args.AddAllArgs(CmdArgs, options::OPT_MQ); + Args.AddAllArgs(CmdArgs, options::OPT_MT); + if (!Args.hasArg(options::OPT_M) && !Args.hasArg(options::OPT_MM) && + (Args.hasArg(options::OPT_MD) || Args.hasArg(options::OPT_MMD))) { + if (Arg *OutputOpt = Args.getLastArg(options::OPT_o)) { + CmdArgs.push_back("-MQ"); + CmdArgs.push_back(OutputOpt->getValue()); + } + } + + Args.AddLastArg(CmdArgs, options::OPT_remap); + if (Args.hasArg(options::OPT_g3)) + CmdArgs.push_back("-dD"); + Args.AddLastArg(CmdArgs, options::OPT_H); + + AddCPPArgs(Args, CmdArgs); + + Args.AddAllArgs(CmdArgs, options::OPT_D, options::OPT_U, options::OPT_A); + Args.AddAllArgs(CmdArgs, options::OPT_i_Group); + + for (InputInfoList::const_iterator + it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { + const InputInfo &II = *it; + + CmdArgs.push_back(II.getFilename()); + } + + Args.AddAllArgValues(CmdArgs, options::OPT_Wp_COMMA, + options::OPT_Xpreprocessor); + + if (Args.hasArg(options::OPT_fmudflap)) { + CmdArgs.push_back("-D_MUDFLAP"); + CmdArgs.push_back("-include"); + CmdArgs.push_back("mf-runtime.h"); + } + + if (Args.hasArg(options::OPT_fmudflapth)) { + CmdArgs.push_back("-D_MUDFLAP"); + CmdArgs.push_back("-D_MUDFLAPTH"); + CmdArgs.push_back("-include"); + CmdArgs.push_back("mf-runtime.h"); + } +} + +void darwin::CC1::AddCPPArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + // Derived from cpp spec. + + if (Args.hasArg(options::OPT_static)) { + // The gcc spec is broken here, it refers to dynamic but + // that has been translated. Start by being bug compatible. + + // if (!Args.hasArg(arglist.parser.dynamicOption)) + CmdArgs.push_back("-D__STATIC__"); + } else + CmdArgs.push_back("-D__DYNAMIC__"); + + if (Args.hasArg(options::OPT_pthread)) + CmdArgs.push_back("-D_REENTRANT"); +} + +void darwin::Preprocess::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + ArgStringList CmdArgs; + + assert(Inputs.size() == 1 && "Unexpected number of inputs!"); + + CmdArgs.push_back("-E"); + + if (Args.hasArg(options::OPT_traditional) || + Args.hasArg(options::OPT_traditional_cpp)) + CmdArgs.push_back("-traditional-cpp"); + + ArgStringList OutputArgs; + assert(Output.isFilename() && "Unexpected CC1 output."); + OutputArgs.push_back("-o"); + OutputArgs.push_back(Output.getFilename()); + + if (Args.hasArg(options::OPT_E) || getToolChain().getDriver().CCCIsCPP) { + AddCPPOptionsArgs(Args, CmdArgs, Inputs, OutputArgs); + } else { + AddCPPOptionsArgs(Args, CmdArgs, Inputs, ArgStringList()); + CmdArgs.append(OutputArgs.begin(), OutputArgs.end()); + } + + Args.AddAllArgs(CmdArgs, options::OPT_d_Group); + + RemoveCC1UnsupportedArgs(CmdArgs); + + const char *CC1Name = getCC1Name(Inputs[0].getType()); + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath(CC1Name)); + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); +} + +void darwin::Compile::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; + + 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(); + if (const Arg *A = Args.getLastArg(options::OPT_traditional)) + D.Diag(diag::err_drv_argument_only_allowed_with) + << A->getAsString(Args) << "-E"; + + if (JA.getType() == types::TY_LLVM_IR || + JA.getType() == types::TY_LTO_IR) + CmdArgs.push_back("-emit-llvm"); + else if (JA.getType() == types::TY_LLVM_BC || + JA.getType() == types::TY_LTO_BC) + CmdArgs.push_back("-emit-llvm-bc"); + else if (Output.getType() == types::TY_AST) + D.Diag(diag::err_drv_no_ast_support) + << getToolChain().getTripleString(); + else if (JA.getType() != types::TY_PP_Asm && + JA.getType() != types::TY_PCH) + D.Diag(diag::err_drv_invalid_gcc_output_type) + << getTypeName(JA.getType()); + + ArgStringList OutputArgs; + if (Output.getType() != types::TY_PCH) { + OutputArgs.push_back("-o"); + if (Output.isNothing()) + OutputArgs.push_back("/dev/null"); + else + OutputArgs.push_back(Output.getFilename()); + } + + // There is no need for this level of compatibility, but it makes + // diffing easier. + bool OutputArgsEarly = (Args.hasArg(options::OPT_fsyntax_only) || + Args.hasArg(options::OPT_S)); + + if (types::getPreprocessedType(InputType) != types::TY_INVALID) { + AddCPPUniqueOptionsArgs(Args, CmdArgs, Inputs); + if (OutputArgsEarly) { + AddCC1OptionsArgs(Args, CmdArgs, Inputs, OutputArgs); + } else { + AddCC1OptionsArgs(Args, CmdArgs, Inputs, ArgStringList()); + CmdArgs.append(OutputArgs.begin(), OutputArgs.end()); + } + } else { + CmdArgs.push_back("-fpreprocessed"); + + for (InputInfoList::const_iterator + it = Inputs.begin(), ie = Inputs.end(); it != ie; ++it) { + const InputInfo &II = *it; + + // Reject AST inputs. + if (II.getType() == types::TY_AST) { + D.Diag(diag::err_drv_no_ast_support) + << getToolChain().getTripleString(); + return; + } + + CmdArgs.push_back(II.getFilename()); + } + + if (OutputArgsEarly) { + AddCC1OptionsArgs(Args, CmdArgs, Inputs, OutputArgs); + } else { + AddCC1OptionsArgs(Args, CmdArgs, Inputs, ArgStringList()); + CmdArgs.append(OutputArgs.begin(), OutputArgs.end()); + } + } + + if (Output.getType() == types::TY_PCH) { + assert(Output.isFilename() && "Invalid PCH output."); + + CmdArgs.push_back("-o"); + // NOTE: gcc uses a temp .s file for this, but there doesn't seem + // to be a good reason. + const char *TmpPath = C.getArgs().MakeArgString( + D.GetTemporaryPath("cc", "s")); + C.addTempFile(TmpPath); + CmdArgs.push_back(TmpPath); + + // If we're emitting a pch file with the last 4 characters of ".pth" + // and falling back to llvm-gcc we want to use ".gch" instead. + std::string OutputFile(Output.getFilename()); + size_t loc = OutputFile.rfind(".pth"); + if (loc != std::string::npos) + OutputFile.replace(loc, 4, ".gch"); + const char *Tmp = C.getArgs().MakeArgString("--output-pch="+OutputFile); + CmdArgs.push_back(Tmp); + } + + RemoveCC1UnsupportedArgs(CmdArgs); + + const char *CC1Name = getCC1Name(Inputs[0].getType()); + const char *Exec = + Args.MakeArgString(getToolChain().GetProgramPath(CC1Name)); + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); +} + void darwin::Assemble::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, diff --git a/clang/lib/Driver/Tools.h b/clang/lib/Driver/Tools.h index cef7d80..5898c66 100644 --- a/clang/lib/Driver/Tools.h +++ b/clang/lib/Driver/Tools.h @@ -31,13 +31,6 @@ namespace tools { /// \brief Clang compiler tool. class LLVM_LIBRARY_VISIBILITY Clang : public Tool { - static const char *getBaseInputName(const ArgList &Args, - const InputInfoList &Inputs); - static const char *getBaseInputStem(const ArgList &Args, - const InputInfoList &Inputs); - static const char *getDependencyFileName(const ArgList &Args, - const InputInfoList &Inputs); - void AddPreprocessingOptions(Compilation &C, const Driver &D, const ArgList &Args, @@ -225,6 +218,63 @@ namespace darwin { const ToolChain &TC) : Tool(Name, ShortName, TC) {} }; + class LLVM_LIBRARY_VISIBILITY CC1 : public DarwinTool { + virtual void anchor(); + public: + static const char *getBaseInputName(const ArgList &Args, + const InputInfoList &Input); + static const char *getBaseInputStem(const ArgList &Args, + const InputInfoList &Input); + static const char *getDependencyFileName(const ArgList &Args, + const InputInfoList &Inputs); + + protected: + const char *getCC1Name(types::ID Type) const; + + void AddCC1Args(const ArgList &Args, ArgStringList &CmdArgs) const; + void RemoveCC1UnsupportedArgs(ArgStringList &CmdArgs) const; + void AddCC1OptionsArgs(const ArgList &Args, ArgStringList &CmdArgs, + const InputInfoList &Inputs, + const ArgStringList &OutputArgs) const; + void AddCPPOptionsArgs(const ArgList &Args, ArgStringList &CmdArgs, + const InputInfoList &Inputs, + const ArgStringList &OutputArgs) const; + void AddCPPUniqueOptionsArgs(const ArgList &Args, + ArgStringList &CmdArgs, + const InputInfoList &Inputs) const; + void AddCPPArgs(const ArgList &Args, ArgStringList &CmdArgs) const; + + public: + CC1(const char *Name, const char *ShortName, + const ToolChain &TC) : DarwinTool(Name, ShortName, TC) {} + + virtual bool hasGoodDiagnostics() const { return true; } + virtual bool hasIntegratedCPP() const { return true; } + }; + + class LLVM_LIBRARY_VISIBILITY Preprocess : public CC1 { + public: + Preprocess(const ToolChain &TC) : CC1("darwin::Preprocess", + "gcc preprocessor", TC) {} + + 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 Compile : public CC1 { + public: + Compile(const ToolChain &TC) : CC1("darwin::Compile", "gcc frontend", TC) {} + + 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 Assemble : public DarwinTool { public: Assemble(const ToolChain &TC) : DarwinTool("darwin::Assemble", diff --git a/clang/lib/Driver/Types.cpp b/clang/lib/Driver/Types.cpp index c22638f..862025e 100644 --- a/clang/lib/Driver/Types.cpp +++ b/clang/lib/Driver/Types.cpp @@ -71,6 +71,29 @@ bool types::canLipoType(ID Id) { Id == TY_LTO_BC); } +bool types::isAcceptedByClang(ID Id) { + switch (Id) { + default: + return false; + + case TY_Asm: + case TY_C: case TY_PP_C: + case TY_CL: + case TY_CUDA: + case TY_ObjC: case TY_PP_ObjC: case TY_PP_ObjC_Alias: + case TY_CXX: case TY_PP_CXX: + case TY_ObjCXX: case TY_PP_ObjCXX: case TY_PP_ObjCXX_Alias: + case TY_CHeader: case TY_PP_CHeader: + case TY_CLHeader: + case TY_ObjCHeader: case TY_PP_ObjCHeader: + case TY_CXXHeader: case TY_PP_CXXHeader: + case TY_ObjCXXHeader: case TY_PP_ObjCXXHeader: + case TY_AST: + case TY_LLVM_IR: case TY_LLVM_BC: + return true; + } +} + bool types::isObjC(ID Id) { switch (Id) { default: diff --git a/clang/lib/Driver/WindowsToolChain.cpp b/clang/lib/Driver/WindowsToolChain.cpp index a93702e..ac65187 100644 --- a/clang/lib/Driver/WindowsToolChain.cpp +++ b/clang/lib/Driver/WindowsToolChain.cpp @@ -37,7 +37,12 @@ Windows::Windows(const Driver &D, const llvm::Triple& Triple) Tool &Windows::SelectTool(const Compilation &C, const JobAction &JA, const ActionList &Inputs) const { - Action::ActionClass Key = JA.getKind(); + 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());