https://github.com/xu-chiheng updated https://github.com/llvm/llvm-project/pull/74933
From daa6702f698724655b91c4fa52272c09924d2d83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BE=90=E6=8C=81=E6=81=92=20Xu=20Chiheng?= <chiheng...@gmail.com> Date: Sat, 9 Dec 2023 21:51:29 +0800 Subject: [PATCH] 1 --- clang/lib/Driver/CMakeLists.txt | 1 + clang/lib/Driver/Driver.cpp | 4 + clang/lib/Driver/ToolChains/Cygwin.cpp | 731 +++++++++++++++++++++++++ clang/lib/Driver/ToolChains/Cygwin.h | 125 +++++ clang/lib/Lex/InitHeaderSearch.cpp | 30 +- 5 files changed, 865 insertions(+), 26 deletions(-) create mode 100644 clang/lib/Driver/ToolChains/Cygwin.cpp create mode 100644 clang/lib/Driver/ToolChains/Cygwin.h diff --git a/clang/lib/Driver/CMakeLists.txt b/clang/lib/Driver/CMakeLists.txt index 58427e3f83c42..7ab5a1ee96351 100644 --- a/clang/lib/Driver/CMakeLists.txt +++ b/clang/lib/Driver/CMakeLists.txt @@ -51,6 +51,7 @@ add_clang_library(clangDriver ToolChains/CrossWindows.cpp ToolChains/CSKYToolChain.cpp ToolChains/Cuda.cpp + ToolChains/Cygwin.cpp ToolChains/Darwin.cpp ToolChains/DragonFly.cpp ToolChains/Flang.cpp diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp index e241706b9082e..b6f3da3a006f4 100644 --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -17,6 +17,7 @@ #include "ToolChains/Clang.h" #include "ToolChains/CrossWindows.h" #include "ToolChains/Cuda.h" +#include "ToolChains/Cygwin.h" #include "ToolChains/Darwin.h" #include "ToolChains/DragonFly.h" #include "ToolChains/FreeBSD.h" @@ -6263,6 +6264,9 @@ const ToolChain &Driver::getToolChain(const ArgList &Args, else TC = std::make_unique<toolchains::Generic_GCC>(*this, Target, Args); break; + case llvm::Triple::Cygnus: + TC = std::make_unique<toolchains::Cygwin>(*this, Target, Args); + break; case llvm::Triple::GNU: TC = std::make_unique<toolchains::MinGW>(*this, Target, Args); break; diff --git a/clang/lib/Driver/ToolChains/Cygwin.cpp b/clang/lib/Driver/ToolChains/Cygwin.cpp new file mode 100644 index 0000000000000..8aa9cf5c8ec03 --- /dev/null +++ b/clang/lib/Driver/ToolChains/Cygwin.cpp @@ -0,0 +1,731 @@ +//===--- Cygwin.cpp - CygwinToolChain Implementation ------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "Cygwin.h" +#include "CommonArgs.h" +#include "clang/Config/config.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/DriverDiagnostic.h" +#include "clang/Driver/InputInfo.h" +#include "clang/Driver/Options.h" +#include "clang/Driver/SanitizerArgs.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/Path.h" +#include "llvm/Support/VirtualFileSystem.h" +#include <system_error> + +using namespace clang::diag; +using namespace clang::driver; +using namespace clang; +using namespace llvm::opt; + +/// Cygwin Tools +void tools::Cygwin::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(std::make_unique<Command>(JA, *this, ResponseFileSupport::None(), + Exec, CmdArgs, Inputs, Output)); + + if (Args.hasArg(options::OPT_gsplit_dwarf)) + SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, + SplitDebugName(JA, Args, Inputs[0], Output)); +} + +void tools::Cygwin::Linker::AddLibGCC(const ArgList &Args, + ArgStringList &CmdArgs) const { + // Make use of compiler-rt if --rtlib option is used + ToolChain::RuntimeLibType RLT = getToolChain().GetRuntimeLibType(Args); + if (RLT == ToolChain::RLT_Libgcc) { + bool Static = Args.hasArg(options::OPT_static_libgcc) || + Args.hasArg(options::OPT_static); + bool Shared = Args.hasArg(options::OPT_shared); + bool CXX = getToolChain().getDriver().CCCIsCXX(); + + if (Static || (!CXX && !Shared)) { + CmdArgs.push_back("-lgcc"); + CmdArgs.push_back("-lgcc_eh"); + } else { + CmdArgs.push_back("-lgcc_s"); + CmdArgs.push_back("-lgcc"); + } + } else { + AddRunTimeLibs(getToolChain(), getToolChain().getDriver(), CmdArgs, Args); + } + + CmdArgs.push_back("-lcygwin"); +} + +void tools::Cygwin::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(Args); + + 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"); + switch (TC.getArch()) { + case llvm::Triple::x86: + CmdArgs.push_back("i386pe"); + break; + case llvm::Triple::x86_64: + CmdArgs.push_back("i386pep"); + break; + case llvm::Triple::arm: + case llvm::Triple::thumb: + // FIXME: this is incorrect for WinCE + CmdArgs.push_back("thumb2pe"); + break; + case llvm::Triple::aarch64: + CmdArgs.push_back("arm64pe"); + break; + default: + D.Diag(diag::err_target_unknown_triple) << TC.getEffectiveTriple().str(); + } + + if (!Args.getLastArgValue(options::OPT_fuse_ld_EQ, "link").equals_insensitive("lld")) { + if (TC.getArch() == llvm::Triple::x86) { + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_Znwj"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_Znaj"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_ZnwjRKSt9nothrow_t"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_ZnajRKSt9nothrow_t"); + } else { + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_Znwm"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_Znam"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_ZnwmRKSt9nothrow_t"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_ZnamRKSt9nothrow_t"); + } + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_ZdlPv"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_ZdaPv"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_ZdlPvRKSt9nothrow_t"); + CmdArgs.push_back("--wrap"); + CmdArgs.push_back("_ZdaPvRKSt9nothrow_t"); + } + + Arg *SubsysArg = + Args.getLastArg(options::OPT_mwindows, options::OPT_mconsole); + if (SubsysArg && SubsysArg->getOption().matches(options::OPT_mwindows)) { + CmdArgs.push_back("--subsystem"); + CmdArgs.push_back("windows"); + } else if (SubsysArg && + SubsysArg->getOption().matches(options::OPT_mconsole)) { + CmdArgs.push_back("--subsystem"); + CmdArgs.push_back("console"); + } + + if (Args.hasArg(options::OPT_mdll)) + CmdArgs.push_back("--dll"); + else if (Args.hasArg(options::OPT_shared)) + CmdArgs.push_back("--shared"); + if (Args.hasArg(options::OPT_static)) + CmdArgs.push_back("-Bstatic"); + else + 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("__cygwin_dll_entry@12"); + else + CmdArgs.push_back("_cygwin_dll_entry"); + CmdArgs.push_back("--enable-auto-image-base"); + } + CmdArgs.push_back("--dynamicbase"); + + if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) + CmdArgs.push_back("--no-demangle"); + + if (Arg *A = Args.getLastArg(options::OPT_mguard_EQ)) { + StringRef GuardArgs = A->getValue(); + if (GuardArgs == "none") + CmdArgs.push_back("--no-guard-cf"); + else if (GuardArgs == "cf" || GuardArgs == "cf-nochecks") + CmdArgs.push_back("--guard-cf"); + else + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getSpelling() << GuardArgs; + } + + CmdArgs.push_back("-o"); + const char *OutputFile = Output.getFilename(); + // GCC implicitly adds an .exe extension if it is given an output file name + // that lacks an extension. + // GCC used to do this only when the compiler itself runs on windows, but + // since GCC 8 it does the same when cross compiling as well. + if (!llvm::sys::path::has_extension(OutputFile)) { + CmdArgs.push_back(Args.MakeArgString(Twine(OutputFile) + ".exe")); + OutputFile = CmdArgs.back(); + } else + CmdArgs.push_back(OutputFile); + + // 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); + + // Add asan_dynamic as the first import lib before other libs. This allows + // asan to be initialized as early as possible to increase its instrumentation + // coverage to include other user DLLs which has not been built with asan. + if (Sanitize.needsAsanRt() && !Args.hasArg(options::OPT_nostdlib) && + !Args.hasArg(options::OPT_nodefaultlibs)) { + // Cygwin always links against a shared Cygwin DLL. + CmdArgs.push_back( + TC.getCompilerRTArgString(Args, "asan_dynamic", ToolChain::FT_Shared)); + } + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { + if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) { + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbeginS.o"))); + } else { + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt0.o"))); + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o"))); + } + if (Args.hasArg(options::OPT_pg)) + CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("gcrt0.o"))); + } + + Args.AddAllArgs(CmdArgs, options::OPT_L); + TC.AddFilePathLibArgs(Args, CmdArgs); + + // Add the compiler-rt library directories if they exist to help + // the linker find the various sanitizer, builtin, and profiling runtimes. + for (const auto &LibPath : TC.getLibraryPaths()) { + if (TC.getVFS().exists(LibPath)) + CmdArgs.push_back(Args.MakeArgString("-L" + LibPath)); + } + auto CRTPath = TC.getCompilerRTPath(); + if (TC.getVFS().exists(CRTPath)) + CmdArgs.push_back(Args.MakeArgString("-L" + CRTPath)); + + AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); + + if (C.getDriver().IsFlangMode()) { + addFortranRuntimeLibraryPath(TC, Args, CmdArgs); + addFortranRuntimeLibs(TC, CmdArgs); + } + + // TODO: Add profile stuff here + + if (TC.ShouldLinkCXXStdlib(Args)) { + 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"); + } + + bool HasWindowsApp = false; + for (auto Lib : Args.getAllArgValues(options::OPT_l)) { + if (Lib == "windowsapp") { + HasWindowsApp = true; + break; + } + } + + 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.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, + options::OPT_fno_openmp, false)) { + switch (TC.getDriver().getOpenMPRuntime(Args)) { + case Driver::OMPRT_OMP: + CmdArgs.push_back("-lomp"); + break; + case Driver::OMPRT_IOMP5: + CmdArgs.push_back("-liomp5md"); + break; + case Driver::OMPRT_GOMP: + CmdArgs.push_back("-lgomp"); + break; + case Driver::OMPRT_Unknown: + // Already diagnosed. + break; + } + } + + AddLibGCC(Args, CmdArgs); + + if (Sanitize.needsAsanRt()) { + // Cygwin always links against a shared Cygwin DLL. + CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dynamic", + ToolChain::FT_Shared)); + CmdArgs.push_back( + TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); + CmdArgs.push_back("--require-defined"); + CmdArgs.push_back(TC.getArch() == llvm::Triple::x86 + ? "___asan_seh_interceptor" + : "__asan_seh_interceptor"); + // Make sure the linker consider all object files from the dynamic + // runtime thunk. + CmdArgs.push_back("--whole-archive"); + CmdArgs.push_back( + TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); + CmdArgs.push_back("--no-whole-archive"); + } + + TC.addProfileRTLibs(Args, CmdArgs); + + if (!HasWindowsApp) { + // Add system libraries. If linking to libwindowsapp.a, that import + // library replaces all these and we shouldn't accidentally try to + // link to the normal desktop mode dlls. + 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 (!HasWindowsApp) + CmdArgs.push_back("-lkernel32"); + } + } + + 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.GetLinkerPath()); + C.addCommand(std::make_unique<Command>(JA, *this, + ResponseFileSupport::AtFileUTF8(), + Exec, CmdArgs, Inputs, Output)); +} + +static bool isCrossCompiling(const llvm::Triple &T, bool RequireArchMatch) { + llvm::Triple HostTriple(llvm::Triple::normalize(LLVM_HOST_TRIPLE)); + if (!HostTriple.isWindowsCygwinEnvironment()) + return true; + if (RequireArchMatch && HostTriple.getArch() != T.getArch()) + return true; + return false; +} + +// Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple. +static bool findGccVersion(StringRef LibDir, std::string &GccLibDir, + std::string &Ver, + toolchains::Generic_GCC::GCCVersion &Version) { + Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0"); + std::error_code EC; + for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE; + LI = LI.increment(EC)) { + StringRef VersionText = llvm::sys::path::filename(LI->path()); + auto CandidateVersion = + toolchains::Generic_GCC::GCCVersion::Parse(VersionText); + if (CandidateVersion.Major == -1) + continue; + if (CandidateVersion <= Version) + continue; + Version = CandidateVersion; + Ver = std::string(VersionText); + GccLibDir = LI->path(); + } + return Ver.size(); +} + +static llvm::Triple getLiteralTriple(const Driver &D, const llvm::Triple &T) { + llvm::Triple LiteralTriple(D.getTargetTriple()); + // The arch portion of the triple may be overridden by -m32/-m64. + LiteralTriple.setArchName(T.getArchName()); + return LiteralTriple; +} + +void toolchains::Cygwin::findGccLibDir(const llvm::Triple &LiteralTriple) { + llvm::SmallVector<llvm::SmallString<32>, 5> SubdirNames; + SubdirNames.emplace_back(getTriple().getArchName()); + SubdirNames[0] += "-pc-cygwin"; + SubdirNames.emplace_back("cygwin"); + if (SubdirName.empty()) + SubdirName = SubdirNames[0].str(); + // lib: Arch Linux, Ubuntu, Windows + // lib64: openSUSE Linux + for (StringRef CandidateLib : {"lib", "lib64"}) { + for (StringRef CandidateSysroot : SubdirNames) { + llvm::SmallString<1024> LibDir(Base); + llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateSysroot); + if (findGccVersion(LibDir, GccLibDir, Ver, GccVer)) { + SubdirName = std::string(CandidateSysroot); + return; + } + } + } +} + +static llvm::ErrorOr<std::string> findGcc(const llvm::Triple &LiteralTriple, + const llvm::Triple &T) { + llvm::SmallVector<llvm::SmallString<32>, 5> Gccs; + Gccs.emplace_back(T.getArchName()); + Gccs[0] += "-pc-cygwin-gcc"; + Gccs.emplace_back("cygwin-gcc"); + // Please do not add "gcc" here + for (StringRef CandidateGcc : Gccs) + if (llvm::ErrorOr<std::string> GPPName = llvm::sys::findProgramByName(CandidateGcc)) + return GPPName; + return make_error_code(std::errc::no_such_file_or_directory); +} + +static llvm::ErrorOr<std::string> +findClangRelativeSysroot(const Driver &D, const llvm::Triple &LiteralTriple, + const llvm::Triple &T, std::string &SubdirName) { + llvm::SmallVector<llvm::SmallString<32>, 4> Subdirs; + Subdirs.emplace_back(T.str()); + Subdirs.emplace_back(T.getArchName()); + Subdirs[1] += "-pc-cygwin"; + StringRef ClangRoot = llvm::sys::path::parent_path(D.getInstalledDir()); + StringRef Sep = llvm::sys::path::get_separator(); + for (StringRef CandidateSubdir : Subdirs) { + if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) { + SubdirName = std::string(CandidateSubdir); + return (ClangRoot + Sep + CandidateSubdir).str(); + } + } + return make_error_code(std::errc::no_such_file_or_directory); +} + +toolchains::Cygwin::Cygwin(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) + : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args), + RocmInstallation(D, Triple, Args) { + getProgramPaths().push_back(getDriver().getInstalledDir()); + + // The sequence for detecting a sysroot here should be kept in sync with + // the testTriple function below. + llvm::Triple LiteralTriple = getLiteralTriple(D, getTriple()); + if (getDriver().SysRoot.size()) + Base = getDriver().SysRoot; + // Look for <clang-bin>/../<triplet>; if found, use <clang-bin>/.. as the + // base as it could still be a base for a gcc setup with libgcc. + else if (llvm::ErrorOr<std::string> TargetSubdir = findClangRelativeSysroot( + getDriver(), LiteralTriple, getTriple(), SubdirName)) + Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get())); + else if (llvm::ErrorOr<std::string> GPPName = + findGcc(LiteralTriple, getTriple())) + Base = std::string(llvm::sys::path::parent_path( + llvm::sys::path::parent_path(GPPName.get()))); + else + Base = std::string( + llvm::sys::path::parent_path(getDriver().getInstalledDir())); + + Base += llvm::sys::path::get_separator(); + findGccLibDir(LiteralTriple); + TripleDirName = SubdirName; + // GccLibDir must precede Base/lib so that the + // correct crtbegin.o ,cetend.o would be found. + getFilePaths().push_back(GccLibDir); + getFilePaths().push_back( + (Base + SubdirName + llvm::sys::path::get_separator() + "lib").str()); + getFilePaths().push_back( + (Base + SubdirName + llvm::sys::path::get_separator() + "usr/lib").str()); + getFilePaths().push_back( + (Base + SubdirName + llvm::sys::path::get_separator() + "usr/lib/w32api").str()); + + // Only include <base>/lib if we're not cross compiling (not even for + // windows->windows to a different arch), or if the sysroot has been set + // (where we presume the user has pointed it at an arch specific + // subdirectory). + if (!::isCrossCompiling(getTriple(), /*RequireArchMatch=*/true) || + getDriver().SysRoot.size()) + getFilePaths().push_back(Base + "lib"); + + // for Cygwin's crt0.o + getFilePaths().push_back(getDriver().SysRoot + "/lib"); + getFilePaths().push_back(getDriver().SysRoot + "/usr/lib"); + + NativeLLVMSupport = + Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER) + .equals_insensitive("lld"); +} + +Tool *toolchains::Cygwin::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 *toolchains::Cygwin::buildAssembler() const { + return new tools::Cygwin::Assembler(*this); +} + +Tool *toolchains::Cygwin::buildLinker() const { + return new tools::Cygwin::Linker(*this); +} + +bool toolchains::Cygwin::HasNativeLLVMSupport() const { + return NativeLLVMSupport; +} + +ToolChain::UnwindTableLevel +toolchains::Cygwin::getDefaultUnwindTableLevel(const ArgList &Args) const { + Arg *ExceptionArg = Args.getLastArg(options::OPT_fsjlj_exceptions, + options::OPT_fseh_exceptions, + options::OPT_fdwarf_exceptions); + if (ExceptionArg && + ExceptionArg->getOption().matches(options::OPT_fseh_exceptions)) + return UnwindTableLevel::Asynchronous; + + if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm || + getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64) + return UnwindTableLevel::Asynchronous; + return UnwindTableLevel::None; +} + +bool toolchains::Cygwin::isPICDefault() const { + return getArch() == llvm::Triple::x86_64 || + getArch() == llvm::Triple::aarch64; +} + +bool toolchains::Cygwin::isPIEDefault(const llvm::opt::ArgList &Args) const { + return false; +} + +bool toolchains::Cygwin::isPICDefaultForced() const { return true; } + +llvm::ExceptionHandling +toolchains::Cygwin::GetExceptionModel(const ArgList &Args) const { + if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64 || + getArch() == llvm::Triple::arm || getArch() == llvm::Triple::thumb) + return llvm::ExceptionHandling::WinEH; + return llvm::ExceptionHandling::DwarfCFI; +} + +SanitizerMask toolchains::Cygwin::getSupportedSanitizers() const { + SanitizerMask Res = ToolChain::getSupportedSanitizers(); + Res |= SanitizerKind::Address; + Res |= SanitizerKind::PointerCompare; + Res |= SanitizerKind::PointerSubtract; + Res |= SanitizerKind::Vptr; + return Res; +} + +void toolchains::Cygwin::AddCudaIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); +} + +void toolchains::Cygwin::AddHIPIncludeArgs(const ArgList &DriverArgs, + ArgStringList &CC1Args) const { + RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args); +} + +void toolchains::Cygwin::printVerboseInfo(raw_ostream &OS) const { + CudaInstallation.print(OS); + RocmInstallation.print(OS); +} + +void toolchains::Cygwin::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; + + addSystemInclude(DriverArgs, CC1Args, + Base + SubdirName + llvm::sys::path::get_separator() + + "include"); + addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/usr/local/include"); + addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/usr/include"); + addSystemInclude(DriverArgs, CC1Args, getDriver().SysRoot + "/usr/include/w32api"); +} + +void toolchains::Cygwin::addClangTargetOptions( + const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args, + Action::OffloadKind DeviceOffloadKind) const { + if (Arg *A = DriverArgs.getLastArg(options::OPT_mguard_EQ)) { + StringRef GuardArgs = A->getValue(); + if (GuardArgs == "none") { + // Do nothing. + } else if (GuardArgs == "cf") { + // Emit CFG instrumentation and the table of address-taken functions. + CC1Args.push_back("-cfguard"); + } else if (GuardArgs == "cf-nochecks") { + // Emit only the table of address-taken functions. + CC1Args.push_back("-cfguard-no-checks"); + } else { + getDriver().Diag(diag::err_drv_unsupported_option_argument) + << A->getSpelling() << GuardArgs; + } + } + + if (Arg *A = DriverArgs.getLastArgNoClaim(options::OPT_mthreads)) + A->ignoreTargetSpecific(); +} + +void toolchains::Cygwin::AddClangCXXStdlibIncludeArgs( + const ArgList &DriverArgs, ArgStringList &CC1Args) const { + if (DriverArgs.hasArg(options::OPT_nostdinc, options::OPT_nostdlibinc, + options::OPT_nostdincxx)) + return; + + StringRef Slash = llvm::sys::path::get_separator(); + + switch (GetCXXStdlibType(DriverArgs)) { + case ToolChain::CST_Libcxx: + addSystemInclude(DriverArgs, CC1Args, + Base + "include" + Slash + "c++" + Slash + "v1"); + break; + + case ToolChain::CST_Libstdcxx: + llvm::SmallVector<llvm::SmallString<1024>, 7> CppIncludeBases; + CppIncludeBases.emplace_back(Base); + llvm::sys::path::append(CppIncludeBases[0], SubdirName, "include", "c++"); + CppIncludeBases.emplace_back(Base); + llvm::sys::path::append(CppIncludeBases[1], SubdirName, "include", "c++", + Ver); + CppIncludeBases.emplace_back(Base); + llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver); + CppIncludeBases.emplace_back(GccLibDir); + llvm::sys::path::append(CppIncludeBases[3], "include", "c++"); + for (auto &CppIncludeBase : CppIncludeBases) { + addSystemInclude(DriverArgs, CC1Args, CppIncludeBase); + CppIncludeBase += Slash; + addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + TripleDirName); + addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward"); + } + break; + } +} + +static bool testTriple(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) { + // If an explicit sysroot is set, that will be used and we shouldn't try to + // detect anything else. + std::string SubdirName; + if (D.SysRoot.size()) + return true; + llvm::Triple LiteralTriple = getLiteralTriple(D, Triple); + if (llvm::ErrorOr<std::string> TargetSubdir = + findClangRelativeSysroot(D, LiteralTriple, Triple, SubdirName)) + return true; + if (llvm::ErrorOr<std::string> GPPName = findGcc(LiteralTriple, Triple)) + return true; + // If we neither found a colocated sysroot or a matching gcc executable, + // conclude that we can't know if this is the correct spelling of the triple. + return false; +} + +static llvm::Triple adjustTriple(const Driver &D, const llvm::Triple &Triple, + const ArgList &Args) { + // First test if the original triple can find a sysroot with the triple + // name. + if (testTriple(D, Triple, Args)) + return Triple; + llvm::SmallVector<llvm::StringRef, 3> Archs; + // If not, test a couple other possible arch names that might be what was + // intended. + if (Triple.getArch() == llvm::Triple::x86) { + Archs.emplace_back("i386"); + Archs.emplace_back("i586"); + Archs.emplace_back("i686"); + } else if (Triple.getArch() == llvm::Triple::arm || + Triple.getArch() == llvm::Triple::thumb) { + Archs.emplace_back("armv7"); + } + for (auto A : Archs) { + llvm::Triple TestTriple(Triple); + TestTriple.setArchName(A); + if (testTriple(D, TestTriple, Args)) + return TestTriple; + } + // If none was found, just proceed with the original value. + return Triple; +} + +void toolchains::Cygwin::fixTripleArch(const Driver &D, llvm::Triple &Triple, + const ArgList &Args) { + if (Triple.getArch() == llvm::Triple::x86 || + Triple.getArch() == llvm::Triple::arm || + Triple.getArch() == llvm::Triple::thumb) + Triple = adjustTriple(D, Triple, Args); +} diff --git a/clang/lib/Driver/ToolChains/Cygwin.h b/clang/lib/Driver/ToolChains/Cygwin.h new file mode 100644 index 0000000000000..9866863389eb6 --- /dev/null +++ b/clang/lib/Driver/ToolChains/Cygwin.h @@ -0,0 +1,125 @@ +//===--- Cygwin.h - Cygwin ToolChain Implementations --------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CYGWIN_H +#define LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CYGWIN_H + +#include "Cuda.h" +#include "Gnu.h" +#include "ROCm.h" +#include "clang/Driver/Tool.h" +#include "clang/Driver/ToolChain.h" +#include "llvm/Support/ErrorOr.h" + +namespace clang { +namespace driver { +namespace tools { + +/// Cygwin -- Directly call GNU Binutils assembler and linker +namespace Cygwin { +class LLVM_LIBRARY_VISIBILITY Assembler : public Tool { +public: + Assembler(const ToolChain &TC) : Tool("Cygwin::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("Cygwin::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, + llvm::opt::ArgStringList &CmdArgs) const; +}; +} // end namespace Cygwin +} // end namespace tools + +namespace toolchains { + +class LLVM_LIBRARY_VISIBILITY Cygwin : public ToolChain { +public: + Cygwin(const Driver &D, const llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + + static void fixTripleArch(const Driver &D, llvm::Triple &Triple, + const llvm::opt::ArgList &Args); + + bool HasNativeLLVMSupport() const override; + + UnwindTableLevel + getDefaultUnwindTableLevel(const llvm::opt::ArgList &Args) const override; + bool isPICDefault() const override; + bool isPIEDefault(const llvm::opt::ArgList &Args) const override; + bool isPICDefaultForced() const override; + + SanitizerMask getSupportedSanitizers() const override; + + llvm::ExceptionHandling GetExceptionModel( + const llvm::opt::ArgList &Args) const override; + + void + AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + void + addClangTargetOptions(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args, + Action::OffloadKind DeviceOffloadKind) const override; + void AddClangCXXStdlibIncludeArgs( + const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + + void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + void AddHIPIncludeArgs(const llvm::opt::ArgList &DriverArgs, + llvm::opt::ArgStringList &CC1Args) const override; + + void printVerboseInfo(raw_ostream &OS) const override; + + unsigned GetDefaultDwarfVersion() const override { return 4; } + +protected: + Tool *getTool(Action::ActionClass AC) const override; + Tool *buildLinker() const override; + Tool *buildAssembler() const override; + +private: + CudaInstallationDetector CudaInstallation; + RocmInstallationDetector RocmInstallation; + + std::string Base; + std::string GccLibDir; + clang::driver::toolchains::Generic_GCC::GCCVersion GccVer; + std::string Ver; + std::string SubdirName; + std::string TripleDirName; + mutable std::unique_ptr<tools::gcc::Preprocessor> Preprocessor; + mutable std::unique_ptr<tools::gcc::Compiler> Compiler; + void findGccLibDir(const llvm::Triple &LiteralTriple); + + bool NativeLLVMSupport; +}; + +} // end namespace toolchains +} // end namespace driver +} // end namespace clang + +#endif // LLVM_CLANG_LIB_DRIVER_TOOLCHAINS_CYGWIN_H diff --git a/clang/lib/Lex/InitHeaderSearch.cpp b/clang/lib/Lex/InitHeaderSearch.cpp index 5b1b7c859c85d..344a5cb88cef9 100644 --- a/clang/lib/Lex/InitHeaderSearch.cpp +++ b/clang/lib/Lex/InitHeaderSearch.cpp @@ -205,9 +205,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, if (HSOpts.UseStandardSystemIncludes) { switch (os) { case llvm::Triple::Win32: - if (triple.getEnvironment() != llvm::Triple::Cygnus) - break; - [[fallthrough]]; + break; default: // FIXME: temporary hack: hard-coded paths. AddPath("/usr/local/include", System, false); @@ -242,14 +240,7 @@ void InitHeaderSearch::AddDefaultCIncludePaths(const llvm::Triple &triple, switch (os) { case llvm::Triple::Win32: - switch (triple.getEnvironment()) { - default: llvm_unreachable("Include management is handled in the driver."); - case llvm::Triple::Cygnus: - AddPath("/usr/include/w32api", System, false); - break; - case llvm::Triple::GNU: - break; - } + llvm_unreachable("Include management is handled in the driver."); break; default: break; @@ -268,17 +259,7 @@ void InitHeaderSearch::AddDefaultCPlusPlusIncludePaths( llvm::Triple::OSType os = triple.getOS(); switch (os) { case llvm::Triple::Win32: - switch (triple.getEnvironment()) { - default: llvm_unreachable("Include management is handled in the driver."); - case llvm::Triple::Cygnus: - // Cygwin-1.7 - AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.7.3"); - AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.5.3"); - AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.4"); - // g++-4 / Cygwin-1.5 - AddMinGWCPlusPlusIncludePaths("/usr/lib/gcc", "i686-pc-cygwin", "4.3.2"); - break; - } + llvm_unreachable("Include management is handled in the driver."); break; default: break; @@ -310,10 +291,7 @@ bool InitHeaderSearch::ShouldAddDefaultIncludePaths( return false; case llvm::Triple::Win32: - if (triple.getEnvironment() != llvm::Triple::Cygnus || - triple.isOSBinFormatMachO()) - return false; - break; + return false; case llvm::Triple::UnknownOS: if (triple.isWasm()) _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits