Skip to content

[Hostjit] Move Clang/LLD hostjit into a separate library - #9583

Merged
shwina merged 14 commits into
NVIDIA:mainfrom
aleeb-nvidia:libnvcc
Aug 3, 2026
Merged

[Hostjit] Move Clang/LLD hostjit into a separate library#9583
shwina merged 14 commits into
NVIDIA:mainfrom
aleeb-nvidia:libnvcc

Conversation

@aleeb-nvidia

Copy link
Copy Markdown
Contributor

Description

This moves the parts of the hostjit library that depend on Clang/LLVM/LLD/nvfatbin/nvjitlink into a separate shared library (currently called libnvcc, though iirc we haven't decided on a name for this yet) which provides an interface similar to that of NVRTC.

Any CCCL-specific parts (such as include paths as well as the PCH-caching mechanism) remain in the hostjit library and are not part of libnvcc.

This change also includes some basic refactoring in a few places in what is now libnvcc (mainly to use non-throwing filesystem APIs), but there's more refactoring to be done later that I will come back to in the future, but this change is already big enough as-is.

This is essentially a NFC: it doesn't really add or remove functionality, instead it only moves it around.

Checklist

  • I am familiar with the Contributing Guidelines
  • New or existing tests cover these changes.
  • The documentation is up to date with these changes.

@aleeb-nvidia
aleeb-nvidia requested review from a team as code owners June 24, 2026 18:10
@aleeb-nvidia
aleeb-nvidia requested a review from griwes June 24, 2026 18:10
@github-project-automation github-project-automation Bot moved this to Todo in CCCL Jun 24, 2026
@copy-pr-bot

copy-pr-bot Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@aleeb-nvidia

Copy link
Copy Markdown
Contributor Author

CC @gevtushenko

@cccl-authenticator-app cccl-authenticator-app Bot moved this from Todo to In Review in CCCL Jun 24, 2026
@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds libnvcc as a shared library with a C API, updates hostjit to use it directly, extends CompilerConfig with PCH and extra argument support, and adjusts CMake, RPATH, and Python install targets.

Changes

libnvcc extraction and hostjit rewiring

Layer / File(s) Summary
libnvcc public C API header
c/parallel.v2/src/hostjit/libnvcc/include/libnvcc/libnvcc.h
Defines the libnvccResult and libnvccPCHKind enums, the opaque libnvccProgram handle, and the exported declarations for program lifecycle, compilation, linking, PCH creation, and diagnostic log retrieval.
libnvcc compiler core
c/parallel.v2/src/hostjit/libnvcc/compiler.cpp
Implements libnvcc option parsing, compiler option handling, PCH support, device bitcode and object compilation, shared-library linking, file output, temp-directory cleanup, and runtime library discovery.
hostjit API surface changes
c/parallel.v2/src/hostjit/include/hostjit/compiler.hpp, c/parallel.v2/src/hostjit/include/hostjit/config.hpp, c/parallel.v2/src/hostjit/include/hostjit/jit_compiler.hpp
Removes the CUDACompiler-based declarations, adds libnvcc helper utilities, extends CompilerConfig with PCH and extra-argument fields, changes the default SM version, and drops the stored compiler member from JITCompiler.
CompilerConfig argument assembly
c/parallel.v2/src/hostjit/config.cpp
Implements helper functions and CompilerConfig::appendCommandLineArguments(...) to build compiler arguments from toolkit paths, search paths, bitcode inputs, macro definitions, extra Clang args, PCH paths, architecture, optimization, and debug flags.
JITCompiler and bitcode codegen rewired to libnvcc
c/parallel.v2/src/hostjit/jit_compiler.cpp, c/parallel.v2/src/hostjit/codegen/bitcode.cpp
Adds PCH cache and file-loading helpers, rewrites JITCompiler::compile to use libnvcc* calls end-to-end, and updates compile_and_add to create a libnvcc program and compile device bitcode through the new API.
CMake wiring, RPATH, and Python install
c/parallel.v2/CMakeLists.txt, c/parallel.v2/src/hostjit/CMakeLists.txt, c/parallel.v2/src/hostjit/libnvcc/CMakeLists.txt, python/cuda_cccl/CMakeLists.txt
Moves hostjit LLVM setup into libnvcc, links libnvcc from hostjit_lib, sets $ORIGIN RPATH on the parallel library on Unix, and includes libnvcc in the Python v2 install target list.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 10

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (5)
c/parallel.v2/src/hostjit/codegen/bitcode.cpp (1)

125-138: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

important: propagate bitcode compilation failures instead of only printing to stderr and returning false. The current callers ignore compile_and_add(...)’s return value, so a libnvcc failure can silently continue without required bitcode and fail later with misleading diagnostics. As per path instructions: focus on public C API error/status handling.

Source: Path instructions

c/parallel.v2/src/hostjit/CMakeLists.txt (1)

113-117: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

important: Exclude libnvcc and any default-built v2 consumers from MSVC Debug as well. add_subdirectory(libnvcc) runs unconditionally on Line 23, but this block only excludes cccl.c.parallel.v2.hostjit_lib; a Debug build can still pull libnvcc through cccl.c.parallel.v2 or packaging targets.

c/parallel.v2/src/hostjit/libnvcc/compiler.cpp (3)

71-91: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

important: make LLVM initialization thread-safe. Parallel libnvcc calls can read/write llvm_initialized concurrently and can run LLVM target initialization twice. Use std::once_flag/std::call_once.


1660-1666: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

important: do not silently skip unreadable or empty LTOIR inputs. The caller explicitly supplied these files, so an empty read should report which --device-ltoir failed instead of continuing with a different link input set.


1701-1704: 🗄️ Data Integrity & Integration | 🟠 Major

important: check the return codes from both nvJitLinkGetLinkedCubinSize and nvJitLinkGetLinkedCubin; on failure, stop before writing cubin_data or passing it to nvFatbin, or this path can emit invalid cubin contents.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 428555d5-25cb-4ff8-858b-4ced8cf7bcab

📥 Commits

Reviewing files that changed from the base of the PR and between 5b5036d and 5933491.

📒 Files selected for processing (12)
  • c/parallel.v2/CMakeLists.txt
  • c/parallel.v2/src/hostjit/CMakeLists.txt
  • c/parallel.v2/src/hostjit/codegen/bitcode.cpp
  • c/parallel.v2/src/hostjit/config.cpp
  • c/parallel.v2/src/hostjit/include/hostjit/compiler.hpp
  • c/parallel.v2/src/hostjit/include/hostjit/config.hpp
  • c/parallel.v2/src/hostjit/include/hostjit/jit_compiler.hpp
  • c/parallel.v2/src/hostjit/jit_compiler.cpp
  • c/parallel.v2/src/hostjit/libnvcc/CMakeLists.txt
  • c/parallel.v2/src/hostjit/libnvcc/compiler.cpp
  • c/parallel.v2/src/hostjit/libnvcc/include/libnvcc/libnvcc.h
  • python/cuda_cccl/CMakeLists.txt
💤 Files with no reviewable changes (1)
  • c/parallel.v2/src/hostjit/include/hostjit/jit_compiler.hpp

Comment thread c/parallel.v2/CMakeLists.txt
Comment thread c/parallel.v2/src/hostjit/include/hostjit/compiler.hpp
Comment thread c/parallel.v2/src/hostjit/jit_compiler.cpp
Comment on lines +51 to +83
pch_path = get_pch_path(kind_name, config.sm_version);
if (std::filesystem::exists(pch_path))
{
return true;
}

config.enable_pch = false;
config.device_pch_path.clear();
config.host_pch_path.clear();

std::vector<std::string> options;
config.appendCommandLineArguments(options);
auto option_ptrs = hostjit::detail::make_libnvcc_option_ptrs(options);

hostjit::detail::LibnvccProgramGuard program;
auto create_result = libnvccCreateProgram(&program.program, pch_preamble_source, "hostjit_preamble.cu");
if (create_result != LIBNVCC_SUCCESS)
{
diagnostics += "Failed to create libnvcc PCH program: ";
diagnostics += libnvccGetErrorString(create_result);
diagnostics += "\n";
pch_path.clear();
return false;
}

auto source_path = get_pch_source_path(kind_name, config.sm_version);
auto pch_result = libnvccCreatePCH(
program.program,
kind,
source_path.c_str(),
pch_path.c_str(),
static_cast<int>(option_ptrs.size()),
option_ptrs.empty() ? nullptr : option_ptrs.data());

@coderabbitai coderabbitai Bot Jun 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

important: avoid check-then-write races for shared PCH paths. Two processes can both miss exists(pch_path), or one can observe a partially written .pch; write to a unique temp path and atomically rename or guard generation with a lock.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that too should be reserved for a future patch if we care about making sure that this works properly across multiple processes

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

suggestion: @aleeb-nvidia makes sense to defer this. The residual risk is limited to concurrent processes sharing hostjit_pch and observing the same *.pch path during generation. If you want, I can open a follow-up issue to track adding locking or temp-file-plus-rename around PCH creation.


🧠 Learnings used
Learnt from: sleeepyjack
Repo: NVIDIA/cccl PR: 8857
File: cudax/include/cuda/experimental/__cuco/__hyperloglog/hyperloglog_impl.cuh:426-428
Timestamp: 2026-05-06T23:47:17.597Z
Learning: In the CCCL/CUDA C++ Core Libraries codebase (NVIDIA/cccl), treat `_CCCL_API` as host-and-device callable. `_CCCL_API` expands to `_CCCL_HOST_DEVICE` via `libcudacxx/include/cuda/std/__cccl/visibility.h`, so functions marked with `_CCCL_API` may be invoked from both host and device code. When reviewing device-code contexts, do not flag `_CCCL_API`-annotated functions as if they were host-only.

Learnt from: shwina
Repo: NVIDIA/cccl PR: 9568
File: c/parallel/src/segmented_reduce.cu:599-643
Timestamp: 2026-06-23T20:49:51.585Z
Learning: When reviewing uses of NVIDIA/cccl AOT serialization, don’t flag a potential mismatch when `cccl::aot::buffer_writer::write_blob` is paired with `cccl::aot::buffer_reader::read_into(void* dest, size_t expected_size)`. The `read_into` implementation reads a length-prefixed blob: it `read_pod`s the stored length, checks it equals `expected_size`, and only then copies that many bytes into `dest`. This behavior is the intended counterpart for `write_blob`, so these pairs should be treated as compatible rather than mismatched.

Comment thread c/parallel.v2/src/hostjit/libnvcc/CMakeLists.txt Outdated
Comment thread c/parallel.v2/src/hostjit/libnvcc/compiler.cpp
Comment thread c/parallel.v2/src/hostjit/libnvcc/compiler.cpp
Comment thread c/parallel.v2/src/hostjit/libnvcc/compiler.cpp Outdated
Comment on lines +2241 to +2252
extern "C" libnvccResult libnvccCreateProgram(libnvccProgram* prog, const char* src, const char* name)
{
if (!prog || !src)
{
return LIBNVCC_ERROR_INVALID_INPUT;
}
*prog = nullptr;

auto* program = new libnvccProgram_st;
program->source = src;
program->name = (name && name[0]) ? name : "input.cu";
*prog = program;

@coderabbitai coderabbitai Bot Jun 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🔴 Critical | 🏗️ Heavy lift

critical: do not let C++ exceptions cross the C ABI. new, std::string assignment, option parsing, and compilation can throw before a libnvccResult is returned, despite the API defining OOM/internal error statuses. Wrap exported entry points in noexcept exception boundaries that map std::bad_alloc and other exceptions to result codes. As per path instructions, c/**/* reviews should focus on C/C++ boundary behavior and error/status handling.

Also applies to: 2267-2390

Source: Path instructions

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To my knowledge catching bad_alloc almost never makes sense since the OS will OOM-kill the process before a memory allocation has a chance to fail (unless you try to allocate like 1TB in a single allocation or sth like that).

Is exception handling even enabled in the contexts where this library will be used? At least LLVM is generally build w/ -fno-exceptions -fno-rtti.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Locate relevant CMake files =="
fd -i 'CMakeLists.txt' c/parallel.v2/src/hostjit c/parallel.v2 | sed 's#^\./##' | sort

echo
echo "== Inspect libnvcc target CMake =="
sed -n '1,260p' c/parallel.v2/src/hostjit/libnvcc/CMakeLists.txt

echo
echo "== Inspect parent hostjit CMake =="
sed -n '1,260p' c/parallel.v2/src/hostjit/CMakeLists.txt

echo
echo "== Search for exception-related CMake settings in c/parallel.v2 =="
rg -n -C2 --glob 'c/parallel.v2/**/CMakeLists.txt' --glob 'c/parallel.v2/**/*.cmake' \
  'fno-exceptions|/EH|exceptions|LLVM_ENABLE_EH|LLVM_ENABLE_RTTI|LLVM_REQUIRES_EH|CXX_EXCEPTIONS|target_compile_options|target_compile_definitions|DISABLE_RTTI|LLVM_NO_RTTI' .

echo
echo "== Search for noexcept or exception mentions in libnvcc public header/source =="
rg -n -C2 'noexcept|throw|bad_alloc|exception' \
  c/parallel.v2/src/hostjit/libnvcc/include/libnvcc/libnvcc.h \
  c/parallel.v2/src/hostjit/libnvcc/compiler.cpp

Length of output: 18839



important: @aleeb-nvidia I checked the build config. c/parallel.v2/src/hostjit/libnvcc/CMakeLists.txt only forces -fno-rtti for libnvcc; it does not disable exceptions for that target, and I didn’t find any LLVM_ENABLE_EH=OFF-style setting in this subtree either.

So LLVM itself may well be built mostly exception-free, but that doesn’t make these C wrappers safe: this TU still has its own throwing paths (new in libnvccCreateProgram, std::string/std::vector growth, filesystem/string allocations, etc.) before a libnvccResult is returned.

I do agree my original wording was too specific on bad_alloc. The real issue is the C ABI boundary, not that one exception type in particular. I’d narrow the ask to:

  • either catch unexpected C++ exceptions in the exported extern "C" entry points and map them to LIBNVCC_ERROR_OUT_OF_MEMORY / LIBNVCC_ERROR_INTERNAL_ERROR,
  • or explicitly define/document that these APIs may terminate on internal exceptions instead of reliably returning a status code.

So I don’t think the concern is invalid, but I would restate it more narrowly.


🧠 Learnings used
Learnt from: sleeepyjack
Repo: NVIDIA/cccl PR: 8857
File: cudax/include/cuda/experimental/__cuco/__hyperloglog/hyperloglog_impl.cuh:426-428
Timestamp: 2026-05-06T23:47:17.597Z
Learning: In the CCCL/CUDA C++ Core Libraries codebase (NVIDIA/cccl), treat `_CCCL_API` as host-and-device callable. `_CCCL_API` expands to `_CCCL_HOST_DEVICE` via `libcudacxx/include/cuda/std/__cccl/visibility.h`, so functions marked with `_CCCL_API` may be invoked from both host and device code. When reviewing device-code contexts, do not flag `_CCCL_API`-annotated functions as if they were host-only.

Learnt from: shwina
Repo: NVIDIA/cccl PR: 9568
File: c/parallel/src/segmented_reduce.cu:599-643
Timestamp: 2026-06-23T20:49:51.585Z
Learning: When reviewing uses of NVIDIA/cccl AOT serialization, don’t flag a potential mismatch when `cccl::aot::buffer_writer::write_blob` is paired with `cccl::aot::buffer_reader::read_into(void* dest, size_t expected_size)`. The `read_into` implementation reads a length-prefixed blob: it `read_pod`s the stored length, checks it equals `expected_size`, and only then copies that many bytes into `dest`. This behavior is the intended counterpart for `write_blob`, so these pairs should be treated as compatible rather than mismatched.

@@ -0,0 +1,203 @@
#pragma once

@coderabbitai coderabbitai Bot Jun 24, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

important: add the required CCCL license header before #pragma once. As per coding guidelines, **/*.{h,hpp,cuh}: “All headers must have the correct license.”

Source: Coding guidelines

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, quite a few of the headers in the hostjit library don't have licence headers; is that intentional?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Header files under c/parallel.v2/src/hostjit =="
fd -e h -e hh -e hpp -e cuh . c/parallel.v2/src/hostjit | sort

echo
echo "== First 8 lines of each hostjit header =="
while IFS= read -r f; do
  echo "-- $f --"
  sed -n '1,8p' "$f"
  echo
done < <(fd -e h -e hh -e hpp -e cuh . c/parallel.v2/src/hostjit | sort)

echo "== First 8 lines of public C API / nearby headers under c/parallel.v2 =="
for f in \
  c/parallel.v2/src/hostjit/libnvcc/include/libnvcc/libnvcc.h \
  c/parallel.v2/src/hostjit/include/hostjit/compiler.hpp \
  c/parallel.v2/src/hostjit/include/hostjit/config.hpp \
  c/parallel.v2/src/hostjit/include/hostjit/jit_compiler.hpp
do
  if [[ -f "$f" ]]; then
    echo "-- $f --"
    sed -n '1,8p' "$f"
    echo
  fi
done

echo "== Sample of license headers elsewhere in c/parallel.v2 =="
fd -e h -e hh -e hpp -e cuh . c/parallel.v2 | sort | while IFS= read -r f; do
  if rg -n -m1 'SPDX-FileCopyrightText|Apache-2.0 WITH LLVM-exception' "$f" >/dev/null; then
    echo "-- $f --"
    sed -n '1,6p' "$f"
    echo
    break
  fi
done

Length of output: 3012


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== First 8 lines of representative hostjit headers =="
for f in \
  c/parallel.v2/src/hostjit/include/hostjit/compiler.hpp \
  c/parallel.v2/src/hostjit/include/hostjit/config.hpp \
  c/parallel.v2/src/hostjit/include/hostjit/jit_compiler.hpp \
  c/parallel.v2/src/hostjit/include/hostjit/codegen/bitcode.hpp \
  c/parallel.v2/src/hostjit/libnvcc/include/libnvcc/libnvcc.h
do
  echo "-- $f --"
  sed -n '1,8p' "$f"
  echo
done

echo "== Count of hostjit headers with SPDX/license markers in first 8 lines =="
python - <<'PY'
from pathlib import Path
files = sorted(Path("c/parallel.v2/src/hostjit").rglob("*"))
headers = [p for p in files if p.suffix in {".h", ".hh", ".hpp", ".cuh"}]
count = 0
for p in headers:
    head = "".join(p.read_text(errors="ignore").splitlines(True)[:8])
    if "SPDX-FileCopyrightText" in head or "Apache-2.0 WITH LLVM-exception" in head:
        count += 1
print(f"{count}/{len(headers)}")
PY

echo
echo "== Sample standard license header elsewhere in c/parallel.v2 =="
python - <<'PY'
from pathlib import Path
for p in sorted(Path("c/parallel.v2").rglob("*")):
    if p.suffix not in {".h", ".hh", ".hpp", ".cuh"}:
        continue
    head_lines = p.read_text(errors="ignore").splitlines()[:8]
    head = "\n".join(head_lines)
    if "SPDX-FileCopyrightText" in head or "Apache-2.0 WITH LLVM-exception" in head:
        print(f"-- {p} --")
        print("\n".join(head_lines))
        break
PY

Length of output: 3366



important: @aleeb-nvidia it doesn’t look intentional.

I checked the hostjit subtree: it’s mixed. c/parallel.v2/src/hostjit/include/hostjit/codegen/bitcode.hpp already has the standard CCCL SPDX/license block, but c/parallel.v2/src/hostjit/include/hostjit/compiler.hpp, c/parallel.v2/src/hostjit/include/hostjit/config.hpp, c/parallel.v2/src/hostjit/include/hostjit/jit_compiler.hpp, and this new c/parallel.v2/src/hostjit/libnvcc/include/libnvcc/libnvcc.h do not. The quick count was 10/21 hostjit headers with license markers.

So I wouldn’t treat missing headers here as an intentional local convention. For this PR, I’d still expect the newly added public header to get the standard CCCL license block. If the rest of hostjit is pre-existing debt, that broader cleanup can be separate.


🧠 Learnings used
Learnt from: sleeepyjack
Repo: NVIDIA/cccl PR: 8857
File: cudax/include/cuda/experimental/__cuco/__hyperloglog/default_policy.cuh:92-95
Timestamp: 2026-05-06T23:47:10.296Z
Learning: In this CCCL (CUDA C++ Core Libraries) codebase, do NOT treat `_CCCL_API` as host-only. `_CCCL_API` is defined in `libcudacxx/include/cuda/std/__cccl/visibility.h` and always expands to include `_CCCL_HOST_DEVICE` (possibly alongside `_CCCL_TILE`, `_CCCL_VISIBILITY_HIDDEN`, and `_CCCL_EXCLUDE_FROM_EXPLICIT_INSTANTIATION`). So any function annotated with `_CCCL_API` is already valid for both host and device code; reviewers should not flag it as host-only.

Learnt from: sleeepyjack
Repo: NVIDIA/cccl PR: 8857
File: cudax/include/cuda/experimental/__cuco/__hyperloglog/hyperloglog_impl.cuh:426-428
Timestamp: 2026-05-06T23:47:17.597Z
Learning: In the CCCL/CUDA C++ Core Libraries codebase (NVIDIA/cccl), treat `_CCCL_API` as host-and-device callable. `_CCCL_API` expands to `_CCCL_HOST_DEVICE` via `libcudacxx/include/cuda/std/__cccl/visibility.h`, so functions marked with `_CCCL_API` may be invoked from both host and device code. When reviewing device-code contexts, do not flag `_CCCL_API`-annotated functions as if they were host-only.

Learnt from: NaderAlAwar
Repo: NVIDIA/cccl PR: 9171
File: libcudacxx/include/cuda/std/__cccl/diagnostic.h:126-126
Timestamp: 2026-06-03T13:24:36.356Z
Learning: When reviewing code that uses NVIDIA NVCC/NVRTC diagnostic suppression pragmas, treat `nv_diag_suppress` as supporting comma-separated warning numbers in a single directive. For example, `_Pragma("nv_diag_suppress 1444,20199")` (or an equivalent `#pragma nv_diag_suppress 1444,20199`) is valid; do not flag comma-separated warning IDs inside `nv_diag_suppress` pragmas as unsupported.

Learnt from: shwina
Repo: NVIDIA/cccl PR: 9568
File: c/parallel/src/segmented_reduce.cu:599-643
Timestamp: 2026-06-23T20:49:51.585Z
Learning: When reviewing uses of NVIDIA/cccl AOT serialization, don’t flag a potential mismatch when `cccl::aot::buffer_writer::write_blob` is paired with `cccl::aot::buffer_reader::read_into(void* dest, size_t expected_size)`. The `read_into` implementation reads a length-prefixed blob: it `read_pod`s the stored length, checks it equals `expected_size`, and only then copies that many bytes into `dest`. This behavior is the intended counterpart for `write_blob`, so these pairs should be treated as compatible rather than mismatched.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
c/parallel.v2/src/hostjit/libnvcc/compiler.cpp (1)

2283-2285: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

important: preserve invalid-input/option status codes at the C API boundary. compileToDeviceBitcode and createPCH can fail from validateOptions, and createPCH can fail from an invalid libnvccPCHKind, but the wrappers collapse those into LIBNVCC_ERROR_COMPILATION or LIBNVCC_ERROR_PCH_CREATE. Propagate a structured failure reason or validate in the wrapper before dispatch so C callers can distinguish bad inputs from compiler failures. As per path instructions, c/**/* reviews should focus on C API/ABI stability and error/status handling.

Also applies to: 2382-2386

Source: Path instructions


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: b190eb7d-6e0a-4971-ba29-5e6af509efcf

📥 Commits

Reviewing files that changed from the base of the PR and between 5933491 and 8d98fda.

📒 Files selected for processing (2)
  • c/parallel.v2/src/hostjit/libnvcc/compiler.cpp
  • c/parallel.v2/src/hostjit/libnvcc/include/libnvcc/libnvcc.h
🚧 Files skipped from review as they are similar to previous changes (1)
  • c/parallel.v2/src/hostjit/libnvcc/include/libnvcc/libnvcc.h

Comment thread c/parallel.v2/src/hostjit/codegen/bitcode.cpp
Comment thread c/parallel.v2/src/hostjit/codegen/bitcode.cpp Outdated
Comment thread c/parallel.v2/src/hostjit/include/hostjit/compiler.hpp
Comment thread c/parallel.v2/src/hostjit/include/hostjit/compiler.hpp
Comment thread c/parallel.v2/src/hostjit/include/hostjit/compiler.hpp
Comment thread c/parallel.v2/src/hostjit/include/hostjit/compiler.hpp Outdated
Comment thread c/parallel.v2/src/hostjit/include/hostjit/config.hpp Outdated
Comment thread c/parallel.v2/src/hostjit/libnvcc/compiler.cpp
Comment thread c/parallel.v2/src/hostjit/libnvcc/compiler.cpp
@gevtushenko

Copy link
Copy Markdown
Collaborator

/ok to test 77b3dcc

@github-actions

This comment has been minimized.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: cfa37b73-024b-4118-ae41-d01cc2162889

📥 Commits

Reviewing files that changed from the base of the PR and between 77b3dcc and 3940bed.

📒 Files selected for processing (11)
  • c/parallel.v2/CMakeLists.txt
  • c/parallel.v2/src/hostjit/CMakeLists.txt
  • c/parallel.v2/src/hostjit/codegen/bitcode.cpp
  • c/parallel.v2/src/hostjit/config.cpp
  • c/parallel.v2/src/hostjit/include/hostjit/compiler.hpp
  • c/parallel.v2/src/hostjit/include/hostjit/config.hpp
  • c/parallel.v2/src/hostjit/include/hostjit/jit_compiler.hpp
  • c/parallel.v2/src/hostjit/jit_compiler.cpp
  • c/parallel.v2/src/hostjit/libnvcc/CMakeLists.txt
  • c/parallel.v2/src/hostjit/libnvcc/compiler.cpp
  • c/parallel.v2/src/hostjit/libnvcc/include/libnvcc/libnvcc.h
💤 Files with no reviewable changes (1)
  • c/parallel.v2/src/hostjit/include/hostjit/jit_compiler.hpp
✅ Files skipped from review due to trivial changes (1)
  • c/parallel.v2/CMakeLists.txt
🚧 Files skipped from review as they are similar to previous changes (8)
  • c/parallel.v2/src/hostjit/codegen/bitcode.cpp
  • c/parallel.v2/src/hostjit/config.cpp
  • c/parallel.v2/src/hostjit/libnvcc/include/libnvcc/libnvcc.h
  • c/parallel.v2/src/hostjit/include/hostjit/compiler.hpp
  • c/parallel.v2/src/hostjit/jit_compiler.cpp
  • c/parallel.v2/src/hostjit/include/hostjit/config.hpp
  • c/parallel.v2/src/hostjit/libnvcc/CMakeLists.txt
  • c/parallel.v2/src/hostjit/libnvcc/compiler.cpp

Comment on lines +17 to +18
set(LIBNVCC_HEADER_INSTALL_DESTINATION "cuda/cccl/headers/libnvcc")
set(LIBNVCC_CLANG_HEADER_INSTALL_DESTINATION "cuda/cccl/headers/clang")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

important: Preserve a standard install location for the new public C API header. This override replaces libnvcc’s default include/libnvcc destination with the Python header layout, so non-Python C consumers may not get <libnvcc/libnvcc.h> on the normal include path. Install to both locations or scope this override to Python packaging. As per path instructions, c/**/*: Focus on C API/ABI stability.

Source: Path instructions

romanso added a commit to romanso/cccl that referenced this pull request Jul 7, 2026
…dows stack overflow)

Re-target of the stack-overflow fix onto the libnvcc refactor (NVIDIA#9583): the four
clang ExecuteAction calls moved from hostjit/compiler.cpp into
libnvcc/compiler.cpp. Embedding clang bypasses the driver's
runWithSufficientStackSpace guard; on Windows the 1 MB default stack overflows on
deep template instantiation. Run each ExecuteAction on an 8 MB worker thread
(= clang's DesiredStackSize).
romanso added a commit to romanso/cccl that referenced this pull request Jul 7, 2026
…dows stack overflow)

Re-target of the stack-overflow fix onto the libnvcc refactor (NVIDIA#9583): the four
clang ExecuteAction calls moved from hostjit/compiler.cpp into
libnvcc/compiler.cpp. Embedding clang bypasses the driver's
runWithSufficientStackSpace guard; on Windows the 1 MB default stack overflows on
deep template instantiation. Run each ExecuteAction on an 8 MB worker thread
(= clang's DesiredStackSize).
romanso added a commit to romanso/cccl that referenced this pull request Jul 7, 2026
…dows stack overflow)

Re-target of the stack-overflow fix onto the libnvcc refactor (NVIDIA#9583): the four
clang ExecuteAction calls moved from hostjit/compiler.cpp into
libnvcc/compiler.cpp. Embedding clang bypasses the driver's
runWithSufficientStackSpace guard; on Windows the 1 MB default stack overflows on
deep template instantiation. Run each ExecuteAction on an 8 MB worker thread
(= clang's DesiredStackSize).
romanso added a commit to romanso/cccl that referenced this pull request Jul 7, 2026
…dows stack overflow)

Re-target of the stack-overflow fix onto the libnvcc refactor (NVIDIA#9583): the four
clang ExecuteAction calls moved from hostjit/compiler.cpp into
libnvcc/compiler.cpp. Embedding clang bypasses the driver's
runWithSufficientStackSpace guard; on Windows the 1 MB default stack overflows on
deep template instantiation. Run each ExecuteAction on an 8 MB worker thread
(= clang's DesiredStackSize).
romanso added a commit to romanso/cccl that referenced this pull request Jul 8, 2026
…dows stack overflow)

Re-target of the stack-overflow fix onto the libnvcc refactor (NVIDIA#9583): the four
clang ExecuteAction calls moved from hostjit/compiler.cpp into
libnvcc/compiler.cpp. Embedding clang bypasses the driver's
runWithSufficientStackSpace guard; on Windows the 1 MB default stack overflows on
deep template instantiation. Run each ExecuteAction on an 8 MB worker thread
(= clang's DesiredStackSize).
romanso added a commit to romanso/cccl that referenced this pull request Jul 9, 2026
…dows stack overflow)

Re-target of the stack-overflow fix onto the libnvcc refactor (NVIDIA#9583): the four
clang ExecuteAction calls moved from hostjit/compiler.cpp into
libnvcc/compiler.cpp. Embedding clang bypasses the driver's
runWithSufficientStackSpace guard; on Windows the 1 MB default stack overflows on
deep template instantiation. Run each ExecuteAction on an 8 MB worker thread
(= clang's DesiredStackSize).
romanso added a commit to romanso/cccl that referenced this pull request Jul 9, 2026
…dows stack overflow)

Re-target of the stack-overflow fix onto the libnvcc refactor (NVIDIA#9583): the four
clang ExecuteAction calls moved from hostjit/compiler.cpp into
libnvcc/compiler.cpp. Embedding clang bypasses the driver's
runWithSufficientStackSpace guard; on Windows the 1 MB default stack overflows on
deep template instantiation. Run each ExecuteAction on an 8 MB worker thread
(= clang's DesiredStackSize).
romanso added a commit to romanso/cccl that referenced this pull request Jul 9, 2026
…dows stack overflow)

Re-target of the stack-overflow fix onto the libnvcc refactor (NVIDIA#9583): the four
clang ExecuteAction calls moved from hostjit/compiler.cpp into
libnvcc/compiler.cpp. Embedding clang bypasses the driver's
runWithSufficientStackSpace guard; on Windows the 1 MB default stack overflows on
deep template instantiation. Run each ExecuteAction on an 8 MB worker thread
(= clang's DesiredStackSize).
romanso added a commit to romanso/cccl that referenced this pull request Jul 9, 2026
…dows stack overflow)

Re-target of the stack-overflow fix onto the libnvcc refactor (NVIDIA#9583): the four
clang ExecuteAction calls moved from hostjit/compiler.cpp into
libnvcc/compiler.cpp. Embedding clang bypasses the driver's
runWithSufficientStackSpace guard; on Windows the 1 MB default stack overflows on
deep template instantiation. Run each ExecuteAction on an 8 MB worker thread
(= clang's DesiredStackSize).
romanso pushed a commit to romanso/cccl that referenced this pull request Jul 16, 2026
Re-apply the device-API list from NVIDIA#9663 (which landed in main's
hostjit/compiler.cpp) into jit_compiler.cpp, where the NVIDIA#9583 refactor moved
the PCH preamble. Keeps the PCH cache covering all tested device APIs.
romanso pushed a commit to romanso/cccl that referenced this pull request Jul 16, 2026
Re-apply the device-API list from NVIDIA#9663 (which landed in main's
hostjit/compiler.cpp) into jit_compiler.cpp, where the NVIDIA#9583 refactor moved
the PCH preamble. Keeps the PCH cache covering all tested device APIs.
romanso pushed a commit to romanso/cccl that referenced this pull request Jul 16, 2026
Re-apply the device-API list from NVIDIA#9663 (which landed in main's
hostjit/compiler.cpp) into jit_compiler.cpp, where the NVIDIA#9583 refactor moved
the PCH preamble. Keeps the PCH cache covering all tested device APIs.
@shwina

shwina commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

/ok to test romanso@f9ff544

@copy-pr-bot

copy-pr-bot Bot commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

/ok to test romanso@f9ff544

@shwina, there was an error processing your request: E2

See the following link for more information: https://docs.gha-runners.nvidia.com/cpr/e/2/

@shwina

shwina commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

/ok to test 12a56b3

@github-actions

This comment has been minimized.

@shwina

shwina commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

/ok to test 903fb73

@github-actions

This comment has been minimized.

@shwina

shwina commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

/ok to test 1226d6e

@github-actions

This comment has been minimized.

@shwina

shwina commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

/ok to test 9712095

@github-actions

This comment has been minimized.

@shwina

shwina commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

/ok to test 3dd411a

@shwina
shwina enabled auto-merge (squash) July 31, 2026 16:59
@github-actions

Copy link
Copy Markdown
Contributor

🥳 CI Workflow Results

🟩 Finished in 1h 33m: Pass: 100%/78 | Total: 1d 04h | Max: 59m 15s | Hits: 99%/5295

See results here.

Comment on lines +3 to 6
# Find CUDA toolkit (may already be found by parent)
if (NOT CUDAToolkit_FOUND)
find_package(CUDAToolkit)
endif()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to guard here, find_package() will exit early if it is already found

Comment on lines +4 to +9
find_file(
LIBNVCC_CPM_CMAKE_PATH
NAMES CPM.cmake
PATHS ${CMAKE_MODULE_PATH}
NO_DEFAULT_PATH
)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

include(CPM) (note no .cmake) will do exactly the same thing, searching CMAKE_MODULE_PATH as well as producing an error for you if it is not found.

Comment on lines +42 to +43
set(LLVM_ENABLE_PROJECTS "clang;lld" CACHE STRING "" FORCE)
set(LLVM_TARGETS_TO_BUILD "X86;NVPTX" CACHE STRING "" FORCE)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the point here is to just pass these as OPTIONS in the CPMAddPackage() call, you can just do

CPMAddPackage(
  OPTIONS
    "LLVM_ENABLE_PROJECTS \"clang;lld\""
)

to do lists. Alternatively using raw comments

CPMAddPackage(
  OPTIONS
    [[LLVM_ENABLE_PROJECTS "clang;lld"]]
)

message(FATAL_ERROR "libnvcc requires a CUDA toolkit")
endif()

target_include_directories(libnvcc PRIVATE ${CUDAToolkit_INCLUDE_DIRS})

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should just target_link_libraries() here. Or is the goal to only get compile-time but no link-time dependency?

Comment on lines +85 to +90
${llvm_project_SOURCE_DIR}/llvm/include
${llvm_project_BINARY_DIR}/include
${llvm_project_SOURCE_DIR}/clang/include
${llvm_project_BINARY_DIR}/tools/clang/include
${llvm_project_SOURCE_DIR}/lld/include
${llvm_project_BINARY_DIR}/tools/lld/include

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These includes should already be coming from the target_link_libraries() call you do down below, no need to add them separately.

lldCommon
)

if (CUDAToolkit_FOUND)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CUDAToolkit is most definitely found at this point due to the previous assertion.

endif()

if (NOT LIBNVCC_HEADER_INSTALL_DESTINATION)
set(LIBNVCC_HEADER_INSTALL_DESTINATION "include/libnvcc")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should use the GNUInstallDirs-provided values instead of hardcoding include/ here.

# We DON'T install device_functions, math, or libdevice_declares — our local
# copies in cuda_minimal/ replace them.
set(
_clang_cuda_headers_needed

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: why the extra variable? You can just list these inline in the install() command, looks neater as well.

)
endif()

if (UNIX AND NOT APPLE)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note the equivalent for $ORIGIN on macos is @loader_path

@shwina
shwina merged commit de06b2e into NVIDIA:main Aug 3, 2026
100 checks passed
davebayer pushed a commit to davebayer/cccl that referenced this pull request Aug 4, 2026
* [Hostjit] Move Clang/LLD hostjit into a separate library

* clang-format

* Address some review comments

* format CMake

* fix merge error

* fix unused variable warning when assertions are disabled

* attempt to fix DLL not found issue on Windows

* run cmake formatter

* attempt to fix DLL path on windows

* remove invalid set_target_properties call
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

5 participants