Index: tools/clang/include/clang/Driver/Options.td =================================================================== --- tools/clang/include/clang/Driver/Options.td +++ tools/clang/include/clang/Driver/Options.td @@ -1153,6 +1153,11 @@ def masm_EQ : Joined<["-"], "masm=">, Group, Flags<[DriverOption]>; def mcmodel_EQ : Joined<["-"], "mcmodel=">, Group; def mconstant_cfstrings : Flag<["-"], "mconstant-cfstrings">, Group; +def mconsole : Joined<["-"], "mconsole">, Group, Flags<[DriverOption]>; +def mwindows : Joined<["-"], "mwindows">, Group, Flags<[DriverOption]>; +def mdll : Joined<["-"], "mdll">, Group, Flags<[DriverOption]>; +def municode : Joined<["-"], "municode">, Group, Flags<[DriverOption]>; +def mthreads : Joined<["-"], "mthreads">, Group, Flags<[DriverOption]>; def mcpu_EQ : Joined<["-"], "mcpu=">, Group; def mdynamic_no_pic : Joined<["-"], "mdynamic-no-pic">, Group; def mfix_and_continue : Flag<["-"], "mfix-and-continue">, Group; Index: tools/clang/lib/Driver/CMakeLists.txt =================================================================== --- tools/clang/lib/Driver/CMakeLists.txt +++ tools/clang/lib/Driver/CMakeLists.txt @@ -10,6 +10,7 @@ Driver.cpp DriverOptions.cpp Job.cpp + MinGWToolChain.cpp Multilib.cpp MSVCToolChain.cpp Phases.cpp Index: tools/clang/lib/Driver/Driver.cpp =================================================================== --- tools/clang/lib/Driver/Driver.cpp +++ tools/clang/lib/Driver/Driver.cpp @@ -2053,12 +2053,7 @@ TC = new toolchains::Generic_GCC(*this, Target, Args); break; case llvm::Triple::GNU: - // FIXME: We need a MinGW toolchain. Use the default Generic_GCC - // toolchain for now as the default case would below otherwise. - if (Target.isOSBinFormatELF()) - TC = new toolchains::Generic_ELF(*this, Target, Args); - else - TC = new toolchains::Generic_GCC(*this, Target, Args); + TC = new toolchains::MinGW(*this, Target, Args); break; case llvm::Triple::Itanium: TC = new toolchains::CrossWindowsToolChain(*this, Target, Args); Index: tools/clang/lib/Driver/MinGWToolChain.cpp =================================================================== --- tools/clang/lib/Driver/MinGWToolChain.cpp +++ tools/clang/lib/Driver/MinGWToolChain.cpp @@ -0,0 +1,141 @@ +//===--- MinGWToolChain.cpp - MinGWToolChain Implementation +//-----------------------===// +// +// 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/Driver.h" +#include "clang/Driver/Options.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" + +using namespace clang::diag; +using namespace clang::driver; +using namespace clang::driver::toolchains; +using namespace clang; +using namespace llvm::opt; + +MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) + : ToolChain(D, Triple, Args) { + getProgramPaths().push_back(getDriver().getInstalledDir()); + + llvm::ErrorOr GPPName = llvm::sys::findProgramByName("gcc"); + if (GPPName) + Base = llvm::sys::path::parent_path( + llvm::sys::path::parent_path(GPPName.get())); + else + Base = llvm::sys::path::parent_path(getDriver().getInstalledDir()); + Base += llvm::sys::path::get_separator(); + llvm::SmallString<1024> LibDir(Base); + llvm::sys::path::append(LibDir, "lib", "gcc"); + LibDir += llvm::sys::path::get_separator(); + + // First look for mingw-w64. + Arch = getTriple().getArchName(); + Arch += "-w64-mingw32"; + std::error_code EC; + llvm::sys::fs::directory_iterator MingW64Entry(LibDir + Arch, EC); + if (!EC) { + GccLibDir = MingW64Entry->path(); + } else { + // If mingw-w64 not found, try looking for mingw.org. + Arch = "mingw32"; + llvm::sys::fs::directory_iterator MingwOrgEntry(LibDir + Arch, EC); + if (!EC) + GccLibDir = MingwOrgEntry->path(); + } + Arch += llvm::sys::path::get_separator(); + // GccLibDir must precede Base/lib so that the + // correct crtbegin.o ,cetend.o would be found. + getFilePaths().push_back(GccLibDir); + getFilePaths().push_back(Base + "lib"); + getFilePaths().push_back(Base + Arch + "lib"); +} + +bool MinGW::IsIntegratedAssemblerDefault() const { return true; } + +Tool *MinGW::getTool(Action::ActionClass AC) const { + switch (AC) { + case Action::PreprocessJobClass: + if (!Preprocessor) + Preprocessor.reset(new tools::gcc::Preprocessor(*this)); + return Preprocessor.get(); + case Action::CompileJobClass: + if (!Compiler) + Compiler.reset(new tools::gcc::Compiler(*this)); + return Compiler.get(); + default: + return ToolChain::getTool(AC); + } +} + +Tool *MinGW::buildAssembler() const { + return new tools::MinGW::Assembler(*this); +} + +Tool *MinGW::buildLinker() const { return new tools::MinGW::Linker(*this); } + +bool MinGW::IsUnwindTablesDefault() const { + return getArch() == llvm::Triple::x86_64; +} + +bool MinGW::isPICDefault() const { return getArch() == llvm::Triple::x86_64; } + +bool MinGW::isPIEDefault() const { return false; } + +bool MinGW::isPICDefaultForced() const { + return getArch() == llvm::Triple::x86_64; +} + +bool MinGW::UseSEHExceptions() const { + return getArch() == llvm::Triple::x86_64; +} + +void MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdinc)) + return; + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { + SmallString<1024> P(getDriver().ResourceDir); + llvm::sys::path::append(P, "include"); + addSystemInclude(DriverArgs, CC1Args, P.str()); + } + + if (DriverArgs.hasArg(options::OPT_nostdlibinc)) + return; + + llvm::SmallString<1024> IncludeDir(GccLibDir); + llvm::sys::path::append(IncludeDir, "include"); + addSystemInclude(DriverArgs, CC1Args, IncludeDir.c_str()); + IncludeDir += "-fixed"; + addSystemInclude(DriverArgs, CC1Args, IncludeDir.c_str()); + addSystemInclude(DriverArgs, CC1Args, Base + Arch + "include"); + addSystemInclude(DriverArgs, CC1Args, Base + "include"); +} + +void MinGW::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdlibinc) || + DriverArgs.hasArg(options::OPT_nostdincxx)) + return; + + llvm::SmallString<1024> IncludeDir; + for (bool MingW64 : {true, false}) { + if (MingW64) + IncludeDir = Base + Arch; + else + IncludeDir = GccLibDir; + llvm::sys::path::append(IncludeDir, "include", "c++"); + addSystemInclude(DriverArgs, CC1Args, IncludeDir.str()); + IncludeDir += llvm::sys::path::get_separator(); + addSystemInclude(DriverArgs, CC1Args, IncludeDir.str() + Arch); + addSystemInclude(DriverArgs, CC1Args, IncludeDir.str() + "backward"); + } +} Index: tools/clang/lib/Driver/ToolChains.h =================================================================== --- tools/clang/lib/Driver/ToolChains.h +++ tools/clang/lib/Driver/ToolChains.h @@ -525,6 +525,38 @@ Tool *buildLinker() const override; }; +class LLVM_LIBRARY_VISIBILITY MinGW : public ToolChain { +public: + MinGW(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + + bool IsIntegratedAssemblerDefault() const override; + bool IsUnwindTablesDefault() const override; + bool isPICDefault() const override; + bool isPIEDefault() const override; + bool isPICDefaultForced() const override; + bool UseSEHExceptions() const; + + void + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + void AddClangCXXStdlibIncludeArgs( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + +protected: + Tool *getTool(Action::ActionClass AC) const override; + Tool *buildLinker() const override; + Tool *buildAssembler() const override; + +private: + std::string Base; + std::string GccLibDir; + std::string Arch; + mutable std::unique_ptr Preprocessor; + mutable std::unique_ptr Compiler; +}; + class LLVM_LIBRARY_VISIBILITY OpenBSD : public Generic_ELF { public: OpenBSD(const Driver &D, const llvm::Triple &Triple, Index: tools/clang/lib/Driver/Tools.h =================================================================== --- tools/clang/lib/Driver/Tools.h +++ tools/clang/lib/Driver/Tools.h @@ -672,6 +672,37 @@ }; } // end namespace visualstudio +/// MinGW -- Directly call GNU Binutils assembler and linker +namespace MinGW { +class LLVM_LIBRARY_VISIBILITY Assembler : public Tool { +public: + Assembler(const ToolChain &TC) : Tool("MinGW::Assemble", "assembler", TC) {} + + bool hasIntegratedCPP() const override { return false; } + + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; +}; + +class LLVM_LIBRARY_VISIBILITY Linker : public Tool { +public: + Linker(const ToolChain &TC) : Tool("MinGW::Linker", "linker", TC) {} + + bool hasIntegratedCPP() const override { return false; } + bool isLinkJob() const override { return true; } + + void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const override; + +private: + void AddLibGCC(const llvm::opt::ArgList &Args, ArgStringList &CmdArgs) const; +}; +} // end namespace MinGW + namespace arm { StringRef getARMFloatABI(const Driver &D, const llvm::opt::ArgList &Args, const llvm::Triple &Triple); Index: tools/clang/lib/Driver/Tools.cpp =================================================================== --- tools/clang/lib/Driver/Tools.cpp +++ tools/clang/lib/Driver/Tools.cpp @@ -8772,6 +8772,212 @@ CmdArgs); } +/// MinGW Tools +void MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + claimNoWarnArgs(Args); + ArgStringList CmdArgs; + + if (getToolChain().getArch() == llvm::Triple::x86) { + CmdArgs.push_back("--32"); + } else if (getToolChain().getArch() == llvm::Triple::x86_64) { + CmdArgs.push_back("--64"); + } + + Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); + + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + + for (const auto &II : Inputs) + CmdArgs.push_back(II.getFilename()); + + const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); + C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs)); + + if (Args.hasArg(options::OPT_gsplit_dwarf)) + SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, + SplitDebugName(Args, Inputs[0])); +} + +void MinGW::Linker::AddLibGCC(const ArgList &Args, + ArgStringList &CmdArgs) const { + if (Args.hasArg(options::OPT_mthreads)) + CmdArgs.push_back("-lmingwthrd"); + CmdArgs.push_back("-lmingw32"); + if (Args.hasArg(options::OPT_shared) || + Args.hasArg(options::OPT_shared_libgcc) || + !Args.hasArg(options::OPT_static_libgcc)) { + CmdArgs.push_back("-lgcc_s"); + CmdArgs.push_back("-lgcc"); + } else { + CmdArgs.push_back("-lgcc"); + CmdArgs.push_back("-lgcc_eh"); + } + CmdArgs.push_back("-lmoldname"); + CmdArgs.push_back("-lmingwex"); + CmdArgs.push_back("-lmsvcrt"); +} + +void MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + const ToolChain &TC = getToolChain(); + const Driver &D = TC.getDriver(); + // const SanitizerArgs &Sanitize = TC.getSanitizerArgs(); + + ArgStringList CmdArgs; + + // Silence warning for "clang -g foo.o -o foo" + Args.ClaimAllArgs(options::OPT_g_Group); + // and "clang -emit-llvm foo.o -o foo" + Args.ClaimAllArgs(options::OPT_emit_llvm); + // and for "clang -w foo.o -o foo". Other warning options are already + // handled somewhere else. + Args.ClaimAllArgs(options::OPT_w); + + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + + if (Args.hasArg(options::OPT_s)) + CmdArgs.push_back("-s"); + + CmdArgs.push_back("-m"); + if (TC.getArch() == llvm::Triple::x86) + CmdArgs.push_back("i386pe"); + if (TC.getArch() == llvm::Triple::x86_64) + CmdArgs.push_back("i386pep"); + + if (Args.hasArg(options::OPT_mwindows)) { + CmdArgs.push_back("--subsystem"); + CmdArgs.push_back("windows"); + } else if (Args.hasArg(options::OPT_mconsole)) { + CmdArgs.push_back("--subsystem"); + CmdArgs.push_back("console"); + } + + if (Args.hasArg(options::OPT_static)) + CmdArgs.push_back("-Bstatic"); + else { + if (Args.hasArg(options::OPT_mdll)) + CmdArgs.push_back("--dll"); + else if (Args.hasArg(options::OPT_shared)) + CmdArgs.push_back("--shared"); + CmdArgs.push_back("-Bdynamic"); + if (Args.hasArg(options::OPT_mdll) || Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back("-e"); + if (TC.getArch() == llvm::Triple::x86) + CmdArgs.push_back("_DllMainCRTStartup@12"); + else + CmdArgs.push_back("DllMainCRTStartup"); + CmdArgs.push_back("--enable-auto-image-base"); + } + } + + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + + Args.AddAllArgs(CmdArgs, options::OPT_e); + // FIXME: add -N, -n flags + Args.AddLastArg(CmdArgs, options::OPT_r); + Args.AddLastArg(CmdArgs, options::OPT_s); + Args.AddLastArg(CmdArgs, options::OPT_t); + Args.AddAllArgs(CmdArgs, options::OPT_u_Group); + Args.AddLastArg(CmdArgs, options::OPT_Z_Flag); + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) { + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o"))); + } else { + if (Args.hasArg(options::OPT_municode)) + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2u.o"))); + else + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2.o"))); + } + if (Args.hasArg(options::OPT_pg)) + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("gcrt2.o"))); + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o"))); + } + + Args.AddAllArgs(CmdArgs, options::OPT_L); + const ToolChain::path_list Paths = TC.getFilePaths(); + for (const auto &Path : Paths) + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + Path)); + + AddLinkerInputs(TC, Inputs, Args, CmdArgs); + + // TODO: Add ASan stuff here + + // TODO: Add profile stuff here + + if (D.CCCIsCXX() && !Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && + !Args.hasArg(options::OPT_static); + if (OnlyLibstdcxxStatic) + CmdArgs.push_back("-Bstatic"); + TC.AddCXXStdlibLibArgs(Args, CmdArgs); + if (OnlyLibstdcxxStatic) + CmdArgs.push_back("-Bdynamic"); + } + + if (!Args.hasArg(options::OPT_nostdlib)) { + if (!Args.hasArg(options::OPT_nodefaultlibs)) { + if (Args.hasArg(options::OPT_static)) + CmdArgs.push_back("--start-group"); + + if (Args.hasArg(options::OPT_fstack_protector) || + Args.hasArg(options::OPT_fstack_protector_strong) || + Args.hasArg(options::OPT_fstack_protector_all)) { + CmdArgs.push_back("-lssp_nonshared"); + CmdArgs.push_back("-lssp"); + } + if (Args.hasArg(options::OPT_fopenmp)) + CmdArgs.push_back("-lgomp"); + + AddLibGCC(Args, CmdArgs); + + if (Args.hasArg(options::OPT_pg)) + CmdArgs.push_back("-lgmon"); + + // FIXME: what to do about pthreads library? + // Currently required for OpenMP and posix-threading libgcc, + // does not exists in mingw.org. + //CmdArgs.push_back("-lpthread"); + + // add system libraries + if (Args.hasArg(options::OPT_mwindows)) { + CmdArgs.push_back("-lgdi32"); + CmdArgs.push_back("-lcomdlg32"); + } + CmdArgs.push_back("-ladvapi32"); + CmdArgs.push_back("-lshell32"); + CmdArgs.push_back("-luser32"); + CmdArgs.push_back("-lkernel32"); + + if (Args.hasArg(options::OPT_static)) + CmdArgs.push_back("--end-group"); + else + AddLibGCC(Args, CmdArgs); + } + + if (!Args.hasArg(options::OPT_nostartfiles)) { + // Add crtfastmath.o if available and fast math is enabled. + TC.AddFastMathRuntimeIfAvailable(Args, CmdArgs); + + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o"))); + } + } + const char *Exec = Args.MakeArgString(TC.GetProgramPath("ld")); + C.addCommand(llvm::make_unique(JA, *this, Exec, CmdArgs)); +} + /// XCore Tools // We pass assemble and link construction to the xcc tool. Index: tools/clang/lib/Frontend/InitHeaderSearch.cpp =================================================================== --- tools/clang/lib/Frontend/InitHeaderSearch.cpp +++ tools/clang/lib/Frontend/InitHeaderSearch.cpp @@ -82,11 +82,6 @@ StringRef Arch, StringRef Version); - /// AddMinGW64CXXPaths - Add the necessary paths to support - /// libstdc++ of x86_64-w64-mingw32 aka mingw-w64. - void AddMinGW64CXXPaths(StringRef Base, - StringRef Version); - // AddDefaultCIncludePaths - Add paths that should always be searched. void AddDefaultCIncludePaths(const llvm::Triple &triple, const HeaderSearchOptions &HSOpts); @@ -208,19 +203,6 @@ CXXSystem, false); } -void InitHeaderSearch::AddMinGW64CXXPaths(StringRef Base, - StringRef Version) { - // Assumes Base is HeaderSearchOpts' ResourceDir - AddPath(Base + "/../../../include/c++/" + Version, - CXXSystem, false); - AddPath(Base + "/../../../include/c++/" + Version + "/x86_64-w64-mingw32", - CXXSystem, false); - AddPath(Base + "/../../../include/c++/" + Version + "/i686-w64-mingw32", - CXXSystem, false); - AddPath(Base + "/../../../include/c++/" + Version + "/backward", - CXXSystem, false); -} - void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, const HeaderSearchOptions &HSOpts) { llvm::Triple::OSType os = triple.getOS(); @@ -233,6 +215,7 @@ case llvm::Triple::OpenBSD: case llvm::Triple::Bitrig: case llvm::Triple::NaCl: + case llvm::Triple::Win32: break; default: // FIXME: temporary hack: hard-coded paths. @@ -323,26 +306,6 @@ AddPath("/usr/include/w32api", System, false); break; case llvm::Triple::GNU: - // mingw-w64 crt include paths - // /i686-w64-mingw32/include - SmallString<128> P = StringRef(HSOpts.ResourceDir); - llvm::sys::path::append(P, "../../../i686-w64-mingw32/include"); - AddPath(P, System, false); - - // /x86_64-w64-mingw32/include - P.resize(HSOpts.ResourceDir.size()); - llvm::sys::path::append(P, "../../../x86_64-w64-mingw32/include"); - AddPath(P, System, false); - - // mingw.org crt include paths - // /include - P.resize(HSOpts.ResourceDir.size()); - llvm::sys::path::append(P, "../../../include"); - AddPath(P, System, false); - AddPath("/mingw/include", System, false); -#if defined(LLVM_ON_WIN32) - AddPath("c:/mingw/include", System, false); -#endif break; } break; @@ -419,27 +382,8 @@ // g++-4 / Cygwin-1.5 AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.2"); break; - case llvm::Triple::GNU: - // mingw-w64 C++ include paths (i686-w64-mingw32 and x86_64-w64-mingw32) - AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.7.0"); - AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.7.1"); - AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.7.2"); - AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.7.3"); - AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.8.0"); - AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.8.1"); - AddMinGW64CXXPaths(HSOpts.ResourceDir, "4.8.2"); - // mingw.org C++ include paths -#if defined(LLVM_ON_WIN32) - AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.7.0"); - AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.7.1"); - AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.7.2"); - AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.7.3"); - AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.8.0"); - AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.8.1"); - AddMinGWCPlusPlusIncludePaths("c:/MinGW/lib/gcc", "mingw32", "4.8.2"); -#endif - break; } + break; case llvm::Triple::DragonFly: if (llvm::sys::fs::exists("/usr/lib/gcc47")) AddPath("/usr/include/c++/4.7", CXXSystem, false); @@ -482,8 +426,7 @@ return; case llvm::Triple::Win32: - if (triple.getEnvironment() == llvm::Triple::MSVC || - triple.getEnvironment() == llvm::Triple::Itanium || + if (triple.getEnvironment() != llvm::Triple::Cygnus || triple.isOSBinFormatMachO()) return; break;