From 1f7c21782a4bee4c0d9b6078a3dacf7c708acfda Mon Sep 17 00:00:00 2001
From: Eleni Mathioulaki <emathioulaki@athenarc.gr>
Date: Tue, 13 Feb 2024 00:42:29 +0100
Subject: [PATCH] update llvm to adapt to spack v0.21.1

---
 .../add-include-for-libelf-llvm-12-14.patch   |  26 +
 .../llvm/add-include-for-libelf-llvm-15.patch |  26 +
 packages/llvm/no_cyclades9.patch              |   5 +
 packages/llvm/package.py                      | 511 +++++++++++++-----
 packages/llvm/sanitizer-ipc_perm_mode.patch   |  52 +-
 packages/llvm/xray_buffer_queue-cstddef.patch |  10 +-
 6 files changed, 487 insertions(+), 143 deletions(-)
 create mode 100644 packages/llvm/add-include-for-libelf-llvm-12-14.patch
 create mode 100644 packages/llvm/add-include-for-libelf-llvm-15.patch

diff --git a/packages/llvm/add-include-for-libelf-llvm-12-14.patch b/packages/llvm/add-include-for-libelf-llvm-12-14.patch
new file mode 100644
index 00000000..f585d08d
--- /dev/null
+++ b/packages/llvm/add-include-for-libelf-llvm-12-14.patch
@@ -0,0 +1,26 @@
+From e5f0939fde75f769c53c6c99c9ed6886e7d58c43 Mon Sep 17 00:00:00 2001
+From: Harmen Stoppels <me@harmenstoppels.nl>
+Date: Wed, 23 Aug 2023 11:35:23 +0200
+Subject: [PATCH] Add corresponding -I for libelf.h
+
+Funnily enough, it's added to `include_directories` in multiple places,
+except where it's necessary.
+---
+ openmp/libomptarget/plugins/amdgpu/CMakeLists.txt | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt b/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt
+index 92523c23f68b..52e1923f97b7 100644
+--- a/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt
++++ b/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt
+@@ -51,6 +51,7 @@ endif()
+ include_directories(
+   ${CMAKE_CURRENT_SOURCE_DIR}/impl
+   ${LIBOMPTARGET_LLVM_INCLUDE_DIRS}
++  ${LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR}
+ )
+ 
+ set(LIBOMPTARGET_DLOPEN_LIBHSA OFF)
+-- 
+2.39.2
+
diff --git a/packages/llvm/add-include-for-libelf-llvm-15.patch b/packages/llvm/add-include-for-libelf-llvm-15.patch
new file mode 100644
index 00000000..7a7d57d1
--- /dev/null
+++ b/packages/llvm/add-include-for-libelf-llvm-15.patch
@@ -0,0 +1,26 @@
+From 5e149c3ec8118ad8f3d20a30ce5d3fbac4072515 Mon Sep 17 00:00:00 2001
+From: Harmen Stoppels <me@harmenstoppels.nl>
+Date: Wed, 23 Aug 2023 11:35:23 +0200
+Subject: [PATCH] Add corresponding -I for libelf.h
+
+Funnily enough, it's added to `include_directories` in multiple places,
+except where it's necessary.
+---
+ openmp/libomptarget/plugins/amdgpu/CMakeLists.txt | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt b/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt
+index 66bf680d15c7..6be12ab6d7f8 100644
+--- a/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt
++++ b/openmp/libomptarget/plugins/amdgpu/CMakeLists.txt
+@@ -99,6 +99,7 @@ target_include_directories(
+   PRIVATE
+   ${LIBOMPTARGET_INCLUDE_DIR}
+   ${CMAKE_CURRENT_SOURCE_DIR}/impl
++  ${LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR}
+ )
+ 
+ 
+-- 
+2.39.2
+
diff --git a/packages/llvm/no_cyclades9.patch b/packages/llvm/no_cyclades9.patch
index 7532865e..55cb70d1 100644
--- a/packages/llvm/no_cyclades9.patch
+++ b/packages/llvm/no_cyclades9.patch
@@ -1,3 +1,8 @@
+# This is a backport of https://reviews.llvm.org/D102059.
+#
+# We need the patch to be applicable when="@:9" and, therefore, cannot fetch
+# it from the upstream repo.
+
 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
 +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interceptors_ioctl.inc
 @@ -370,9 +370,0 @@
diff --git a/packages/llvm/package.py b/packages/llvm/package.py
index dd54e7c0..333c9f0e 100644
--- a/packages/llvm/package.py
+++ b/packages/llvm/package.py
@@ -26,7 +26,7 @@ class Llvm(CMakePackage, CudaPackage):
     url = "https://github.com/llvm/llvm-project/archive/llvmorg-7.1.0.tar.gz"
     list_url = "https://releases.llvm.org/download.html"
     git = "https://github.com/llvm/llvm-project"
-    maintainers("trws", "haampie")
+    maintainers("trws", "haampie", "skosukhin")
 
     tags = ["e4s"]
 
@@ -35,6 +35,14 @@ class Llvm(CMakePackage, CudaPackage):
     family = "compiler"  # Used by lmod
 
     version("main", branch="main")
