diff --git a/cuda_bindings/cuda/bindings/_internal/nvvm.pxd b/cuda_bindings/cuda/bindings/_internal/nvvm.pxd index 1a8569488..1f3b9662e 100644 --- a/cuda_bindings/cuda/bindings/_internal/nvvm.pxd +++ b/cuda_bindings/cuda/bindings/_internal/nvvm.pxd @@ -11,6 +11,7 @@ from ..cynvvm cimport * # Wrapper functions ############################################################################### +cdef const char* _nvvmGetErrorString(nvvmResult result) except?NULL nogil cdef nvvmResult _nvvmVersion(int* major, int* minor) except?_NVVMRESULT_INTERNAL_LOADING_ERROR nogil cdef nvvmResult _nvvmIRVersion(int* majorIR, int* minorIR, int* majorDbg, int* minorDbg) except?_NVVMRESULT_INTERNAL_LOADING_ERROR nogil cdef nvvmResult _nvvmCreateProgram(nvvmProgram* prog) except?_NVVMRESULT_INTERNAL_LOADING_ERROR nogil diff --git a/cuda_bindings/cuda/bindings/_internal/nvvm_linux.pyx b/cuda_bindings/cuda/bindings/_internal/nvvm_linux.pyx index 8759096a4..34df56e9c 100644 --- a/cuda_bindings/cuda/bindings/_internal/nvvm_linux.pyx +++ b/cuda_bindings/cuda/bindings/_internal/nvvm_linux.pyx @@ -36,6 +36,7 @@ cdef extern from "" nogil: cdef bint __py_nvvm_init = False cdef void* __cuDriverGetVersion = NULL +cdef void* __nvvmGetErrorString = NULL cdef void* __nvvmVersion = NULL cdef void* __nvvmIRVersion = NULL cdef void* __nvvmCreateProgram = NULL @@ -82,6 +83,13 @@ cdef int _check_or_init_nvvm() except -1 nogil: handle = NULL # Load function + global __nvvmGetErrorString + __nvvmGetErrorString = dlsym(RTLD_DEFAULT, 'nvvmGetErrorString') + if __nvvmGetErrorString == NULL: + if handle == NULL: + handle = load_library(driver_ver) + __nvvmGetErrorString = dlsym(handle, 'nvvmGetErrorString') + global __nvvmVersion __nvvmVersion = dlsym(RTLD_DEFAULT, 'nvvmVersion') if __nvvmVersion == NULL: @@ -181,6 +189,9 @@ cpdef dict _inspect_function_pointers(): _check_or_init_nvvm() cdef dict data = {} + global __nvvmGetErrorString + data["__nvvmGetErrorString"] = __nvvmGetErrorString + global __nvvmVersion data["__nvvmVersion"] = __nvvmVersion @@ -232,6 +243,16 @@ cpdef _inspect_function_pointer(str name): # Wrapper functions ############################################################################### +cdef const char* _nvvmGetErrorString(nvvmResult result) except?NULL nogil: + global __nvvmGetErrorString + _check_or_init_nvvm() + if __nvvmGetErrorString == NULL: + with gil: + raise FunctionNotFoundError("function nvvmGetErrorString is not found") + return (__nvvmGetErrorString)( + result) + + cdef nvvmResult _nvvmVersion(int* major, int* minor) except?_NVVMRESULT_INTERNAL_LOADING_ERROR nogil: global __nvvmVersion _check_or_init_nvvm() diff --git a/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx b/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx index 0a7eae320..f809a5280 100644 --- a/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx +++ b/cuda_bindings/cuda/bindings/_internal/nvvm_windows.pyx @@ -23,6 +23,7 @@ LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100 cdef bint __py_nvvm_init = False cdef void* __cuDriverGetVersion = NULL +cdef void* __nvvmGetErrorString = NULL cdef void* __nvvmVersion = NULL cdef void* __nvvmIRVersion = NULL cdef void* __nvvmCreateProgram = NULL @@ -62,6 +63,12 @@ cdef int _check_or_init_nvvm() except -1 nogil: handle = path_finder._load_nvidia_dynamic_library("nvvm").handle # Load function + global __nvvmGetErrorString + try: + __nvvmGetErrorString = win32api.GetProcAddress(handle, 'nvvmGetErrorString') + except: + pass + global __nvvmVersion try: __nvvmVersion = win32api.GetProcAddress(handle, 'nvvmVersion') @@ -149,6 +156,9 @@ cpdef dict _inspect_function_pointers(): _check_or_init_nvvm() cdef dict data = {} + global __nvvmGetErrorString + data["__nvvmGetErrorString"] = __nvvmGetErrorString + global __nvvmVersion data["__nvvmVersion"] = __nvvmVersion @@ -200,6 +210,16 @@ cpdef _inspect_function_pointer(str name): # Wrapper functions ############################################################################### +cdef const char* _nvvmGetErrorString(nvvmResult result) except?NULL nogil: + global __nvvmGetErrorString + _check_or_init_nvvm() + if __nvvmGetErrorString == NULL: + with gil: + raise FunctionNotFoundError("function nvvmGetErrorString is not found") + return (__nvvmGetErrorString)( + result) + + cdef nvvmResult _nvvmVersion(int* major, int* minor) except?_NVVMRESULT_INTERNAL_LOADING_ERROR nogil: global __nvvmVersion _check_or_init_nvvm() diff --git a/cuda_bindings/cuda/bindings/cynvvm.pxd b/cuda_bindings/cuda/bindings/cynvvm.pxd index cea1ce10f..64e807703 100644 --- a/cuda_bindings/cuda/bindings/cynvvm.pxd +++ b/cuda_bindings/cuda/bindings/cynvvm.pxd @@ -33,6 +33,7 @@ ctypedef void* nvvmProgram 'nvvmProgram' # Functions ############################################################################### +cdef const char* nvvmGetErrorString(nvvmResult result) except?NULL nogil cdef nvvmResult nvvmVersion(int* major, int* minor) except?_NVVMRESULT_INTERNAL_LOADING_ERROR nogil cdef nvvmResult nvvmIRVersion(int* majorIR, int* minorIR, int* majorDbg, int* minorDbg) except?_NVVMRESULT_INTERNAL_LOADING_ERROR nogil cdef nvvmResult nvvmCreateProgram(nvvmProgram* prog) except?_NVVMRESULT_INTERNAL_LOADING_ERROR nogil diff --git a/cuda_bindings/cuda/bindings/cynvvm.pyx b/cuda_bindings/cuda/bindings/cynvvm.pyx index 5c1a818bb..b3813fc88 100644 --- a/cuda_bindings/cuda/bindings/cynvvm.pyx +++ b/cuda_bindings/cuda/bindings/cynvvm.pyx @@ -11,6 +11,10 @@ from ._internal cimport nvvm as _nvvm # Wrapper functions ############################################################################### +cdef const char* nvvmGetErrorString(nvvmResult result) except?NULL nogil: + return _nvvm._nvvmGetErrorString(result) + + cdef nvvmResult nvvmVersion(int* major, int* minor) except?_NVVMRESULT_INTERNAL_LOADING_ERROR nogil: return _nvvm._nvvmVersion(major, minor) diff --git a/cuda_bindings/cuda/bindings/nvvm.pxd b/cuda_bindings/cuda/bindings/nvvm.pxd index f8564f86a..4712d4fb0 100644 --- a/cuda_bindings/cuda/bindings/nvvm.pxd +++ b/cuda_bindings/cuda/bindings/nvvm.pxd @@ -27,6 +27,7 @@ ctypedef nvvmResult _Result # Functions ############################################################################### +cpdef str get_error_string(int result) cpdef tuple version() cpdef tuple ir_version() cpdef intptr_t create_program() except? 0 diff --git a/cuda_bindings/cuda/bindings/nvvm.pyx b/cuda_bindings/cuda/bindings/nvvm.pyx index 0a35150e5..db5bc367a 100644 --- a/cuda_bindings/cuda/bindings/nvvm.pyx +++ b/cuda_bindings/cuda/bindings/nvvm.pyx @@ -73,6 +73,19 @@ cpdef destroy_program(intptr_t prog): check_status(status) +cpdef str get_error_string(int result): + """Get the message string for the given ``nvvmResult`` code. + + Args: + result (Result): NVVM API result code. + + .. seealso:: `nvvmGetErrorString` + """ + cdef bytes _output_ + _output_ = nvvmGetErrorString(<_Result>result) + return _output_.decode() + + cpdef tuple version(): """Get the NVVM version. diff --git a/cuda_bindings/tests/test_nvvm.py b/cuda_bindings/tests/test_nvvm.py index db8481a92..7ea3be9d5 100644 --- a/cuda_bindings/tests/test_nvvm.py +++ b/cuda_bindings/tests/test_nvvm.py @@ -194,6 +194,20 @@ def get_program_log(prog): return buffer.decode(errors="backslashreplace") +def test_get_error_string(): + num_success = 0 + num_errors = 0 + for enum_obj in nvvm.Result: + es = nvvm.get_error_string(enum_obj) + if enum_obj is nvvm.Result.SUCCESS: + num_success += 1 + else: + assert es.startswith("NVVM_ERROR") + num_errors += 1 + assert num_success == 1 + assert num_errors > 1 # smoke check is sufficient + + def test_nvvm_version(): ver = nvvm.version() assert len(ver) == 2