diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 61f5100f1385a..1b4a94d72cc0a 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -2224,6 +2224,12 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( const llvm::Triple &TargetTriple, SmallVectorImpl &Prefixes, StringRef SysRoot) { + + if (TargetTriple.isOSHaiku()) { + Prefixes.push_back(concat(SysRoot, "/boot/system/develop/tools")); + return; + } + if (TargetTriple.isOSSolaris()) { // Solaris is a special case. // The GCC installation is under diff --git a/clang/lib/Driver/ToolChains/Haiku.cpp b/clang/lib/Driver/ToolChains/Haiku.cpp index 55fc0533f699f..33d71f030e51c 100644 --- a/clang/lib/Driver/ToolChains/Haiku.cpp +++ b/clang/lib/Driver/ToolChains/Haiku.cpp @@ -9,20 +9,141 @@ #include "Haiku.h" #include "CommonArgs.h" #include "clang/Config/config.h" +#include "clang/Driver/Compilation.h" #include "llvm/Support/Path.h" using namespace clang::driver; +using namespace clang::driver::tools; using namespace clang::driver::toolchains; using namespace clang; using namespace llvm::opt; +void haiku::Linker::ConstructJob(Compilation &C, const JobAction &JA, + const InputInfo &Output, + const InputInfoList &Inputs, + const ArgList &Args, + const char *LinkingOutput) const { + const toolchains::Haiku &ToolChain = + static_cast(getToolChain()); + const Driver &D = ToolChain.getDriver(); + const llvm::Triple::ArchType Arch = ToolChain.getArch(); + const bool Static = Args.hasArg(options::OPT_static); + const bool Shared = Args.hasArg(options::OPT_shared); + 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); + + // Silence warning for "clang -pie foo.o -o foo" + Args.ClaimAllArgs(options::OPT_pie); + + if (!D.SysRoot.empty()) + CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); + + CmdArgs.push_back("--eh-frame-hdr"); + if (Static) { + CmdArgs.push_back("-Bstatic"); + } else { + if (Args.hasArg(options::OPT_rdynamic)) + CmdArgs.push_back("-export-dynamic"); + if (Shared) + CmdArgs.push_back("-shared"); + CmdArgs.push_back("--enable-new-dtags"); + } + + CmdArgs.push_back("-shared"); + + if (!Shared) + CmdArgs.push_back("--no-undefined"); + + if (Arch == llvm::Triple::riscv64) + CmdArgs.push_back("-X"); + + assert((Output.isFilename() || Output.isNothing()) && "Invalid output."); + if (Output.isFilename()) { + CmdArgs.push_back("-o"); + CmdArgs.push_back(Output.getFilename()); + } + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, + options::OPT_r)) { + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crti.o"))); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtbeginS.o"))); + if (!Shared) + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("start_dyn.o"))); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("init_term_dyn.o"))); + } + + Args.AddAllArgs(CmdArgs, + {options::OPT_L, options::OPT_T_Group, options::OPT_s, + options::OPT_t, options::OPT_Z_Flag, options::OPT_r}); + ToolChain.AddFilePathLibArgs(Args, CmdArgs); + + addLinkerCompressDebugSectionsOption(ToolChain, Args, CmdArgs); + AddLinkerInputs(ToolChain, Inputs, Args, CmdArgs, JA); + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs, + options::OPT_r)) { + // Use the static OpenMP runtime with -static-openmp + bool StaticOpenMP = Args.hasArg(options::OPT_static_openmp) && !Static; + addOpenMPRuntime(CmdArgs, ToolChain, Args, StaticOpenMP); + + if (D.CCCIsCXX() && ToolChain.ShouldLinkCXXStdlib(Args)) + ToolChain.AddCXXStdlibLibArgs(Args, CmdArgs); + + CmdArgs.push_back("-lgcc"); + + CmdArgs.push_back("--push-state"); + CmdArgs.push_back("--as-needed"); + CmdArgs.push_back("-lgcc_s"); + CmdArgs.push_back("--no-as-needed"); + CmdArgs.push_back("--pop-state"); + + CmdArgs.push_back("-lroot"); + + CmdArgs.push_back("-lgcc"); + + CmdArgs.push_back("--push-state"); + CmdArgs.push_back("--as-needed"); + CmdArgs.push_back("-lgcc_s"); + CmdArgs.push_back("--no-as-needed"); + CmdArgs.push_back("--pop-state"); + } + + // No need to do anything for pthreads. Claim argument to avoid warning. + Args.claimAllArgs(options::OPT_pthread, options::OPT_pthreads); + + if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles, + options::OPT_r)) { + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtendS.o"))); + CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath("crtn.o"))); + } + + ToolChain.addProfileRTLibs(Args, CmdArgs); + + const char *Exec = Args.MakeArgString(getToolChain().GetLinkerPath()); + C.addCommand(std::make_unique(JA, *this, + ResponseFileSupport::AtFileCurCP(), + Exec, CmdArgs, Inputs, Output)); +} + /// Haiku - Haiku tool chain which can call as(1) and ld(1) directly. Haiku::Haiku(const Driver &D, const llvm::Triple& Triple, const ArgList &Args) : Generic_ELF(D, Triple, Args) { + GCCInstallation.init(Triple, Args); + getFilePaths().push_back(concat(getDriver().SysRoot, "/boot/system/lib")); getFilePaths().push_back(concat(getDriver().SysRoot, "/boot/system/develop/lib")); + + if (GCCInstallation.isValid()) + getFilePaths().push_back(GCCInstallation.getInstallPath().str()); } void Haiku::AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, @@ -128,8 +249,6 @@ void Haiku::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, concat(getDriver().SysRoot, "/boot/system/develop/headers/c++/v1")); } -void Haiku::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const { - addLibStdCXXIncludePaths(concat(getDriver().SysRoot, "/boot/system/develop/headers/c++"), - getTriple().str(), "", DriverArgs, CC1Args); -} +Tool *Haiku::buildLinker() const { return new tools::haiku::Linker(*this); } + +bool Haiku::HasNativeLLVMSupport() const { return true; } diff --git a/clang/lib/Driver/ToolChains/Haiku.h b/clang/lib/Driver/ToolChains/Haiku.h index 4b5f21f7ba66b..a34f76e22284c 100644 --- a/clang/lib/Driver/ToolChains/Haiku.h +++ b/clang/lib/Driver/ToolChains/Haiku.h @@ -15,6 +15,25 @@ namespace clang { namespace driver { +namespace tools { + +/// Directly call GNU Binutils assembler and linker +namespace haiku { +class LLVM_LIBRARY_VISIBILITY Linker final : public Tool { +public: + Linker(const ToolChain &TC) : Tool("haiku::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; +}; +} // end namespace haiku +} // end namespace tools + namespace toolchains { class LLVM_LIBRARY_VISIBILITY Haiku : public Generic_ELF { @@ -22,23 +41,27 @@ class LLVM_LIBRARY_VISIBILITY Haiku : public Generic_ELF { Haiku(const Driver &D, const llvm::Triple &Triple, const llvm::opt::ArgList &Args); + bool HasNativeLLVMSupport() const override; + bool IsMathErrnoDefault() const override { return false; } bool IsObjCNonFragileABIDefault() const override { return true; } bool isPICDefault() const override { return true; } + const char *getDefaultLinker() const override { return "ld.lld"; } + void AddClangSystemIncludeArgs( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; void addLibCxxIncludePaths( const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; - void addLibStdCxxIncludePaths( - const llvm::opt::ArgList &DriverArgs, - llvm::opt::ArgStringList &CC1Args) const override; unsigned GetDefaultDwarfVersion() const override { return 4; } bool GetDefaultStandaloneDebug() const override { return true; } + +protected: + Tool *buildLinker() const override; }; } // end namespace toolchains diff --git a/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/lib/crti.o b/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/lib/crti.o new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/lib/crtn.o b/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/lib/crtn.o new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/lib/init_term_dyn.o b/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/lib/init_term_dyn.o new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/lib/start_dyn.o b/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/lib/start_dyn.o new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/tools/lib/gcc/x86_64-unknown-haiku/13.2.0/crtbegin.o b/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/tools/lib/gcc/x86_64-unknown-haiku/13.2.0/crtbegin.o new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/tools/lib/gcc/x86_64-unknown-haiku/13.2.0/crtbeginS.o b/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/tools/lib/gcc/x86_64-unknown-haiku/13.2.0/crtbeginS.o new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/tools/lib/gcc/x86_64-unknown-haiku/13.2.0/crtend.o b/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/tools/lib/gcc/x86_64-unknown-haiku/13.2.0/crtend.o new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/tools/lib/gcc/x86_64-unknown-haiku/13.2.0/crtendS.o b/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/tools/lib/gcc/x86_64-unknown-haiku/13.2.0/crtendS.o new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/tools/lib/gcc/x86_64-unknown-haiku/13.2.0/include/c++/.keep b/clang/test/Driver/Inputs/haiku_x86_64_tree/boot/system/develop/tools/lib/gcc/x86_64-unknown-haiku/13.2.0/include/c++/.keep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/haiku.c b/clang/test/Driver/haiku.c index 728173a78ccf9..021ab522be06e 100644 --- a/clang/test/Driver/haiku.c +++ b/clang/test/Driver/haiku.c @@ -36,3 +36,32 @@ // CHECK-C-HEADER-PATH: "-internal-isystem" "/boot/system/develop/headers/gnu" // CHECK-C-HEADER-PATH: "-internal-isystem" "/boot/system/develop/headers/posix" // CHECK-C-HEADER-PATH: "-internal-isystem" "/boot/system/develop/headers" + +// Check x86_64-unknown-haiku, X86_64 +// RUN: %clang -### %s 2>&1 --target=x86_64-unknown-haiku \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/haiku_x86_64_tree \ +// RUN: | FileCheck --check-prefix=CHECK-LD-X86_64 %s +// CHECK-LD-X86_64: "-cc1" "-triple" "x86_64-unknown-haiku" +// CHECK-LD-X86_64-SAME: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-LD-X86_64: "{{.*}}ld{{(.exe)?}}" +// CHECK-LD-X86_64-SAME: "--no-undefined" +// CHECK-LD-X86_64-SAME: "[[SYSROOT]]/boot/system/develop/lib/crti.o" +// CHECK-LD-X86_64-SAME: {{^}} "[[SYSROOT]]/boot/system/develop/tools/lib/gcc/x86_64-unknown-haiku/13.2.0/crtbeginS.o" +// CHECK-LD-X86_64-SAME: {{^}} "[[SYSROOT]]/boot/system/develop/lib/start_dyn.o" +// CHECK-LD-X86_64-SAME: {{^}} "[[SYSROOT]]/boot/system/develop/lib/init_term_dyn.o" +// CHECK-LD-X86_64-SAME: "-lgcc" "--push-state" "--as-needed" "-lgcc_s" "--no-as-needed" "--pop-state" +// CHECK-LD-X86_64-SAME: {{^}} "-lroot" +// CHECK-LD-X86_64-SAME: {{^}} "-lgcc" "--push-state" "--as-needed" "-lgcc_s" "--no-as-needed" "--pop-state" +// CHECK-LD-X86_64-SAME: {{^}} "[[SYSROOT]]/boot/system/develop/tools/lib/gcc/x86_64-unknown-haiku/13.2.0/crtendS.o" +// CHECK-LD-X86_64-SAME: {{^}} "[[SYSROOT]]/boot/system/develop/lib/crtn.o" + +// Check the right flags are present with -shared +// RUN: %clang -### %s -shared 2>&1 --target=x86_64-unknown-haiku \ +// RUN: --gcc-toolchain="" \ +// RUN: --sysroot=%S/Inputs/haiku_x86_64_tree \ +// RUN: | FileCheck --check-prefix=CHECK-X86_64-SHARED %s +// CHECK-X86_64-SHARED: "-cc1" "-triple" "x86_64-unknown-haiku" +// CHECK-X86_64-SHARED-SAME: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-X86_64-SHARED: "{{.*}}ld{{(.exe)?}}" +// CHECK-X86_64-SHARED-NOT: "[[SYSROOT]]/boot/system/develop/lib/start_dyn.o" diff --git a/clang/test/Driver/haiku.cpp b/clang/test/Driver/haiku.cpp index 64018e8236b28..982227ff65fef 100644 --- a/clang/test/Driver/haiku.cpp +++ b/clang/test/Driver/haiku.cpp @@ -2,7 +2,8 @@ // RUN: %clangxx --target=x86_64-unknown-haiku --stdlib=libstdc++ -### %s 2>&1 \ // RUN: --sysroot=%S/Inputs/haiku_x86_64_tree \ // RUN: | FileCheck --check-prefix=CHECK-LIBSTDCXX-HEADER-PATH %s -// CHECK-LIBSTDCXX-HEADER-PATH: "-internal-isystem" "[[SYSROOT:[^"]+]]/boot/system/develop/headers/c++" +// CHECK-LIBSTDCXX-HEADER-PATH: "-internal-isystem" "[[SYSROOT:[^"]+]]/boot/system/develop/tools/lib/gcc/x86_64-unknown-haiku/13.2.0/../../../gcc/x86_64-unknown-haiku/13.2.0/include/c++/" +// CHECK-LIBSTDCXX-HEADER-PATH-SAME: "-internal-isystem" "[[SYSROOT:[^"]+]]/boot/system/develop/tools/lib/gcc/x86_64-unknown-haiku/13.2.0/../../../gcc/x86_64-unknown-haiku/13.2.0/include/c++//backward" // Check the C++ header path (when using libc++) // RUN: %clangxx --target=x86_64-unknown-haiku --stdlib=libc++ -### %s 2>&1 \