+    version("17.0.4", sha256="46200b79f52a02fe26d0a43fd856ab6ceff49ab2a0b7c240ac4b700a6ada700c")
+    version("17.0.3", sha256="1e3d9d04fb5fbd8d0080042ad72c7e2a5c68788b014b186647a604dbbdd625d2")
+    version("17.0.2", sha256="dcba3eb486973dce45b6edfe618f3f29b703ae7e6ef9df65182fb50fb6fe4235")
+    version("17.0.1", sha256="d51b10be66c10a6a81f4c594b554ffbf1063ffbadcb810af37d1f88d6e0b49dd")
+    version("16.0.6", sha256="56b2f75fdaa95ad5e477a246d3f0d164964ab066b4619a01836ef08e475ec9d5")
+    version("16.0.5", sha256="e0fbca476693fcafa125bc71c8535587b6d9950293122b66b262bb4333a03942")
+    version("16.0.4", sha256="10c3fe1757d2e4f1cd7745dc548ecf687680a71824ec81701c38524c2a0753e2")
+    version("16.0.3", sha256="0bd71bc687a4e5a250c40afb0decefc50c85178fcce726137b682039de63919b")
     version("16.0.2", sha256="97c3c6aafb53c4bb0ed2781a18d6f05e75445e24bb1dc57a32b74f8d710ac19f")
     version("16.0.1", sha256="b5a9ff1793b1e2d388a3819bf35797002b1d2e40bb35a10c65605e0ea1435271")
     version("16.0.0", sha256="cba969a0782a3a398658d439f047b5e548ea04724f4fbfdbe17cfc946f4cd3ed")
@@ -74,44 +82,78 @@ class Llvm(CMakePackage, CudaPackage):
     version("5.0.1", sha256="84ca454abf262579814a2a2b846569f6e0cb3e16dc33ca3642b4f1dff6fbafd3")
     version("5.0.0", sha256="1f1843315657a4371d8ca37f01265fa9aae17dbcf46d2d0a95c1fdb3c6a4bab6")
 
-    # NOTE: The debug version of LLVM is an order of magnitude larger than
-    # the release version, and may take up 20-30 GB of space. If you want
-    # to save space, build with `build_type=Release`.
-
     variant(
         "clang", default=True, description="Build the LLVM C/C++/Objective-C compiler frontend"
     )
+
     variant(
         "flang",
         default=False,
-        when="@11: +clang",
         description="Build the LLVM Fortran compiler frontend "
         "(experimental - parser only, needs GCC)",
     )
-    variant(
-        "omp_debug",
-        default=False,
-        description="Include debugging code in OpenMP runtime libraries",
-    )
-    variant("lldb", default=True, when="+clang", description="Build the LLVM debugger")
+    conflicts("+flang", when="@:10")
+    conflicts("+flang", when="~clang")
+
+    variant("lldb", default=True, description="Build the LLVM debugger")
+    conflicts("+lldb", when="~clang")
+
     variant("lld", default=True, description="Build the LLVM linker")
     variant("mlir", default=False, when="@10:", description="Build with MLIR support")
     variant(
-        "internal_unwind", default=True, when="+clang", description="Build the libcxxabi libunwind"
+        "libunwind",
+        values=(
+            "none",
+            conditional("project", when="@:15"),
+            conditional("runtime", when="+clang @6:"),
+        ),
+        default="runtime",
+        description="Build the LLVM unwinder library"
+        "either as a runtime (with just-build Clang) "
+        "or as a project (with the compiler in use)",
     )
     variant(
         "polly",
         default=True,
-        description="Build the LLVM polyhedral optimization plugin, " "only builds for 3.7.0+",
+        description="Build the LLVM polyhedral optimization plugin, only builds for 3.7.0+",
     )
     variant(
-        "libcxx", default=True, when="+clang", description="Build the LLVM C++ standard library"
+        "libcxx",
+        values=(
+            "none",
+            conditional("project", when="@:15"),
+            conditional("runtime", when="+clang @6:"),
+        ),
+        default="runtime",
+        description="Build the LLVM C++ standard library "
+        "either as a runtime (with just-build Clang) "
+        "or as a project (with the compiler in use)",
     )
