Index: lib/Driver/CMakeLists.txt =================================================================== --- lib/Driver/CMakeLists.txt +++ lib/Driver/CMakeLists.txt @@ -17,6 +17,7 @@ ToolChain.cpp ToolChains.cpp WindowsToolChain.cpp + MinGWToolChain.cpp Tools.cpp Types.cpp ) Index: lib/Driver/Driver.cpp =================================================================== --- lib/Driver/Driver.cpp +++ lib/Driver/Driver.cpp @@ -1967,10 +1970,7 @@ 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::MSVC: case llvm::Triple::UnknownEnvironment: Index: lib/Driver/MinGWToolChain.cpp =================================================================== --- /dev/null +++ lib/Driver/MinGWToolChain.cpp @@ -0,0 +1,158 @@ +//===--- 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/Basic/CharInfo.h" +#include "clang/Basic/DiagnosticIDs.h" +#include "clang/Basic/Version.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/Options.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/ErrorHandling.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) { + //TODO: libc++ directory + + // Get GCC version string for library and header directories + const std::string GCClibdir = +#ifdef _WIN32 + getDriver().Dir + "/../lib/gcc/" + getTriple().getArchName().str() + "-w64-mingw32"; +#else + getDriver().SysRoot + "/usr/lib/gcc/" + getTriple().getArchName().str() + "-w64-mingw32"; +#endif + if (llvm::sys::fs::exists(GCClibdir)) { + // Find subdirectory, should be the version of MinGW-w64 GCC + llvm::error_code EC; + llvm::sys::fs::directory_iterator entry(StringRef(GCClibdir), EC); + if (!EC) + GCCVersion = llvm::sys::path::filename(entry->path()); + //TODO report error: "no MinGW-w64 GCC installation found" + } + +#ifdef _WIN32 + // assume sysrooted compiler + getFilePaths().push_back(getDriver().Dir + "/../lib"); + getFilePaths().push_back(getDriver().Dir + "/../" + getTriple().getArchName().str() + "-w64-mingw32" + + "/lib"); + getFilePaths().push_back(getDriver().Dir + "/../lib/gcc/" + + getTriple().getArchName().str() + "-w64-mingw32" + "/" + GCCVersion); + +#else + // assume install prefix /usr + getFilePaths().push_back(getDriver().SysRoot + "/usr/" + + getTriple().getArchName().str() + "-w64-mingw32" + "/lib"); + getFilePaths().push_back(getDriver().SysRoot + "/usr/lib/gcc/" + + getTriple().getArchName().str() + "-w64-mingw32" + "/" + GCCVersion); +#endif +} + +Tool *MinGW::buildLinker() const { + return new tools::MinGW::Link(*this); +} + +bool MinGW::IsIntegratedAssemblerDefault() const { + return true; +} + +Tool *MinGW::buildAssembler() const { + return new tools::MinGW::Assemble(*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; +} + +void MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdinc)) + return; + + if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { + SmallString<128> P(getDriver().ResourceDir); + llvm::sys::path::append(P, "include"); + addSystemInclude(DriverArgs, CC1Args, P.str()); + } + + if (DriverArgs.hasArg(options::OPT_nostdlibinc)) + return; + +#ifdef _WIN32 + // Clang runs on Windows, assume sysroot toolchain + addSystemInclude(DriverArgs, CC1Args, + getDriver().Dir + "/../" + getTriple().getArchName().str() + "-w64-mingw32" + + "/include"); +#else + // Clang runs somewhere else, e.g. Linux, assume install prefix /usr + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/usr/" + getTriple().getArchName().str() + "-w64-mingw32" + + "/include"); +#endif +} + +void MinGW::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdlibinc) || + DriverArgs.hasArg(options::OPT_nostdincxx)) + return; + + // Check if libc++ has been enabled and provide its include paths if so. + if (GetCXXStdlibType(DriverArgs) == ToolChain::CST_Libcxx) { + // libc++ is always installed at a fixed path on Linux currently. + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/usr/include/c++/v1"); + return; + } +#ifdef _WIN32 + // Assume sysroot toolchain + addSystemInclude(DriverArgs, CC1Args, + getDriver().Dir + "/../include/c++/" + GCCVersion); + addSystemInclude(DriverArgs, CC1Args, + getDriver().Dir + "/../include/c++/" + GCCVersion + + "/" + getTriple().getArchName().str() + "-w64-mingw32"); + addSystemInclude(DriverArgs, CC1Args, + getDriver().Dir + "/../include/c++/" + GCCVersion + + "/backward"); +#else + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/usr/" + getTriple().getArchName().str() + "-w64-mingw32" + + "/include/c++/" + GCCVersion); + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/usr/" + getTriple().getArchName().str() + "-w64-mingw32" + + "/include/c++/" + GCCVersion + + "/" + getTriple().getArchName().str() + "-w64-mingw32"); + addSystemInclude(DriverArgs, CC1Args, + getDriver().SysRoot + "/usr/" + getTriple().getArchName().str() + "-w64-mingw32" + + "/include/c++/" + GCCVersion + "/backward"); +#endif +} Index: lib/Driver/ToolChains.h =================================================================== --- lib/Driver/ToolChains.h +++ lib/Driver/ToolChains.h @@ -740,6 +740,32 @@ virtual Tool *buildAssembler() const; }; +class LLVM_LIBRARY_VISIBILITY MinGW : public ToolChain { +public: + MinGW(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + + virtual bool IsIntegratedAssemblerDefault() const; + virtual bool IsUnwindTablesDefault() const; + virtual bool isPICDefault() const; + virtual bool isPIEDefault() const; + virtual bool isPICDefaultForced() const; + + virtual void + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const; + virtual void + AddClangCXXStdlibIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const; + +protected: + virtual Tool *buildLinker() const; + virtual Tool *buildAssembler() const; + +private: + std::string GCCVersion; +}; + class LLVM_LIBRARY_VISIBILITY XCore : public ToolChain { public: Index: lib/Driver/Tools.h =================================================================== --- lib/Driver/Tools.h +++ lib/Driver/Tools.h @@ -614,6 +614,37 @@ }; } // end namespace visualstudio + /// MinGW -- Directly call GNU Binutils assembler and linker +namespace MinGW { + class LLVM_LIBRARY_VISIBILITY Assemble : public Tool { + public: + Assemble(const ToolChain &TC) : Tool("dragonfly::Assemble", "assembler", + TC) {} + + virtual bool hasIntegratedCPP() const { return false; } + + virtual void ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const; + }; + class LLVM_LIBRARY_VISIBILITY Link : public Tool { + public: + 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, + const InputInfoList &Inputs, + const llvm::opt::ArgList &TCArgs, + const char *LinkingOutput) const; + }; +} // end namespace MinGW + + namespace arm { StringRef getARMFloatABI(const Driver &D, const llvm::opt::ArgList &Args, const llvm::Triple &Triple); Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -7089,6 +7089,163 @@ return new Command(JA, *this, Args.MakeArgString(Exec), CmdArgs); } +/// MinGW Tools +void MinGW::Assemble::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + 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 (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 MinGW::Link::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_static)) + CmdArgs.push_back("-Bstatic"); + else { + CmdArgs.push_back("-Bdynamic"); + // -shared means building DLL + if (Args.hasArg(options::OPT_shared)) { + CmdArgs.push_back("--shared"); + CmdArgs.push_back("-Bdynamic"); + if (TC.getArch() == llvm::Triple::x86) + CmdArgs.push_back("-e DllMainCRTStartup"); + else + CmdArgs.push_back("-e _DllMainCRTStartup@12"); + + CmdArgs.push_back("--enable-auto-image-base"); + } + } + + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + + if (!Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nostartfiles)) { + if (Args.hasArg(options::OPT_shared)) + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o"))); + else { + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2.o"))); + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o"))); + } + } + + Args.AddAllArgs(CmdArgs, options::OPT_L); + + const ToolChain::path_list Paths = TC.getFilePaths(); + + for (ToolChain::path_list::const_iterator i = Paths.begin(), e = Paths.end(); + i != e; ++i) + CmdArgs.push_back(Args.MakeArgString(StringRef("-L") + *i)); + + 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)) { + CmdArgs.push_back("--start-group"); + + if (Args.hasArg(options::OPT_fopenmp)) + CmdArgs.push_back("-lgomp"); + + AddLibgcc(TC.getTriple(), D, CmdArgs, Args); + + //TODO: remove unconditionally linking pthreads library + // Currently required for OpenMP and posix-threading libgcc + CmdArgs.push_back("-lpthread"); + + // add system libraries + // TODO: handle msvcr*.dll versions here. + CmdArgs.push_back("-lmingw32"); + CmdArgs.push_back("-lmoldname"); + CmdArgs.push_back("-lmingwex"); + CmdArgs.push_back("-lmsvcrt"); + CmdArgs.push_back("-ladvapi32"); + CmdArgs.push_back("-lshell32"); + CmdArgs.push_back("-luser32"); + CmdArgs.push_back("-lkernel32"); + + CmdArgs.push_back("--end-group"); + AddLibgcc(TC.getTriple(), D, CmdArgs, Args); + } + + if (!Args.hasArg(options::OPT_nostartfiles)) { + // Add crtfastmath.o if available and fast math is enabled. + getToolChain().AddFastMathRuntimeIfAvailable(Args, CmdArgs); + + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o"))); + } + } + const char *Exec = + Args.MakeArgString(TC.GetProgramPath("ld")); + C.addCommand(new Command(JA, *this, Exec, CmdArgs)); +} /// XCore Tools // We pass assemble and link construction to the xcc tool. Index: lib/Frontend/InitHeaderSearch.cpp =================================================================== --- lib/Frontend/InitHeaderSearch.cpp +++ 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,18 +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) { @@ -269,7 +252,7 @@ switch (os) { case llvm::Triple::Linux: llvm_unreachable("Include management is handled in the driver."); - + break; case llvm::Triple::Haiku: AddPath("/boot/common/include", System, false); AddPath("/boot/develop/headers/os", System, false); @@ -309,30 +292,11 @@ case llvm::Triple::Win32: switch (triple.getEnvironment()) { default: llvm_unreachable("Include management is handled in the driver."); + break; case llvm::Triple::Cygnus: 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.str(), System, false); - - // /x86_64-w64-mingw32/include - P.resize(HSOpts.ResourceDir.size()); - llvm::sys::path::append(P, "../../../x86_64-w64-mingw32/include"); - AddPath(P.str(), System, false); - - // mingw.org crt include paths - // /include - P.resize(HSOpts.ResourceDir.size()); - llvm::sys::path::append(P, "../../../include"); - AddPath(P.str(), System, false); - AddPath("/mingw/include", System, false); -#if defined(LLVM_ON_WIN32) - AddPath("c:/mingw/include", System, false); -#endif break; } break; @@ -340,7 +304,8 @@ break; } - if ( os != llvm::Triple::RTEMS ) + if ((os != llvm::Triple::RTEMS) && + (!((os == llvm::Triple::Win32) && (triple.getEnvironment() == llvm::Triple::GNU)))) AddPath("/usr/include", ExternCSystem, false); } @@ -403,24 +368,6 @@ 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; } case llvm::Triple::DragonFly: