Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
97 commits
Select commit Hold shift + click to select a range
a4db20b
add ltoir test support
abhilash1910 Nov 5, 2025
fb6cfb3
add options for multi-modules
abhilash1910 Nov 25, 2025
7aaed4e
add tests
abhilash1910 Nov 25, 2025
64c7f7d
add bitcode test
abhilash1910 Nov 25, 2025
42ba301
[pre-commit.ci] auto code formatting
pre-commit-ci[bot] Nov 25, 2025
7ca6899
fix format
abhilash1910 Nov 25, 2025
0674ea1
[pre-commit.ci] auto code formatting
pre-commit-ci[bot] Nov 25, 2025
03b1224
refresh
abhilash1910 Nov 26, 2025
033f11c
apply bitcode file from cupy_test helpers
abhilash1910 Dec 1, 2025
6e411ee
use 2 tuples
abhilash1910 Dec 1, 2025
b4c21db
Merge branch 'main' into nvvm_enhance
abhilash1910 Dec 2, 2025
aeb26aa
refresh
abhilash1910 Dec 3, 2025
b3d6d96
format
abhilash1910 Dec 3, 2025
edd6401
[pre-commit.ci] auto code formatting
pre-commit-ci[bot] Dec 3, 2025
d53e00b
Merge branch 'main' into nvvm_enhance
abhilash1910 Dec 7, 2025
8dbbafe
fix from upstream
abhilash1910 Dec 15, 2025
0174bb8
Merge branch 'main' into nvvm_enhance
abhilash1910 Dec 16, 2025
b78f0c3
refresh from upstream
abhilash1910 Dec 17, 2025
99a5593
fix tests
abhilash1910 Dec 17, 2025
783f6e5
take path_finder from PR 447
abhilash1910 Dec 17, 2025
5dbfb2d
add builder files
abhilash1910 Dec 17, 2025
0a9eea9
use python lists/tuples
abhilash1910 Dec 17, 2025
79138c0
libdevice integration
abhilash1910 Dec 18, 2025
25d336c
refresh
abhilash1910 Dec 19, 2025
32c1913
refresh
abhilash1910 Dec 19, 2025
01f03e5
refresh
abhilash1910 Dec 19, 2025
9a5d5fe
use cuda_pathfinder module for libdevice
abhilash1910 Dec 19, 2025
07c6199
rebase
abhilash1910 Feb 5, 2026
e1b19cc
rebase
abhilash1910 Feb 5, 2026
f89aac8
Merge branch 'main' into nvvm_enhance
abhilash1910 Feb 5, 2026
0ad13ae
Merge branch 'main' into nvvm_enhance
abhilash1910 Feb 10, 2026
dcdd100
tests
brandon-b-miller Feb 6, 2026
aca2e36
Address reviews
brandon-b-miller Feb 11, 2026
af6e70a
put libdevice stuff under _static_libs
brandon-b-miller Feb 11, 2026
b1d423f
refresh reviews
abhilash1910 Feb 11, 2026
4cedbb7
change program to cython per PR 1565
abhilash1910 Feb 11, 2026
d9aed9b
Merge branch 'main' into nvvm_enhance
abhilash1910 Feb 11, 2026
ca32d2b
fix import
abhilash1910 Feb 11, 2026
fac1907
fix tests
abhilash1910 Feb 12, 2026
4a01e06
fix ruff check
abhilash1910 Feb 12, 2026
2d5252f
ruff fix find_libdevice
abhilash1910 Feb 12, 2026
2976c24
[pre-commit.ci] auto code formatting
pre-commit-ci[bot] Feb 12, 2026
61c1e00
add spdx and copyright
abhilash1910 Feb 12, 2026
c6bea0c
rm redundant include and fix test
abhilash1910 Feb 12, 2026
b7866cf
[pre-commit.ci] auto code formatting
pre-commit-ci[bot] Feb 12, 2026
4283230
refresh tests
abhilash1910 Feb 12, 2026
78f4328
add correct libdevice for CTK> 13
abhilash1910 Feb 12, 2026
ddf4839
[pre-commit.ci] auto code formatting
pre-commit-ci[bot] Feb 12, 2026
cd3644e
revamp design of pathfinder as LocatedHeaderDir
abhilash1910 Feb 13, 2026
68b33a2
refresh
abhilash1910 Feb 13, 2026
631a113
[pre-commit.ci] auto code formatting
pre-commit-ci[bot] Feb 13, 2026
7a02aee
fix mypy errirs
abhilash1910 Feb 13, 2026
b8f2eb0
fix base var declaration
abhilash1910 Feb 13, 2026
434b3c9
format changes
abhilash1910 Feb 13, 2026
9f0a319
format changes
abhilash1910 Feb 13, 2026
f499487
rename to bitcodelib
abhilash1910 Feb 16, 2026
5ee41fe
refresh
abhilash1910 Feb 16, 2026
606652d
refresh
abhilash1910 Feb 16, 2026
88d5278
revert
abhilash1910 Feb 16, 2026
4cd7755
refresh test_nvvm to use cupy test helpers
abhilash1910 Feb 16, 2026
c562d28
refresh test_nvvm
abhilash1910 Feb 16, 2026
150fd26
[pre-commit.ci] auto code formatting
pre-commit-ci[bot] Feb 16, 2026
afe17b2
refresh with actual test
abhilash1910 Feb 16, 2026
0f1c393
rm try_common_paths
abhilash1910 Feb 16, 2026
9e7e75c
refresh 1
abhilash1910 Feb 16, 2026
56dc23f
[pre-commit.ci] auto code formatting
pre-commit-ci[bot] Feb 16, 2026
a19e9ee
refresh
abhilash1910 Feb 16, 2026
2748ce0
refresh
abhilash1910 Feb 16, 2026
8f44791
[pre-commit.ci] auto code formatting
pre-commit-ci[bot] Feb 16, 2026
6b1fc9f
refresh
abhilash1910 Feb 16, 2026
404963b
[pre-commit.ci] auto code formatting
pre-commit-ci[bot] Feb 16, 2026
dfe930e
Merge branch 'main' into abhilash1910→nvvm_enhance
rwgk Feb 17, 2026
bc27ed6
refresh pathfinder test after rebae
abhilash1910 Feb 17, 2026
9a7c5dc
Merge branch 'main' into abhilash1910→nvvm_enhance
rwgk Feb 17, 2026
82c65a1
Uniform handling of cuda_python_test_helpers dependency in cuda_bindi…
rwgk Feb 17, 2026
9bc68bb
pre-commit cleanup
rwgk Feb 17, 2026
38e87d2
Prefer installed cuda-python-test-helpers in test bootstrap.
rwgk Feb 17, 2026
4c2dc46
Remove cuda_core Pixi PYTHONPATH override for test helpers.
rwgk Feb 17, 2026
c93251a
Remove helper package install from coverage workflow.
rwgk Feb 17, 2026
57eb0b0
Use per-module pytest plugin registration for NVVM helper fixtures.
rwgk Feb 17, 2026
1357d34
Merge branch 'main' into abhilash1910→nvvm_enhance
rwgk Feb 17, 2026
c8484ee
Merge branch 'main' into abhilash1910→nvvm_enhance
rwgk Feb 17, 2026
f0eb1a7
Remove "Renamed" comments
rwgk Feb 17, 2026
7c6e2c9
Make bitcode locate/find consistently raise not-found errors.
rwgk Feb 17, 2026
b77f91b
Refocus bitcode-lib tests on real coverage and narrow mocks.
rwgk Feb 17, 2026
b250395
Merge branch 'main' into abhilash1910→nvvm_enhance
rwgk Feb 17, 2026
e98f32c
Undo accidental change in cuda_pathfinder/tests/test_find_nvidia_bina…
rwgk Feb 17, 2026
296aaf2
Use direct platform_aware.IS_WINDOWS import (rather than the detour t…
rwgk Feb 17, 2026
037b26a
Add found_via metadata for bitcode library discovery.
rwgk Feb 18, 2026
3f73de4
Export SUPPORTED_BITCODE_LIBS in cuda.pathfinder public API.
rwgk Feb 18, 2026
f7b9c4f
Merge branch 'main' into abhilash1910→nvvm_enhance
rwgk Feb 18, 2026
a3696c1
refresh
abhilash1910 Feb 18, 2026
815e574
[pre-commit.ci] auto code formatting
pre-commit-ci[bot] Feb 18, 2026
d72f087
refresh
abhilash1910 Feb 18, 2026
e62ecbd
[pre-commit.ci] auto code formatting
pre-commit-ci[bot] Feb 18, 2026
51f6009
Merge branch 'main' into nvvm_enhance
abhilash1910 Feb 18, 2026
701f54b
Serialize NVVM compile/libdevice mutation per Program instance.
rwgk Feb 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions cuda_core/cuda/core/experimental/_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,7 @@ class ProgramOptions:
split_compile: int | None = None
fdevice_syntax_only: bool | None = None
minimal: bool | None = None
extra_sources: Union[str, bytes, list[Union[str, bytes]], tuple[Union[str, bytes]]] | None = None

def __post_init__(self):
self._name = self.name.encode()
Expand Down Expand Up @@ -480,13 +481,19 @@ def __init__(self, code, code_type, options: ProgramOptions = None):
# TODO: support pre-loaded headers & include names
# TODO: allow tuples once NVIDIA/cuda-python#72 is resolved

if options.extra_sources is not None:
raise ValueError("extra_sources is not supported by the NVRTC backend (C++ code_type)")

self._mnff.handle = handle_return(nvrtc.nvrtcCreateProgram(code.encode(), options._name, 0, [], []))
Comment thread
leofang marked this conversation as resolved.
Outdated
self._mnff.backend = "NVRTC"
self._backend = "NVRTC"
self._linker = None

elif code_type == "ptx":
assert_type(code, str)
if options.extra_sources is not None:
raise ValueError("extra_sources is not supported by the PTX backend.")

self._linker = Linker(
ObjectCode._init(code.encode(), code_type), options=self._translate_program_options(options)
)
Expand All @@ -502,6 +509,29 @@ def __init__(self, code, code_type, options: ProgramOptions = None):
self._mnff.handle = nvvm.create_program()
self._mnff.backend = "NVVM"
nvvm.add_module_to_program(self._mnff.handle, code, len(code), options._name.decode())
if options.extra_sources is not None:
if isinstance(options.extra_sources, (str, bytes)):
extra_sources = [options.extra_sources]
elif isinstance(options.extra_sources, (list, tuple)):
extra_sources = options.extra_sources
else:
raise TypeError("extra_sources must be str, bytes, list, or tuple")

if len(extra_sources) == 0:
raise ValueError("extra_sources cannot be empty if provided")

for i, extra_source in enumerate(extra_sources):
if isinstance(extra_source, str):
extra_source = extra_source.encode("utf-8")
elif not isinstance(extra_source, (bytes, bytearray)):
raise TypeError(f"Extra source {i} must be provided as str, bytes, or bytearray")

if len(extra_source) == 0:
raise ValueError(f"Extra source {i} cannot be empty")

extra_name = f"{options.name}_extra_{i}"
nvvm.add_module_to_program(self._mnff.handle, extra_source, len(extra_source), extra_name)
Comment thread
abhilash1910 marked this conversation as resolved.
Outdated

self._backend = "NVVM"
self._linker = None

Expand Down
192 changes: 192 additions & 0 deletions cuda_core/tests/test_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -387,3 +387,195 @@ def test_nvvm_program_options(init_cuda, nvvm_ir, options):
assert ".visible .entry simple(" in ptx_text

program.close()


@nvvm_available
@pytest.mark.parametrize(
"options",
[
ProgramOptions(name="ltoir_test1", arch="sm_90", device_code_optimize=False),
ProgramOptions(name="ltoir_test2", arch="sm_100", link_time_optimization=True),
ProgramOptions(
name="ltoir_test3",
arch="sm_90",
ftz=True,
prec_sqrt=False,
prec_div=False,
fma=True,
device_code_optimize=True,
link_time_optimization=True,
),
],
)
def test_nvvm_program_options_ltoir(init_cuda, nvvm_ir, options):
"""Test NVVM programs for LTOIR with different options"""
program = Program(nvvm_ir, "nvvm", options)
assert program.backend == "NVVM"

ltoir_code = program.compile("ltoir")
assert isinstance(ltoir_code, ObjectCode)
assert ltoir_code.name == options.name
code_content = ltoir_code.code
assert len(code_content) > 0
program.close()
Comment thread
abhilash1910 marked this conversation as resolved.
Outdated


@nvvm_available
def test_nvvm_program_with_single_extra_source(nvvm_ir):
"""Test NVVM program with a single extra source"""
from cuda.core.experimental._program import _get_nvvm_module

nvvm = _get_nvvm_module()
major, minor, debug_major, debug_minor = nvvm.ir_version()
# helper nvvm ir for multiple module loading
helper_nvvm_ir = f"""target triple = "nvptx64-unknown-cuda"
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-i128:128:128-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64"

define i32 @helper_add(i32 %x) {{
entry:
%result = add i32 %x, 1
ret i32 %result
}}

!nvvmir.version = !{{!0}}
!0 = !{{i32 {major}, i32 {minor}, i32 {debug_major}, i32 {debug_minor}}}
""" # noqa: E501

options = ProgramOptions(name="multi_module_test", extra_sources=helper_nvvm_ir)
program = Program(nvvm_ir, "nvvm", options)

assert program.backend == "NVVM"

ptx_code = program.compile("ptx")
assert isinstance(ptx_code, ObjectCode)
assert ptx_code.name == "multi_module_test"

program.close()


@nvvm_available
def test_nvvm_program_with_multiple_extra_sources():
"""Test NVVM program with multiple extra sources"""
from cuda.core.experimental._program import _get_nvvm_module

nvvm = _get_nvvm_module()
major, minor, debug_major, debug_minor = nvvm.ir_version()

main_nvvm_ir = f"""target triple = "nvptx64-unknown-cuda"
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-i128:128:128-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64"

declare i32 @helper_add(i32) nounwind readnone
declare i32 @helper_mul(i32) nounwind readnone

define void @main_kernel(i32* %data) {{
entry:
%tid = call i32 @llvm.nvvm.read.ptx.sreg.tid.x()
%ptr = getelementptr inbounds i32, i32* %data, i32 %tid
%val = load i32, i32* %ptr, align 4

%val1 = call i32 @helper_add(i32 %val)
%val2 = call i32 @helper_mul(i32 %val1)

store i32 %val2, i32* %ptr, align 4
ret void
}}

declare i32 @llvm.nvvm.read.ptx.sreg.tid.x() nounwind readnone

!nvvm.annotations = !{{!0}}
!0 = !{{void (i32*)* @main_kernel, !"kernel", i32 1}}

!nvvmir.version = !{{!1}}
!1 = !{{i32 {major}, i32 {minor}, i32 {debug_major}, i32 {debug_minor}}}
""" # noqa: E501

helper1_ir = f"""target triple = "nvptx64-unknown-cuda"
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-i128:128:128-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64"

define i32 @helper_add(i32 %x) nounwind readnone {{
entry:
%result = add i32 %x, 1
ret i32 %result
}}

!nvvmir.version = !{{!0}}
!0 = !{{i32 {major}, i32 {minor}, i32 {debug_major}, i32 {debug_minor}}}
""" # noqa: E501

helper2_ir = f"""target triple = "nvptx64-unknown-cuda"
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-i128:128:128-f32:32:32-f64:64:64-v16:16:16-v32:32:32-v64:64:64-v128:128:128-n16:32:64"

define i32 @helper_mul(i32 %x) nounwind readnone {{
entry:
%result = mul i32 %x, 2
ret i32 %result
}}

!nvvmir.version = !{{!0}}
!0 = !{{i32 {major}, i32 {minor}, i32 {debug_major}, i32 {debug_minor}}}
""" # noqa: E501

options = ProgramOptions(name="nvvm_multi_helper_test", extra_sources=[helper1_ir, helper2_ir])
program = Program(main_nvvm_ir, "nvvm", options)

assert program.backend == "NVVM"
ptx_code = program.compile("ptx")
assert isinstance(ptx_code, ObjectCode)
assert ptx_code.name == "nvvm_multi_helper_test"

ltoir_code = program.compile("ltoir")
assert isinstance(ltoir_code, ObjectCode)
assert ltoir_code.name == "nvvm_multi_helper_test"

program.close()


@nvvm_available
def test_bitcode_format():
import os
from pathlib import Path

bitcode_path = os.environ.get("BITCODE_NVVM_PATH")
if not bitcode_path:
pytest.skip("BITCODE_NVVM_PATH environment variable is not set.Disabling the test.")
bitcode_file = Path(bitcode_path)
if not bitcode_file.exists():
pytest.skip(f"Bitcode file not found: {bitcode_path}")

if bitcode_file.suffix != ".bc":
pytest.skip(f"Expected .bc file, got: {bitcode_file.suffix}")
Comment thread
abhilash1910 marked this conversation as resolved.
Outdated

try:
with open(bitcode_file, "rb") as f:
bitcode_data = f.read()

if len(bitcode_data) < 4:
pytest.skip("Bitcode file appears to be empty or invalid")

options = ProgramOptions(name=f"existing_bitcode_{bitcode_file.stem}", arch="sm_90")
program = Program(bitcode_data, "nvvm", options)

assert program.backend == "NVVM"
ptx_result = program.compile("ptx")
assert isinstance(ptx_result, ObjectCode)
assert ptx_result.name.startswith("existing_bitcode_")
assert len(ptx_result.code) > 0
try:
ltoir_result = program.compile("ltoir")
assert isinstance(ltoir_result, ObjectCode)
assert len(ltoir_result.code) > 0
print(f"LTOIR size: {len(ltoir_result.code)} bytes")
except Exception as e:
print(f"LTOIR compilation failed : {e}")
program.close()
Comment thread
abhilash1910 marked this conversation as resolved.
Outdated
except Exception as e:
pytest.fail(f"Failed to compile existing bitcode file {bitcode_path}: {str(e)}")


def test_cpp_program_with_extra_sources():
# negative test with NVRTC with multiple sources
code = 'extern "C" __global__ void my_kernel(){}'
helper = 'extern "C" __global__ void helper(){}'
options = ProgramOptions(extra_sources=helper)
with pytest.raises(ValueError, match="extra_sources is not supported by the NVRTC backend"):
Program(code, "c++", options)