+
+    variant("libomptarget", default=True, description="Build the OpenMP offloading library")
+    conflicts("+libomptarget", when="~clang")
+    for _p in ["darwin", "windows"]:
+        conflicts("+libomptarget", when="platform={0}".format(_p))
+    del _p
+
+    variant(
+        "libomptarget_debug",
+        default=False,
+        description="Allow debug output with the environment variable LIBOMPTARGET_DEBUG=1",
+    )
+    conflicts("+libomptarget_debug", when="~libomptarget")
+
     variant(
         "compiler-rt",
-        when="+clang",
-        default=True,
-        description="Build LLVM compiler runtime, including sanitizers",
+        values=(
+            "none",
+            conditional("project", when="+clang"),
+            conditional("runtime", when="+clang @6:"),
+        ),
+        default="runtime",
+        description="Build the LLVM compiler runtime, including sanitizers, "
+        "either as a runtime (with just-build Clang) "
+        "or as a project (with the compiler in use)",
     )
     variant(
         "gold",
@@ -132,7 +174,7 @@ class Llvm(CMakePackage, CudaPackage):
     )
     variant(
         "targets",
-        default="none",
+        default="all",
         description=(
             "What targets to build. Spack's target family is always added "
             "(e.g. X86 is automatically enabled when targeting znver2)."
@@ -162,16 +204,19 @@ class Llvm(CMakePackage, CudaPackage):
         multi=True,
     )
     variant(
-        "omp_tsan",
+        "libomp_tsan",
         default=False,
-        when="@6:",
+        # Added in https://reviews.llvm.org/D13072
+        # Removed in https://reviews.llvm.org/D103767
+        when="@4:12",
         description="Build with OpenMP capable thread sanitizer",
     )
     variant(
-        "omp_as_runtime",
-        default=True,
-        when="+clang @12:",
-        description="Build OpenMP runtime via ENABLE_RUNTIME by just-built Clang",
+        "openmp",
+        values=("project", conditional("runtime", when="+clang @12:")),
+        default="runtime",
+        description="Build OpenMP either as a runtime (with just-build Clang) "
+        "or as a project (with the compiler in use)",
     )
     variant(
         "code_signing",
@@ -180,6 +225,7 @@ class Llvm(CMakePackage, CudaPackage):
         description="Enable code-signing on macOS",
     )
     variant("python", default=False, description="Install python bindings")
+    variant("lua", default=True, description="Enable lua scripting inside lldb")
     variant("version_suffix", default="none", description="Add a symbol suffix")
     variant(
         "shlib_symbol_version",
@@ -187,9 +233,12 @@ class Llvm(CMakePackage, CudaPackage):
         description="Add shared library symbol version",
         when="@13:",
     )
-    variant(
-        "z3", default=False, when="+clang @8:", description="Use Z3 for the clang static analyzer"
-    )
+    variant("z3", default=False, description="Use Z3 for the clang static analyzer")
+    conflicts("+z3", when="@:7")
+    conflicts("+z3", when="~clang")
+    conflicts("+lua", when="@:10")
+    conflicts("+lua", when="~lldb")
+
     variant(
         "zstd",
         default=False,
@@ -197,6 +246,8 @@ class Llvm(CMakePackage, CudaPackage):
         description="Enable zstd support for static analyzer / lld",
     )
 
+    provides("libllvm@16", when="@16.0.0:16")
+    provides("libllvm@15", when="@15.0.0:15")
     provides("libllvm@14", when="@14.0.0:14")
     provides("libllvm@13", when="@13.0.0:13")
     provides("libllvm@12", when="@12.0.0:12")
@@ -216,6 +267,12 @@ class Llvm(CMakePackage, CudaPackage):
     depends_on("cmake@3.4.3:", type="build")
     depends_on("cmake@3.13.4:", type="build", when="@12:")
     depends_on("cmake@3.20:", type="build", when="@16:")
+    with when("@:10"):
+        # Versions 10 and older cannot build runtimes with cmake@3.17:
+        # See https://reviews.llvm.org/D77284
+        for runtime in ["libunwind", "libcxx", "compiler-rt"]:
+            depends_on("cmake@:3.16", type="build", when="{0}=runtime".format(runtime))
+        del runtime
     depends_on("python", when="~python", type="build")
     depends_on("pkgconfig", type="build")
 
@@ -228,26 +285,41 @@ class Llvm(CMakePackage, CudaPackage):
     # openmp dependencies
     depends_on("perl-data-dumper", type=("build"))
     depends_on("hwloc")
-    depends_on("hwloc@2.0.1:", when="@9:")
-    depends_on("elf", when="+cuda")  # libomptarget
-    depends_on("libffi", when="+cuda")  # libomptarget
+    depends_on("hwloc@2.0.1:", when="@13")
+    with when("@:15"):
+        depends_on("elf", when="+cuda")
+        depends_on("elf", when="+libomptarget")
+    depends_on("libffi", when="+libomptarget")
 
     # llvm-config --system-libs libraries.
-    depends_on("zlib")
+    depends_on("zlib-api")
 
     # needs zstd cmake config file, which is not added when built with makefile.
     depends_on("zstd build_system=cmake", when="+zstd")
 
     # lldb dependencies
-    with when("+lldb +python"):
-        depends_on("swig")
-        # begin VISIONS: modified, bring upstream
+    with when("+lldb"):
+        depends_on("libedit")
+        depends_on("libxml2")
+        depends_on("lua@5.3", when="+lua")  # purposefully not a range
+        depends_on("ncurses")
+        depends_on("py-six", when="+python")
+        depends_on("swig", when="+lua")
+        depends_on("swig", when="+python")
+        depends_on("xz")
+        # begin VISIONS: modified, bring upstream FIXME: maybe no longer needed
         depends_on("swig@2:4.0", when="@10:")
         depends_on("swig@3:4.0", when="@12:")
         # end VISIONS
-    depends_on("libedit", when="+lldb")
-    depends_on("ncurses", when="+lldb")
-    depends_on("py-six", when="+lldb+python")
+
+    # Use ^swig cause it's triggered by both python & lua scripting in lldb
+    with when("^swig"):
+        depends_on("swig@2:", when="@10:")
+        depends_on("swig@3:", when="@12:")
+        depends_on("swig@4:", when="@17:")
+        # Commits f0a25fe0b746f56295d5c02116ba28d2f965c175 and
+        # 81fc5f7909a4ef5a8d4b5da2a10f77f7cb01ba63 fixed swig 4.1 support
+        depends_on("swig@:4.0", when="@:15")
 
     # gold support, required for some features
     depends_on("binutils+gold+ld+plugins+headers", when="+gold")
@@ -262,17 +334,51 @@ class Llvm(CMakePackage, CudaPackage):
     # Internal compiler error on gcc 8.4 on aarch64 https://bugzilla.redhat.com/show_bug.cgi?id=1958295
     conflicts("%gcc@8.4:8.4.9", when="@12: target=aarch64:")
 
-    # When these versions are concretized, but not explicitly with +libcxx, these
-    # conflicts will enable clingo to set ~libcxx, making the build successful:
-
-    # libc++ of LLVM13, see https://libcxx.llvm.org/#platform-and-compiler-support
-    # @13 does not support %gcc@:10 https://bugs.llvm.org/show_bug.cgi?id=51359#c1
-    # GCC    11     - latest stable release per GCC release page
-    # Clang: 11, 12 - latest two stable releases per LLVM release page
-    # AppleClang 12 - latest stable release per Xcode release page
-    conflicts("%gcc@:10", when="@13:+libcxx")
-    conflicts("%clang@:10", when="@13:+libcxx")
-    conflicts("%apple-clang@:11", when="@13:+libcxx")
+    # libcxx=project imposes compiler conflicts
+    # see https://libcxx.llvm.org/#platform-and-compiler-support for the latest release
+    # and https://github.com/llvm/www-releases for older releases
+    with when("libcxx=project"):
+        for v, compiler_conflicts in {
+            "@7:": {"clang": "@:3.4", "gcc": "@:4.6"},
+            "@9:": {"clang": "@:3.4", "gcc": "@:4"},
+            "@11:": {"clang": "@:3", "gcc": "@:4"},
+            "@13:": {"clang": "@:10", "gcc": "@:10", "apple-clang": "@:11"},
+            "@14:": {
+                "clang": "@:11",
+                "gcc": "@:10",
+                "apple-clang": "@:11",
+                "xlc": "@:17.0",
+                "xlc_r": "@:17.0",
+            },
+            "@15:": {
+                "clang": "@:12",
+                "gcc": "@:11",
+                "apple-clang": "@:12",
+                "xlc": "@:17.0",
+                "xlc_r": "@:17.0",
+            },
+            "@16:": {
+                "clang": "@:13",
+                "gcc": "@:11",
+                "apple-clang": "@:13",
+                "xlc": "@:17.0",
+                "xlc_r": "@:17.0",
+            },
+        }.items():
+            with when(v):
+                for comp in spack.compilers.supported_compilers():
+                    conflicts("%{0}{1}".format(comp, compiler_conflicts.get(comp, "")))
+        del v, compiler_conflicts, comp
+
+    # libomptarget
+    conflicts("+cuda", when="@15:")  # +cuda variant is obselete since LLVM 15
+    conflicts(
+        "targets=none",
+        when="+libomptarget",
+        msg="Non-host backends needed for offloading, set targets=all",
+    )
+    # See https://github.com/spack/spack/pull/32476#issuecomment-1573770361
+    conflicts("~lld", when="+libomptarget")
 
     # cuda_arch value must be specified
     conflicts("cuda_arch=none", when="+cuda", msg="A value for cuda_arch must be specified.")
@@ -282,7 +388,7 @@ class Llvm(CMakePackage, CudaPackage):
     # Fixed in upstream versions of both
     conflicts("^cmake@3.19.0", when="@6:11.0.0")
 
-    # begin VISIONS (added)
+    # begin VISIONS (added) FIXME: check patches
     variant('visionary', default=False,
             description="Include patches necessary for visionary python "
             "bindings generator")
@@ -308,84 +414,197 @@ class Llvm(CMakePackage, CudaPackage):
     patch('llvm9-disable-check-for-ipc_perm-mode.patch', when='@9.0.0:9.0.999', level=2)
     # end VISIONS
 
-    # sys/ustat.h has been removed in favour of statfs from glibc-2.28. Use fixed sizes:
-    patch("llvm5-sanitizer-ustat.patch", when="@4:6.0.0+compiler-rt")
-
     # Fix lld templates: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=230463
-    patch("llvm5-lld-ELF-Symbols.patch", when="@5+lld%clang@7:")
-
-    # Fix missing std:size_t in 'llvm@4:5' when built with '%clang@7:'
-    patch("xray_buffer_queue-cstddef.patch", when="@4:5+compiler-rt%clang@7:")
+    patch(
+        "https://raw.githubusercontent.com/freebsd/freebsd-ports/f8f9333d8e1e5a7a6b28c5ef0ca73785db06136e/devel/llvm50/files/lld/patch-tools_lld_ELF_Symbols.cpp",
+        sha256="c81a50c1b6b78d359c0ce3b88914477f4f2a85b8dbfa7ac745b9e7eb4e53931b",
+        when="@5+lld%clang@7:",
+    )
 
-    # https://github.com/llvm/llvm-project/commit/947f9692440836dcb8d88b74b69dd379d85974ce
-    patch("sanitizer-ipc_perm_mode.patch", when="@5:7+compiler-rt%clang@11:")
-    patch("sanitizer-ipc_perm_mode.patch", when="@5:9+compiler-rt%gcc@9:")
+    # Add missing include directives for the standard headers (the real need for the following
+    # patches depends on the implementation of the standard C++ library, the headers, however, must
+    # be included according to the standard, therefore, we apply the patches regardless of the
+    # compiler and compiler version).
+    #
+    # fix missing ::size_t in 'llvm@4:5'
+    # see comments in the patch file
+    patch(
+        "xray_buffer_queue-cstddef.patch",
+        # we do not cover compiler-rt=runtime because it is not supported when @:5
+        when="@4:5 compiler-rt=project",
+    )
+    #
+    # see https://reviews.llvm.org/D64937
+    # see https://github.com/spack/spack/issues/24270
+    patch(
+        "https://github.com/llvm/llvm-project/commit/b288d90b39f4b905c02092a9bfcfd6d78f99b191.patch?full_index=1",
+        sha256="2028d52e1a39326bb48fb7463132bbfe7fb4fa18f1adfeea9c3ed0320ed49564",
+        when="@8:9.0.0",
+    )
+    #
+    # committed upstream without a review
+    # see https://github.com/llvm/llvm-project/commit/b498303066a63a203d24f739b2d2e0e56dca70d1
+    # see https://github.com/spack/spack/pull/28547
+    patch(
+        "https://github.com/llvm/llvm-project/commit/b498303066a63a203d24f739b2d2e0e56dca70d1.patch?full_index=1",
+        sha256="514926d661635de47972c7d403c9c4669235aa51e22e56d44676d2a2709179b6",
+        when="@8:11",
+    )
+    #
+    # fix compilation against libstdc++13
+    patch(
+        "https://github.com/llvm/llvm-project/commit/1b4fdf18bc2aaa2d46bf072475dd9cbcd44a9fee.patch?full_index=1",
+        sha256="82481418766b4b949ea808d956ff3800b9a241a576370114862428bb0e25ee1f",
+        when="@14:15",
+    )
 
-    # github.com/spack/spack/issues/24270: MicrosoftDemangle for %gcc@10: and %clang@13:
-    patch("missing-includes.patch", when="@8")
+    # fix building of older versions of llvm with newer versions of glibc
+    for compiler_rt_as in ["project", "runtime"]:
+        with when("compiler-rt={0}".format(compiler_rt_as)):
+            # sys/ustat.h has been removed in favour of statfs from glibc-2.28
+            # see https://reviews.llvm.org/D47281
+            patch(
+                "https://github.com/llvm/llvm-project/commit/383fe5c8668f63ef21c646b43f48da9fa41aa100.patch?full_index=1",
+                sha256="66f01ac1769a6815aba09d6f4347ac1744f77f82ec9578a1158b24daca7a89e6",
+                when="@4:6.0.0",
+            )
+            # fix sanitizer-common build with glibc 2.31
+            # see https://reviews.llvm.org/D70662
+            patch("sanitizer-ipc_perm_mode.patch", when="@5:9")
+    del compiler_rt_as
 
     # Backport from llvm upstream gcc ppc const expr long double issue
     # see https://bugs.llvm.org/show_bug.cgi?id=39696
-    # This fix was initially commited (3bf63cf3b366) for the 9.0 release
+    # This fix was initially committed (3bf63cf3b366) for the 9.0 release
     # but was then broken (0583d9ea8d5e) prior to the 9.0 release and
     # eventually unbroken (d9a42ec98adc) for the 11.0 release.  The first
     # patch backports the original correct fix to previous releases.  The
     # second patch backports the un-breaking of the original fix.
-    patch("constexpr_longdouble.patch", when="@6:8+libcxx")
-    patch("constexpr_longdouble_9.0.patch", when="@9:10+libcxx")
+    for libcxx_as in ["project", "runtime"]:
+        with when("libcxx={0}".format(libcxx_as)):
+            patch(
+                "https://github.com/llvm/llvm-project/commit/3bf63cf3b366d3a57cf5cbad4112a6abf6c0c3b1.patch?full_index=1",
+                sha256="e56489a4bcf3c3636e206adca366bfcda2722ad81a5fa9a0360faed63933191a",
+                when="@6:8",
+            )
+            patch(
+                "https://github.com/llvm/llvm-project/commit/d9a42ec98adcb1ebc0c3837715df4e5a50c7ccc0.patch?full_index=1",
+                sha256="50bfc4e82c02bb5b7739990f363d99b1e43d5d11a5104f6aabbc303ebce6fbe3",
+                when="@9:10",
+            )
+    del libcxx_as
 
-    # Backport from llvm master; see
-    # https://bugs.llvm.org/show_bug.cgi?id=38233
-    # for a bug report about this problem in llvm master.
-    patch("llvm_py37.patch", when="@4:6 ^python@3.7:")
+    # Backport from llvm to fix issues related to Python 3.7
+    # see https://bugs.llvm.org/show_bug.cgi?id=38233
+    patch(
+        "https://github.com/llvm/llvm-project/commit/5457b426f5e15a29c0acc8af1a476132f8be2a36.patch?full_index=1",
+        sha256="7a1e4aa80760167807255c3e3121b1281bfcf532396b2d8fb3dce021f3f18758",
+        when="@4:6+python+lldb ^python@3.7:",
+    )
 
-    # https://github.com/spack/spack/issues/19625,
-    # merged in llvm-11.0.0_rc2, first available in 12.0.0
-    patch("lldb_external_ncurses-10.patch", when="@10.0.0:11+lldb")
+    # fix building on SUSE (with panel.h being in /usr/include/ncurses/)
+    # see https://reviews.llvm.org/D85219
+    # see https://github.com/spack/spack/issues/19625
+    patch(
+        "https://github.com/llvm/llvm-project/commit/c952ec15d38843b69e22dfd7b0665304a0459f9f.patch?full_index=1",
+        sha256="66932ba31b5bf8808ea112e42cfd79b2480a4936e711771c06ce851eac429b2c",
+        when="@10:11+lldb",
+    )
 
-    # https://github.com/spack/spack/issues/19908
-    # merged in llvm main prior to 12.0.0
-    patch("llvm_python_path.patch", when="@:11")
+    # honor Python2_EXECUTABLE and Python3_EXECUTABLE when they are passed to cmake
+    # see https://reviews.llvm.org/D91536
+    patch(
+        "https://github.com/llvm/llvm-project/commit/16de50895e96adbe261a5ce2498366bda7b3fccd.patch?full_index=1",
+        sha256="0e121ed460aa6e117f9f5f339d597a96c0fe4f97dc2209aba47b43ffc831ea24",
+        # The patch is applicable only starting version 7.0.0 (the older version might require a
+        # different patch addressing https://github.com/spack/spack/issues/19908). It looks like
+        # the patched function is used only if both compiler-rt and libcxx are enabled but we keep
+        # it simple:
+        when="@7:11",
+    )
 
     # Workaround for issue https://github.com/spack/spack/issues/18197
     patch("llvm7_intel.patch", when="@7 %intel@18.0.2,19.0.0:19.1.99")
 
     # Remove cyclades support to build against newer kernel headers
     # https://reviews.llvm.org/D102059
-    patch("no_cyclades.patch", when="@10:12.0.0")
-    patch("no_cyclades9.patch", when="@6:9")
-
-    patch("llvm-gcc11.patch", when="@9:11%gcc@11:")
-
-    # add -lpthread to build OpenMP libraries with Fujitsu compiler
-    patch("llvm12-thread.patch", when="@12 %fj")
-
-    # add -lpthread to build OpenMP libraries
-    patch("llvm13-14-thread.patch", when="@13:14")
-    patch("llvm15-thread.patch", when="@15")
+    patch(
+        "https://github.com/llvm/llvm-project/commit/68d5235cb58f988c71b403334cd9482d663841ab.patch?full_index=1",
+        sha256="742501723642675075e617f3c38339961b2c7b6fd8290dbffc52239ab0783317",
+        when="@10:12.0.0",
+    )
+    # The patch above is not applicable when "@:9" due to the file renaming and reformatting. The
+    # following patch is applicable starting at least version 5.0.0, the oldest we try to support.
+    patch("no_cyclades9.patch", when="@5:9")
+
+    with when("+libomptarget"):
+        # libomptarget makes use of multithreading via the standard C++ library (e.g.
+        # std::call_once), which, depending on the platform and the implementation of the standard
+        # library, might or might not require linking to libpthread (note that the failure might
+        # happen at the linking time as well as at the runtime). In some cases, the required linker
+        # flag comes as a transitive dependency (e.g. from the static LLVMSupport component). The
+        # following patches enforce linking to the thread library that is relevant for the system,
+        # which might lead to overlinking in some cases though.
+        # TODO: figure out why we do not use LLVM_PTHREAD_LIB but run find_package(Threads), at
+        #  least for newer versions (the solution must work with both openmp=runtime and
+        #  openmp=project)
+        patch("llvm12-thread.patch", when="@12")
+        patch("llvm13-14-thread.patch", when="@13:14")
+        patch("llvm15-thread.patch", when="@15")
 
     # avoid build failed with Fujitsu compiler
     patch("llvm13-fujitsu.patch", when="@13 %fj")
 
     # patch for missing hwloc.h include for libompd
-    patch("llvm14-hwloc-ompd.patch", when="@14")
-
-    # make libflags a list in openmp subproject when ~omp_as_runtime
-    patch("libomp-libflags-as-list.patch", when="@3.7:14")
+    # see https://reviews.llvm.org/D123888
+    patch(
+        "https://github.com/llvm/llvm-project/commit/91ccd8248c85385a5654c63c302a37d97f811bab.patch?full_index=1",
+        sha256="b216cff38659c176c5381e9dda3252edbb204e6f6f1f33e843a9ebcc42732e5d",
+        when="@14 openmp=runtime",
+    )
 
-    # Add missing include leading to build fail with clang
+    # make libflags a list in openmp subproject when openmp=project
+    # see https://reviews.llvm.org/D125370
     patch(
-        "https://github.com/llvm/llvm-project/commit/b498303066a63a203d24f739b2d2e0e56dca70d1.patch?full_index=1",
-        sha256="514926d661635de47972c7d403c9c4669235aa51e22e56d44676d2a2709179b6",
-        when="@8:11",
+        "https://github.com/llvm/llvm-project/commit/e27ce281399dca8b08b6ca593172a1bd5dbdd5c1.patch?full_index=1",
+        sha256="6f0cfa55e3ed17ee33346b0a5bca8092adcc1dc75ca712ab83901755fba9767e",
+        when="@3.7:14 openmp=project",
     )
 
     # fix detection of LLDB_PYTHON_EXE_RELATIVE_PATH
     # see https://reviews.llvm.org/D133513
-    # TODO: adjust version constraint and switch to fetching from the upstream GitHub repo
-    #  when/if the bugfix is merged
+    # TODO: the patch is not applicable after https://reviews.llvm.org/D141042 but it is not clear
+    #  yet whether we need a version of it for when="@16:"
     patch("D133513.diff", level=0, when="@14:15+lldb+python")
 
+    # Fix hwloc@:2.3 (Conditionally disable hwloc@2.0 and hwloc@2.4 code)
+    patch(
+        "https://github.com/llvm/llvm-project/commit/3a362a9f38b95978160377ee408dbc7d14af9aad.patch?full_index=1",
+        sha256="25bc503f7855229620e56e76161cf4654945aef0be493a2d8d9e94a088157b7c",
+        when="@14:15",
+    )
+
+    # Fix false positive detection of a target when building compiler-rt as a runtime
+    # https://reviews.llvm.org/D127975
+    patch(
+        "https://github.com/llvm/llvm-project/commit/9f1d90bf91570efa124c4a86cd033de374d1049a.patch?full_index=1",
+        sha256="1f4287465b3e499911e039e6cc2f395b8cb00eb8a0a223fa0db3704ba77f9969",
+        when="@13:14 compiler-rt=runtime",
+    )
+
+    patch("add-include-for-libelf-llvm-12-14.patch", when="@12:14")
+    patch("add-include-for-libelf-llvm-15.patch", when="@15")
+
+    @when("@14:17")
+    def patch(self):
+        # https://github.com/llvm/llvm-project/pull/69458
+        filter_file(
+            r"${TERMINFO_LIB}",
+            r"${Terminfo_LIBRARIES}",
+            "lldb/source/Core/CMakeLists.txt",
+            string=True,
+        )
+
     # The functions and attributes below implement external package
     # detection for LLVM. See:
     #
@@ -424,6 +643,8 @@ class Llvm(CMakePackage, CudaPackage):
             output = compiler("--version", output=str, error=str)
             if "Apple" in output:
                 return None
+            if "AMD" in output:
+                return None
             match = version_regex.search(output)
             if match:
                 return match.group(match.lastindex)
@@ -564,14 +785,6 @@ class Llvm(CMakePackage, CudaPackage):
                     os.symlink(bin, sym)
             env.prepend_path("PATH", self.stage.path)
 
-    def setup_run_environment(self, env):
-        if "+clang" in self.spec:
-            env.set("CC", join_path(self.spec.prefix.bin, "clang"))
-            env.set("CXX", join_path(self.spec.prefix.bin, "clang++"))
-        if "+flang" in self.spec:
-            env.set("FC", join_path(self.spec.prefix.bin, "flang"))
-            env.set("F77", join_path(self.spec.prefix.bin, "flang"))
-
     root_cmakelists_dir = "llvm"
 
     def cmake_args(self):
@@ -583,7 +796,6 @@ class Llvm(CMakePackage, CudaPackage):
         cmake_args = [
             define("LLVM_REQUIRES_RTTI", True),
             define("LLVM_ENABLE_RTTI", True),
-            define("LLVM_ENABLE_EH", True),
             define("LLVM_ENABLE_LIBXML2", False),
             define("CLANG_DEFAULT_OPENMP_RUNTIME", "libomp"),
             define("PYTHON_EXECUTABLE", python.command.path),
@@ -592,6 +804,16 @@ class Llvm(CMakePackage, CudaPackage):
             from_variant("LLVM_ENABLE_ZSTD", "zstd"),
         ]
 
+        # Flang does not support exceptions from core llvm.
+        # LLVM_ENABLE_EH=True when building flang will soon
+        # fail (with changes at the llvm-project level).
+        # Only enable exceptions in LLVM if we are *not*
+        # building flang.  FYI: LLVM <= 16.x will build flang
+        # successfully but the executable will suffer from
+        # link errors looking for C++ EH support.
+        if "+flang" not in spec:
+            cmake_args.append(define("LLVM_ENABLE_EH", True))
+
         version_suffix = spec.variants["version_suffix"].value
         if version_suffix != "none":
             cmake_args.append(define("LLVM_VERSION_SUFFIX", version_suffix))
@@ -622,14 +844,8 @@ class Llvm(CMakePackage, CudaPackage):
                     ),
                 ]
             )
