Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 9 additions & 2 deletions cuda_core/cuda/core/_program.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -771,6 +771,8 @@ cdef inline int Program_init(Program self, object code, str code_type, object op
assert_type(code, str)
if options.extra_sources is not None:
raise ValueError("extra_sources is not supported by the NVRTC backend (C++ code_type)")
if options.use_libdevice:
raise ValueError("use_libdevice is not supported by the NVRTC backend (C++ code_type)")

# TODO: support pre-loaded headers & include names
code_bytes = code.encode()
Expand All @@ -789,6 +791,8 @@ cdef inline int Program_init(Program self, object code, str code_type, object op
assert_type(code, str)
if options.extra_sources is not None:
raise ValueError("extra_sources is not supported by the PTX backend.")
if options.use_libdevice:
raise ValueError("use_libdevice is not supported by the PTX backend.")

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.

It seems deprecation is a much more stable option than directly removing .

if code_type == "c++":
    assert_type(code, str)
    if options.extra_sources is not None:
        raise ValueError("extra_sources is not supported by the NVRTC backend (C++ code_type)")
    if options.use_libdevice:
        warnings.warn(
            "use_libdevice is only supported by the NVVM backend; it is ignored "
            "on the NVRTC and PTX backend and will raise ValueError in a future release.",
            DeprecationWarning,
            stacklevel=3,
        )

@leofang @rwgk what do you think?

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.

codex (in addition to the findings posted under this comment):

Good point. Although the documented NVVM-only contract makes an immediate error defensible as a bug fix, I agree that warning is the safer behavior for 1.x. The ignored behavior was explicitly codified before 1.0 by test_make_program_cache_key_use_libdevice_ignored_for_non_nvvm.

I’d mirror #2658: emit a visible UserWarning for both code_type="c++" and "ptx" and continue ignoring the option. I would not use DeprecationWarning, because ProgramOptions.use_libdevice itself is not deprecated—it remains supported for NVVM. We should still remove the misplaced check from the unknown-code_type branch so the invalid code type remains the primary error.

If we decide these combinations should eventually raise, our support policy puts that change at 2.0.0, and we should state that version explicitly. Also, agreed on tightening the regex to the full expected message.

code_bytes = code.encode()
self._code = code_bytes
self._linker = Linker(
Expand Down Expand Up @@ -835,9 +839,12 @@ cdef inline int Program_init(Program self, object code, str code_type, object op
self._linker = None

else:
# No use_libdevice check here: this branch is only reached for a
# code_type that is not a backend at all, and an unrecognised
# code_type is the error worth reporting. The per-backend guards
# above mirror the extra_sources ones and are what actually
# enforce "NVVM only", which is what ProgramOptions documents.
supported_code_types = tuple(x.value for x in SourceCodeType)
if options.use_libdevice:
raise ValueError("use_libdevice is only supported by the NVVM backend")
raise RuntimeError(f"Unsupported {code_type=} ({supported_code_types=})")

return 0
Expand Down
8 changes: 8 additions & 0 deletions cuda_core/docs/source/release/1.2.0-notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,14 @@ Fixes and enhancements
Windows, both ``ctypes.CFUNCTYPE`` and ``ctypes.WINFUNCTYPE`` are accepted.
(`#2439 <https://github.com/NVIDIA/cuda-python/issues/2439>`__)

- :class:`Program` now rejects ``use_libdevice=True`` for ``code_type="c++"``
and ``code_type="ptx"``, as :class:`ProgramOptions` documents. The guard was
written in ``Program_init``'s unrecognised-``code_type`` branch, so the two
real non-NVVM backends accepted the option silently and never linked
libdevice, leaving the caller with undefined-symbol errors at link time.
Conversely, an unrecognised ``code_type`` combined with ``use_libdevice=True``
now reports the ``code_type``, not libdevice.

Deprecation Notices
-------------------

Expand Down
38 changes: 38 additions & 0 deletions cuda_core/tests/test_program.py
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,20 @@ def test_program_init_invalid_code_type():
Program(code, "FORTRAN")


@pytest.mark.agent_authored(model="claude-opus-5")
def test_program_init_invalid_code_type_reports_the_code_type():
"""An unrecognised code_type is the error worth reporting, even when
use_libdevice is set.

The use_libdevice guard used to live in this branch, so a typo'd
code_type combined with use_libdevice=True reported
"use_libdevice is only supported by the NVVM backend" and never
mentioned that the code_type was the actual problem.
"""
with pytest.raises(RuntimeError, match=r"^Unsupported code_type='fortran'"):
Program("goto 100", "FORTRAN", ProgramOptions(arch="sm_80", use_libdevice=True))

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.

Regex can be :

match=r"^Unsupported code_type='fortran' \(supported_code_types=\('c\+\+', 'ptx', 'nvvm'\)\)$"



def test_program_init_invalid_code_format():
code = 12345
with pytest.raises(TypeError):
Expand Down Expand Up @@ -718,6 +732,22 @@ def test_cpp_program_with_extra_sources():
Program(code, "c++", options)


@pytest.mark.agent_authored(model="claude-opus-5")
def test_cpp_program_with_use_libdevice():
"""NVRTC has no libdevice loading path.

The guard used to sit in Program_init's unrecognised-code_type branch, so
"c++" accepted use_libdevice=True silently: Program._use_libdevice stays
False (it is only set inside the nvvm branch), libdevice is never linked,
and the caller finds out from undefined-symbol errors at link time instead
of from the up-front ValueError ProgramOptions documents.
"""
code = 'extern "C" __global__ void my_kernel(){}'
options = ProgramOptions(use_libdevice=True)
with pytest.raises(ValueError, match="use_libdevice is not supported by the NVRTC backend"):
Program(code, "c++", options)


def test_program_options_as_bytes_nvrtc():
"""Test ProgramOptions.as_bytes() for NVRTC backend"""
options = ProgramOptions(arch="sm_80", debug=True, lineinfo=True, ftz=True)
Expand Down Expand Up @@ -831,6 +861,14 @@ def test_ptx_program_extra_sources_unsupported(ptx_code_object):
Program(ptx_code_object.code.decode(), "ptx", options)


@pytest.mark.agent_authored(model="claude-opus-5")
def test_ptx_program_use_libdevice_unsupported(ptx_code_object):
"""PTX goes through the Linker, which has no libdevice loading path."""
options = ProgramOptions(use_libdevice=True)
with pytest.raises(ValueError, match="use_libdevice is not supported by the PTX backend"):
Program(ptx_code_object.code.decode(), "ptx", options)


def test_ptx_program_handle_is_linker_handle(init_cuda, ptx_code_object):
"""Program.handle for the PTX backend delegates to the linker handle."""
program = Program(ptx_code_object.code.decode(), "ptx")
Expand Down
Loading