$OpenBSD: patch-tools_clang_lib_Driver_ToolChains_OpenBSD_cpp,v 1.19 2021/09/19 17:49:23 jca Exp $

- Add support for building against libestdc++ from ports-gcc.
- Allow the compiler driver to link the libclang_rt.profile library.
- Use Component in OpenBSD::getCompilerRT to find libraries.

Index: tools/clang/lib/Driver/ToolChains/OpenBSD.cpp
--- tools/clang/lib/Driver/ToolChains/OpenBSD.cpp.orig
+++ tools/clang/lib/Driver/ToolChains/OpenBSD.cpp
@@ -12,6 +12,8 @@
 #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/Options.h"
 #include "clang/Driver/SanitizerArgs.h"
 #include "llvm/Option/ArgList.h"
@@ -191,7 +193,13 @@ void openbsd::Linker::ConstructJob(Compilation &C, con
     }
     // FIXME: For some reason GCC passes -lgcc before adding
     // the default system libraries. Just mimic this for now.
-    CmdArgs.push_back("-lcompiler_rt");
+    if (ToolChain.GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
+      CmdArgs.push_back("-lcompiler_rt");
+    else {
+      CmdArgs.push_back("-L${LOCALBASE}/lib/gcc/${GCC_CONFIG}/${GCC_VER}");
+      CmdArgs.push_back("-L${LOCALBASE}/lib"); // XXX nasty
+      CmdArgs.push_back("-lgcc");
+    }
 
     if (Args.hasArg(options::OPT_pthread)) {
       if (!Args.hasArg(options::OPT_shared) && Args.hasArg(options::OPT_pg))
@@ -207,7 +215,10 @@ void openbsd::Linker::ConstructJob(Compilation &C, con
         CmdArgs.push_back("-lc");
     }
 
-    CmdArgs.push_back("-lcompiler_rt");
+    if (ToolChain.GetCXXStdlibType(Args) == ToolChain::CST_Libcxx)
+      CmdArgs.push_back("-lcompiler_rt");
+    else
+      CmdArgs.push_back("-lgcc");
   }
 
   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) {
@@ -220,6 +231,8 @@ void openbsd::Linker::ConstructJob(Compilation &C, con
     CmdArgs.push_back(Args.MakeArgString(ToolChain.GetFilePath(crtend)));
   }
 
+  ToolChain.addProfileRTLibs(Args, CmdArgs);
+
   const char *Exec = Args.MakeArgString(ToolChain.GetLinkerPath());
   C.addCommand(std::make_unique<Command>(
       JA, *this, ResponseFileSupport::AtFileCurCP(), Exec, CmdArgs, Inputs));
@@ -288,20 +301,21 @@ void OpenBSD::addLibCxxIncludePaths(const llvm::opt::A
                    getDriver().SysRoot + "/usr/include/c++/v1");
 }
 
-void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args,
-                                  ArgStringList &CmdArgs) const {
-  bool Profiling = Args.hasArg(options::OPT_pg);
 
-  CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
-  CmdArgs.push_back(Profiling ? "-lc++abi_p" : "-lc++abi");
-}
-
 std::string OpenBSD::getCompilerRT(const ArgList &Args,
                                    StringRef Component,
                                    FileType Type) const {
-  SmallString<128> Path(getDriver().SysRoot);
-  llvm::sys::path::append(Path, "/usr/lib/libcompiler_rt.a");
-  return std::string(Path.str());
+  if (Component == "builtins") {
+    SmallString<128> Path(getDriver().SysRoot);
+    llvm::sys::path::append(Path, "/usr/lib/libcompiler_rt.a");
+    return std::string(Path.str());
+  } else {
+    SmallString<128> P(getDriver().ResourceDir);
+    std::string CRTBasename =
+        getCompilerRTBasename(Args, Component, Type, /*AddArch=*/false);
+    llvm::sys::path::append(P, "lib", CRTBasename);
+    return std::string(P.str());
+  }
 }
 
 Tool *OpenBSD::buildAssembler() const {
@@ -311,3 +325,70 @@ Tool *OpenBSD::buildAssembler() const {
 Tool *OpenBSD::buildLinker() const { return new tools::openbsd::Linker(*this); }
 
 bool OpenBSD::HasNativeLLVMSupport() const { return true; }
+
+ToolChain::CXXStdlibType OpenBSD::GetCXXStdlibType(const ArgList &Args) const {
+  if (Arg *A = Args.getLastArg(options::OPT_stdlib_EQ)) {
+    StringRef Value = A->getValue();
+    if (Value == "libstdc++")
+      return ToolChain::CST_Libstdcxx;
+    if (Value == "libc++")
+      return ToolChain::CST_Libcxx;
+
+    getDriver().Diag(clang::diag::err_drv_invalid_stdlib_name)
+        << A->getAsString(Args);
+  }
+  switch (getTriple().getArch()) {
+  case llvm::Triple::aarch64:
+  case llvm::Triple::arm:
+  case llvm::Triple::mips64:
+  case llvm::Triple::mips64el:
+  case llvm::Triple::ppc:
+  case llvm::Triple::ppc64:
+  case llvm::Triple::riscv64:
+  case llvm::Triple::x86:
+  case llvm::Triple::x86_64:
+    return ToolChain::CST_Libcxx;
+    break;
+  default:
+    return ToolChain::CST_Libstdcxx;
+    break;
+  }
+}
+
+void OpenBSD::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
+                                          ArgStringList &CC1Args) const {
+  if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
+      DriverArgs.hasArg(options::OPT_nostdincxx))
+    return;
+
+  switch (GetCXXStdlibType(DriverArgs)) {
+  case ToolChain::CST_Libcxx:
+    addSystemInclude(DriverArgs, CC1Args,
+                     getDriver().SysRoot + "/usr/include/c++/v1");
+    break;
+  case ToolChain::CST_Libstdcxx:
+    addSystemInclude(DriverArgs, CC1Args,
+                     getDriver().SysRoot + "${LOCALBASE}/include/c++/${GCC_VER}");
+    addSystemInclude(DriverArgs, CC1Args,
+                     getDriver().SysRoot + "${LOCALBASE}/include/c++/${GCC_VER}/${GCC_CONFIG}");
+    addSystemInclude(DriverArgs, CC1Args,
+                     getDriver().SysRoot + "${LOCALBASE}/include/c++/${GCC_VER}/backward");
+    break;
+  }
+}
+
+void OpenBSD::AddCXXStdlibLibArgs(const ArgList &Args,
+                                 ArgStringList &CmdArgs) const {
+  bool Profiling = Args.hasArg(options::OPT_pg);
+
+  switch (GetCXXStdlibType(Args)) {
+  case ToolChain::CST_Libcxx:
+    CmdArgs.push_back(Profiling ? "-lc++_p" : "-lc++");
+    CmdArgs.push_back(Profiling ? "-lc++abi_p" : "-lc++abi");
+    CmdArgs.push_back(Profiling ? "-lpthread_p" : "-lpthread");
+    break;
+  case ToolChain::CST_Libstdcxx:
+    CmdArgs.push_back("-lestdc++");
+    break;
+  }
+}