-            if "+omp_as_runtime" in spec:
-                cmake_args.extend(
-                    [
-                        define("LIBOMPTARGET_NVPTX_ENABLE_BCLIB", True),
-                        # work around bad libelf detection in libomptarget
-                        define("LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR", spec["elf"].prefix.include),
-                    ]
-                )
+            if "openmp=runtime" in spec:
+                cmake_args.append(define("LIBOMPTARGET_NVPTX_ENABLE_BCLIB", True))
         else:
             # still build libomptarget but disable cuda
             cmake_args.extend(
@@ -641,17 +857,23 @@ class Llvm(CMakePackage, CudaPackage):
                 ]
             )
 
-        cmake_args.append(from_variant("LIBOMPTARGET_ENABLE_DEBUG", "omp_debug"))
+        cmake_args.append(from_variant("LIBOMPTARGET_ENABLE_DEBUG", "libomptarget_debug"))
 
         if "+lldb" in spec:
             projects.append("lldb")
-            cmake_args.append(define("LLDB_ENABLE_LIBEDIT", True))
-            cmake_args.append(define("LLDB_ENABLE_CURSES", True))
+            cmake_args.extend(
+                [
+                    define("LLDB_ENABLE_LIBEDIT", True),
+                    define("LLDB_ENABLE_CURSES", True),
+                    define("LLDB_ENABLE_LIBXML2", True),
+                    from_variant("LLDB_ENABLE_LUA", "lua"),
+                    define("LLDB_ENABLE_LZMA", True),
+                ]
+            )
             if spec["ncurses"].satisfies("+termlib"):
                 cmake_args.append(define("LLVM_ENABLE_TERMINFO", True))
             else:
                 cmake_args.append(define("LLVM_ENABLE_TERMINFO", False))
-            cmake_args.append(define("LLDB_ENABLE_LIBXML2", False))
             if spec.version >= Version("10"):
                 cmake_args.append(from_variant("LLDB_ENABLE_PYTHON", "python"))
             else:
@@ -667,11 +889,16 @@ class Llvm(CMakePackage, CudaPackage):
         if "+clang" in spec:
             projects.append("clang")
             projects.append("clang-tools-extra")
-            if "+omp_as_runtime" in spec:
+            if "openmp=runtime" in spec:
                 runtimes.append("openmp")
-            else:
+            elif "openmp=project" in spec:
                 projects.append("openmp")
 
+            if "+libomptarget" in spec:
+                cmake_args.append(define("OPENMP_ENABLE_LIBOMPTARGET", True))
+            else:
+                cmake_args.append(define("OPENMP_ENABLE_LIBOMPTARGET", False))
+
             if "@8" in spec:
                 cmake_args.append(from_variant("CLANG_ANALYZER_ENABLE_Z3_SOLVER", "z3"))
             elif "@9:" in spec:
@@ -681,23 +908,20 @@ class Llvm(CMakePackage, CudaPackage):
             projects.append("flang")
         if "+lld" in spec:
             projects.append("lld")
-        if "+compiler-rt" in spec:
-            if self.spec.satisfies("@15.0.0:"):
-                runtimes.append("compiler-rt")
-            else:
-                projects.append("compiler-rt")
-        if "+libcxx" in spec:
-            if self.spec.satisfies("@15.0.0:"):
-                runtimes.extend(["libcxx", "libcxxabi"])
-            else:
-                projects.extend(["libcxx", "libcxxabi"])
+        if "compiler-rt=runtime" in spec:
+            runtimes.append("compiler-rt")
+        elif "compiler-rt=project" in spec:
+            projects.append("compiler-rt")
+        if "libcxx=runtime" in spec:
+            runtimes.extend(["libcxx", "libcxxabi"])
+        elif "libcxx=project" in spec:
+            projects.extend(["libcxx", "libcxxabi"])
         if "+mlir" in spec:
             projects.append("mlir")
-        if "+internal_unwind" in spec:
-            if self.spec.satisfies("@15.0.0:"):
-                runtimes.append("libunwind")
-            else:
-                projects.append("libunwind")
+        if "libunwind=runtime" in spec:
+            runtimes.append("libunwind")
+        elif "libunwind=project" in spec:
+            projects.append("libunwind")
         if "+polly" in spec:
             projects.append("polly")
             cmake_args.append(define("LINK_POLLY_INTO_TOOLS", True))
@@ -717,7 +941,7 @@ class Llvm(CMakePackage, CudaPackage):
 
         cmake_args.append(define("LLVM_TARGETS_TO_BUILD", get_llvm_targets_to_build(spec)))
 
-        cmake_args.append(from_variant("LIBOMP_TSAN_SUPPORT", "omp_tsan"))
+        cmake_args.append(from_variant("LIBOMP_TSAN_SUPPORT", "libomp_tsan"))
 
         if self.compiler.name == "gcc":
             cmake_args.append(define("GCC_INSTALL_PREFIX", self.compiler.prefix))
@@ -725,6 +949,10 @@ class Llvm(CMakePackage, CudaPackage):
         if self.spec.satisfies("~code_signing platform=darwin"):
             cmake_args.append(define("LLDB_USE_SYSTEM_DEBUGSERVER", True))
 
+        # LLDB test suite requires libc++
+        if "libcxx=none" in spec:
+            cmake_args.append(define("LLDB_INCLUDE_TESTS", False))
+
         # Enable building with CLT [and not require full Xcode]
         # https://github.com/llvm/llvm-project/issues/57037
         if self.spec.satisfies("@15.0.0: platform=darwin"):
@@ -735,7 +963,14 @@ class Llvm(CMakePackage, CudaPackage):
 
         # Semicolon seperated list of runtimes to enable
         if runtimes:
-            cmake_args.append(define("LLVM_ENABLE_RUNTIMES", runtimes))
+            cmake_args.extend(
+                [
+                    define("LLVM_ENABLE_RUNTIMES", runtimes),
+                    define(
+                        "RUNTIMES_CMAKE_ARGS", [define("CMAKE_INSTALL_RPATH_USE_LINK_PATH", True)]
+                    ),
+                ]
+            )
 
         return cmake_args
 
@@ -745,7 +980,7 @@ class Llvm(CMakePackage, CudaPackage):
         define = self.define
 
         # unnecessary if we build openmp via LLVM_ENABLE_RUNTIMES
-        if "+cuda ~omp_as_runtime" in self.spec:
+        if "+cuda openmp=project" in self.spec:
             ompdir = "build-bootstrapped-omp"
             prefix_paths = spack.build_environment.get_cmake_prefix_path(self)
             prefix_paths.append(str(spec.prefix))
@@ -764,7 +999,6 @@ class Llvm(CMakePackage, CudaPackage):
                 cmake_args.extend(
                     [
                         define("LIBOMPTARGET_NVPTX_ENABLE_BCLIB", True),
-                        define("LIBOMPTARGET_DEP_LIBELF_INCLUDE_DIR", spec["elf"].prefix.include),
                         self.stage.source_path + "/openmp",
                     ]
                 )
@@ -858,3 +1092,4 @@ def get_llvm_targets_to_build(spec):
         llvm_targets.add("PowerPC")
 
     return list(llvm_targets)
+
diff --git a/packages/llvm/sanitizer-ipc_perm_mode.patch b/packages/llvm/sanitizer-ipc_perm_mode.patch
index 8f91703a..e270f230 100644
--- a/packages/llvm/sanitizer-ipc_perm_mode.patch
+++ b/packages/llvm/sanitizer-ipc_perm_mode.patch
@@ -1,9 +1,53 @@
-# ipc_perm.mode is not used and has changed from short to int over architecures
+# ipc_perm.mode is not used and has changed from short to int over architectures
 # and versions. The last change was in glibc-2.31.
 # LLVM upstream decided to not check ipc_perm.mode below glibc-2.31,
 # because it is not actually used in the sanitizer:
-# github.com/llvm/llvm-project/commit/947f9692440836dcb8d88b74b69dd379d85974ce
+# https://reviews.llvm.org/D70662
+#
+# We need the patch to be applicable when="@5:9" and, therefore, cannot
+# fetch it from the upstream repo.
+
 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
 +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
-@@ -1143,1 +1143,0 @@
--CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
+@@ -1126,8 +1126,9 @@ CHECK_SIZE_AND_OFFSET(ipc_perm, uid);
+ CHECK_SIZE_AND_OFFSET(ipc_perm, gid);
+ CHECK_SIZE_AND_OFFSET(ipc_perm, cuid);
+ CHECK_SIZE_AND_OFFSET(ipc_perm, cgid);
+-#if !defined(__aarch64__) || !SANITIZER_LINUX || __GLIBC_PREREQ (2, 21)
+-/* On aarch64 glibc 2.20 and earlier provided incorrect mode field.  */
++#if !SANITIZER_LINUX || __GLIBC_PREREQ (2, 31)
++/* glibc 2.30 and earlier provided 16-bit mode field instead of 32-bit
++   on many architectures.  */
+ CHECK_SIZE_AND_OFFSET(ipc_perm, mode);
+ #endif
+ 
+--- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
++++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_limits_posix.h
+@@ -203,26 +203,13 @@ namespace __sanitizer {
+     u64 __unused1;
+     u64 __unused2;
+ #elif defined(__sparc__)
+-#if defined(__arch64__)
+     unsigned mode;
+-    unsigned short __pad1;
+-#else
+-    unsigned short __pad1;
+-    unsigned short mode;
+     unsigned short __pad2;
+-#endif
+     unsigned short __seq;
+     unsigned long long __unused1;
+     unsigned long long __unused2;
+-#elif defined(__mips__) || defined(__aarch64__) || defined(__s390x__)
+-    unsigned int mode;
+-    unsigned short __seq;
+-    unsigned short __pad1;
+-    unsigned long __unused1;
+-    unsigned long __unused2;
+ #else
+-    unsigned short mode;
+-    unsigned short __pad1;
++    unsigned int mode;
+     unsigned short __seq;
+     unsigned short __pad2;
+ #if defined(__x86_64__) && !defined(_LP64)
diff --git a/packages/llvm/xray_buffer_queue-cstddef.patch b/packages/llvm/xray_buffer_queue-cstddef.patch
index b5ca841e..35e63504 100644
--- a/packages/llvm/xray_buffer_queue-cstddef.patch
+++ b/packages/llvm/xray_buffer_queue-cstddef.patch
@@ -1,4 +1,12 @@
-# Fix missing std:size_t in 'llvm@4:5' for build with '%clang@7:'
+# The patched file uses size_t, a.k.a. ::size_t (not std::size_t), but does not
+# include <stddef.h> explicitly. Whether or not the header is included
+# implicitly via other headers, depends on the implementation of the standard
+# library. Therefore, we should not apply this patch depending on the compiler
+# version. Strictly speaking, <cstddef> is not guaranteed to provide ::size_t
+# (in contrast to std::size_t). However, it does that in most cases and that is
+# what the upstream developers seem to rely on starting LLVM 6.0.0
+# (see https://reviews.llvm.org/D39175).
+
 --- a/compiler-rt/lib/xray/xray_buffer_queue.h
 +++ b/compiler-rt/lib/xray/xray_buffer_queue.h
 @@ -18,0 +18,1 @@
-- 
GitLab