This commit is contained in:
2026-04-10 15:06:59 +02:00
parent 3031b7153b
commit e5a4711004
7806 changed files with 1918528 additions and 335 deletions

View File

@@ -0,0 +1,8 @@
from numba.cuda.testing import ensure_supported_ccs_initialized
from numba.testing import load_testsuite
import os
def load_tests(loader, tests, pattern):
ensure_supported_ccs_initialized()
return load_testsuite(loader, os.path.dirname(__file__))

View File

@@ -0,0 +1,359 @@
import unittest
import itertools
import numpy as np
from numba.cuda.cudadrv.dummyarray import Array
from numba.cuda.testing import skip_on_cudasim
@skip_on_cudasim("Tests internals of the CUDA driver device array")
class TestSlicing(unittest.TestCase):
def assertSameContig(self, arr, nparr):
attrs = 'C_CONTIGUOUS', 'F_CONTIGUOUS'
for attr in attrs:
if arr.flags[attr] != nparr.flags[attr]:
if arr.size == 0 and nparr.size == 0:
# numpy <=1.7 bug that some empty array are contiguous and
# some are not
pass
else:
self.fail("contiguous flag mismatch:\ngot=%s\nexpect=%s" %
(arr.flags, nparr.flags))
#### 1D
def test_slice0_1d(self):
nparr = np.empty(4)
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
self.assertSameContig(arr, nparr)
xx = -2, -1, 0, 1, 2
for x in xx:
expect = nparr[x:]
got = arr[x:]
self.assertSameContig(got, expect)
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
def test_slice1_1d(self):
nparr = np.empty(4)
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
xx = -2, -1, 0, 1, 2
for x in xx:
expect = nparr[:x]
got = arr[:x]
self.assertSameContig(got, expect)
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
def test_slice2_1d(self):
nparr = np.empty(4)
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
xx = -2, -1, 0, 1, 2
for x, y in itertools.product(xx, xx):
expect = nparr[x:y]
got = arr[x:y]
self.assertSameContig(got, expect)
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
#### 2D
def test_slice0_2d(self):
nparr = np.empty((4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
xx = -2, 0, 1, 2
for x in xx:
expect = nparr[x:]
got = arr[x:]
self.assertSameContig(got, expect)
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
for x, y in itertools.product(xx, xx):
expect = nparr[x:, y:]
got = arr[x:, y:]
self.assertSameContig(got, expect)
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
def test_slice1_2d(self):
nparr = np.empty((4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
xx = -2, 0, 2
for x in xx:
expect = nparr[:x]
got = arr[:x]
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
self.assertSameContig(got, expect)
for x, y in itertools.product(xx, xx):
expect = nparr[:x, :y]
got = arr[:x, :y]
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
self.assertSameContig(got, expect)
def test_slice2_2d(self):
nparr = np.empty((4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
xx = -2, 0, 2
for s, t, u, v in itertools.product(xx, xx, xx, xx):
expect = nparr[s:t, u:v]
got = arr[s:t, u:v]
self.assertSameContig(got, expect)
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
for x, y in itertools.product(xx, xx):
expect = nparr[s:t, u:v]
got = arr[s:t, u:v]
self.assertSameContig(got, expect)
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
#### Strided
def test_strided_1d(self):
nparr = np.empty(4)
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
xx = -2, -1, 1, 2
for x in xx:
expect = nparr[::x]
got = arr[::x]
self.assertSameContig(got, expect)
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
def test_strided_2d(self):
nparr = np.empty((4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
xx = -2, -1, 1, 2
for a, b in itertools.product(xx, xx):
expect = nparr[::a, ::b]
got = arr[::a, ::b]
self.assertSameContig(got, expect)
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
def test_strided_3d(self):
nparr = np.empty((4, 5, 6))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
xx = -2, -1, 1, 2
for a, b, c in itertools.product(xx, xx, xx):
expect = nparr[::a, ::b, ::c]
got = arr[::a, ::b, ::c]
self.assertSameContig(got, expect)
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
def test_issue_2766(self):
z = np.empty((1, 2, 3))
z = np.transpose(z, axes=(2, 0, 1))
arr = Array.from_desc(0, z.shape, z.strides, z.itemsize)
self.assertEqual(z.flags['C_CONTIGUOUS'], arr.flags['C_CONTIGUOUS'])
self.assertEqual(z.flags['F_CONTIGUOUS'], arr.flags['F_CONTIGUOUS'])
@skip_on_cudasim("Tests internals of the CUDA driver device array")
class TestReshape(unittest.TestCase):
def test_reshape_2d2d(self):
nparr = np.empty((4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
expect = nparr.reshape(5, 4)
got = arr.reshape(5, 4)[0]
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
def test_reshape_2d1d(self):
nparr = np.empty((4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
expect = nparr.reshape(5 * 4)
got = arr.reshape(5 * 4)[0]
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
def test_reshape_3d3d(self):
nparr = np.empty((3, 4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
expect = nparr.reshape(5, 3, 4)
got = arr.reshape(5, 3, 4)[0]
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
def test_reshape_3d2d(self):
nparr = np.empty((3, 4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
expect = nparr.reshape(3 * 4, 5)
got = arr.reshape(3 * 4, 5)[0]
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
def test_reshape_3d1d(self):
nparr = np.empty((3, 4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
expect = nparr.reshape(3 * 4 * 5)
got = arr.reshape(3 * 4 * 5)[0]
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
def test_reshape_infer2d2d(self):
nparr = np.empty((4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
expect = nparr.reshape(-1, 4)
got = arr.reshape(-1, 4)[0]
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
def test_reshape_infer2d1d(self):
nparr = np.empty((4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
expect = nparr.reshape(-1)
got = arr.reshape(-1)[0]
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
def test_reshape_infer3d3d(self):
nparr = np.empty((3, 4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
expect = nparr.reshape(5, -1, 4)
got = arr.reshape(5, -1, 4)[0]
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
def test_reshape_infer3d2d(self):
nparr = np.empty((3, 4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
expect = nparr.reshape(3, -1)
got = arr.reshape(3, -1)[0]
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
def test_reshape_infer3d1d(self):
nparr = np.empty((3, 4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
expect = nparr.reshape(-1)
got = arr.reshape(-1)[0]
self.assertEqual(got.shape, expect.shape)
self.assertEqual(got.strides, expect.strides)
def test_reshape_infer_two_unknowns(self):
nparr = np.empty((3, 4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
with self.assertRaises(ValueError) as raises:
arr.reshape(-1, -1, 3)
self.assertIn('can only specify one unknown dimension',
str(raises.exception))
def test_reshape_infer_invalid_shape(self):
nparr = np.empty((3, 4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
with self.assertRaises(ValueError) as raises:
arr.reshape(-1, 7)
expected_message = 'cannot infer valid shape for unknown dimension'
self.assertIn(expected_message, str(raises.exception))
@skip_on_cudasim("Tests internals of the CUDA driver device array")
class TestSqueeze(unittest.TestCase):
def test_squeeze(self):
nparr = np.empty((1, 2, 1, 4, 1, 3))
arr = Array.from_desc(
0, nparr.shape, nparr.strides, nparr.dtype.itemsize
)
def _assert_equal_shape_strides(arr1, arr2):
self.assertEqual(arr1.shape, arr2.shape)
self.assertEqual(arr1.strides, arr2.strides)
_assert_equal_shape_strides(arr, nparr)
_assert_equal_shape_strides(arr.squeeze()[0], nparr.squeeze())
for axis in (0, 2, 4, (0, 2), (0, 4), (2, 4), (0, 2, 4)):
_assert_equal_shape_strides(
arr.squeeze(axis=axis)[0], nparr.squeeze(axis=axis)
)
def test_squeeze_invalid_axis(self):
nparr = np.empty((1, 2, 1, 4, 1, 3))
arr = Array.from_desc(
0, nparr.shape, nparr.strides, nparr.dtype.itemsize
)
with self.assertRaises(ValueError):
arr.squeeze(axis=1)
with self.assertRaises(ValueError):
arr.squeeze(axis=(2, 3))
@skip_on_cudasim("Tests internals of the CUDA driver device array")
class TestExtent(unittest.TestCase):
def test_extent_1d(self):
nparr = np.empty(4)
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
s, e = arr.extent
self.assertEqual(e - s, nparr.size * nparr.dtype.itemsize)
def test_extent_2d(self):
nparr = np.empty((4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
s, e = arr.extent
self.assertEqual(e - s, nparr.size * nparr.dtype.itemsize)
def test_extent_iter_1d(self):
nparr = np.empty(4)
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
[ext] = list(arr.iter_contiguous_extent())
self.assertEqual(ext, arr.extent)
def test_extent_iter_2d(self):
nparr = np.empty((4, 5))
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
[ext] = list(arr.iter_contiguous_extent())
self.assertEqual(ext, arr.extent)
self.assertEqual(len(list(arr[::2].iter_contiguous_extent())), 2)
@skip_on_cudasim("Tests internals of the CUDA driver device array")
class TestIterate(unittest.TestCase):
def test_for_loop(self):
# for #4201
N = 5
nparr = np.empty(N)
arr = Array.from_desc(0, nparr.shape, nparr.strides,
nparr.dtype.itemsize)
x = 0 # just a placeholder
# this loop should not raise AssertionError
for val in arr:
x = val # noqa: F841
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,36 @@
from numba.cuda.testing import unittest, skip_on_cudasim
import operator
from numba.core import types, typing
from numba.cuda.cudadrv import nvvm
@unittest.skipIf(not nvvm.is_available(), "No libNVVM")
@skip_on_cudasim("Skip on simulator due to use of cuda_target")
class TestFunctionResolution(unittest.TestCase):
def test_fp16_binary_operators(self):
from numba.cuda.descriptor import cuda_target
ops = (operator.add, operator.iadd, operator.sub, operator.isub,
operator.mul, operator.imul)
for op in ops:
fp16 = types.float16
typingctx = cuda_target.typing_context
typingctx.refresh()
fnty = typingctx.resolve_value_type(op)
out = typingctx.resolve_function_type(fnty, (fp16, fp16), {})
self.assertEqual(out, typing.signature(fp16, fp16, fp16),
msg=str(out))
def test_fp16_unary_operators(self):
from numba.cuda.descriptor import cuda_target
ops = (operator.neg, abs)
for op in ops:
fp16 = types.float16
typingctx = cuda_target.typing_context
typingctx.refresh()
fnty = typingctx.resolve_value_type(op)
out = typingctx.resolve_function_type(fnty, (fp16,), {})
self.assertEqual(out, typing.signature(fp16, fp16), msg=str(out))
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,49 @@
from numba.tests.support import run_in_subprocess
import unittest
class TestImport(unittest.TestCase):
def test_no_impl_import(self):
"""
Tests that importing cuda doesn't trigger the import of modules
containing lowering implementation that would likely install things in
the builtins registry and have side effects impacting other targets.
"""
banlist = (
'numba.cpython.slicing',
'numba.cpython.tupleobj',
'numba.cpython.enumimpl',
'numba.cpython.hashing',
'numba.cpython.heapq',
'numba.cpython.iterators',
'numba.cpython.numbers',
'numba.cpython.rangeobj',
'numba.cpython.cmathimpl',
'numba.cpython.mathimpl',
'numba.cpython.printimpl',
'numba.cpython.randomimpl',
'numba.core.optional',
'numba.misc.gdb_hook',
'numba.misc.literal',
'numba.misc.cffiimpl',
'numba.np.linalg',
'numba.np.polynomial',
'numba.np.arraymath',
'numba.np.npdatetime',
'numba.np.npyimpl',
'numba.typed.typeddict',
'numba.typed.typedlist',
'numba.experimental.jitclass.base',
)
code = "import sys; from numba import cuda; print(list(sys.modules))"
out, _ = run_in_subprocess(code)
modlist = set(eval(out.strip()))
unexpected = set(banlist) & set(modlist)
self.assertFalse(unexpected, "some modules unexpectedly imported")
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,238 @@
import sys
import os
import multiprocessing as mp
import warnings
from numba.core.config import IS_WIN32, IS_OSX
from numba.core.errors import NumbaWarning
from numba.cuda.cudadrv import nvvm
from numba.cuda.testing import (
unittest,
skip_on_cudasim,
SerialMixin,
skip_unless_conda_cudatoolkit,
)
from numba.cuda.cuda_paths import (
_get_libdevice_path_decision,
_get_nvvm_path_decision,
_get_cudalib_dir_path_decision,
get_system_ctk,
)
has_cuda = nvvm.is_available()
has_mp_get_context = hasattr(mp, 'get_context')
class LibraryLookupBase(SerialMixin, unittest.TestCase):
def setUp(self):
ctx = mp.get_context('spawn')
qrecv = ctx.Queue()
qsend = ctx.Queue()
self.qsend = qsend
self.qrecv = qrecv
self.child_process = ctx.Process(
target=check_lib_lookup,
args=(qrecv, qsend),
daemon=True,
)
self.child_process.start()
def tearDown(self):
self.qsend.put(self.do_terminate)
self.child_process.join(3)
# Ensure the process is terminated
self.assertIsNotNone(self.child_process)
def remote_do(self, action):
self.qsend.put(action)
out = self.qrecv.get()
self.assertNotIsInstance(out, BaseException)
return out
@staticmethod
def do_terminate():
return False, None
def remove_env(name):
try:
del os.environ[name]
except KeyError:
return False
else:
return True
def check_lib_lookup(qout, qin):
status = True
while status:
try:
action = qin.get()
except Exception as e:
qout.put(e)
status = False
else:
try:
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("always", NumbaWarning)
status, result = action()
qout.put(result + (w,))
except Exception as e:
qout.put(e)
status = False
@skip_on_cudasim('Library detection unsupported in the simulator')
@unittest.skipUnless(has_mp_get_context, 'mp.get_context not available')
@skip_unless_conda_cudatoolkit('test assumes conda installed cudatoolkit')
class TestLibDeviceLookUp(LibraryLookupBase):
def test_libdevice_path_decision(self):
# Check that the default is using conda environment
by, info, warns = self.remote_do(self.do_clear_envs)
if has_cuda:
self.assertEqual(by, 'Conda environment')
else:
self.assertEqual(by, "<unknown>")
self.assertIsNone(info)
self.assertFalse(warns)
# Check that CUDA_HOME works by removing conda-env
by, info, warns = self.remote_do(self.do_set_cuda_home)
self.assertEqual(by, 'CUDA_HOME')
self.assertEqual(info, os.path.join('mycudahome', 'nvvm', 'libdevice'))
self.assertFalse(warns)
if get_system_ctk() is None:
# Fake remove conda environment so no cudatoolkit is available
by, info, warns = self.remote_do(self.do_clear_envs)
self.assertEqual(by, '<unknown>')
self.assertIsNone(info)
self.assertFalse(warns)
else:
# Use system available cudatoolkit
by, info, warns = self.remote_do(self.do_clear_envs)
self.assertEqual(by, 'System')
self.assertFalse(warns)
@staticmethod
def do_clear_envs():
remove_env('CUDA_HOME')
remove_env('CUDA_PATH')
return True, _get_libdevice_path_decision()
@staticmethod
def do_set_cuda_home():
os.environ['CUDA_HOME'] = os.path.join('mycudahome')
_fake_non_conda_env()
return True, _get_libdevice_path_decision()
@skip_on_cudasim('Library detection unsupported in the simulator')
@unittest.skipUnless(has_mp_get_context, 'mp.get_context not available')
@skip_unless_conda_cudatoolkit('test assumes conda installed cudatoolkit')
class TestNvvmLookUp(LibraryLookupBase):
def test_nvvm_path_decision(self):
# Check that the default is using conda environment
by, info, warns = self.remote_do(self.do_clear_envs)
if has_cuda:
self.assertEqual(by, 'Conda environment')
else:
self.assertEqual(by, "<unknown>")
self.assertIsNone(info)
self.assertFalse(warns)
# Check that CUDA_HOME works by removing conda-env
by, info, warns = self.remote_do(self.do_set_cuda_home)
self.assertEqual(by, 'CUDA_HOME')
self.assertFalse(warns)
if IS_WIN32:
self.assertEqual(info, os.path.join('mycudahome', 'nvvm', 'bin'))
elif IS_OSX:
self.assertEqual(info, os.path.join('mycudahome', 'nvvm', 'lib'))
else:
self.assertEqual(info, os.path.join('mycudahome', 'nvvm', 'lib64'))
if get_system_ctk() is None:
# Fake remove conda environment so no cudatoolkit is available
by, info, warns = self.remote_do(self.do_clear_envs)
self.assertEqual(by, '<unknown>')
self.assertIsNone(info)
self.assertFalse(warns)
else:
# Use system available cudatoolkit
by, info, warns = self.remote_do(self.do_clear_envs)
self.assertEqual(by, 'System')
self.assertFalse(warns)
@staticmethod
def do_clear_envs():
remove_env('CUDA_HOME')
remove_env('CUDA_PATH')
return True, _get_nvvm_path_decision()
@staticmethod
def do_set_cuda_home():
os.environ['CUDA_HOME'] = os.path.join('mycudahome')
_fake_non_conda_env()
return True, _get_nvvm_path_decision()
@skip_on_cudasim('Library detection unsupported in the simulator')
@unittest.skipUnless(has_mp_get_context, 'mp.get_context not available')
@skip_unless_conda_cudatoolkit('test assumes conda installed cudatoolkit')
class TestCudaLibLookUp(LibraryLookupBase):
def test_cudalib_path_decision(self):
# Check that the default is using conda environment
by, info, warns = self.remote_do(self.do_clear_envs)
if has_cuda:
self.assertEqual(by, 'Conda environment')
else:
self.assertEqual(by, "<unknown>")
self.assertIsNone(info)
self.assertFalse(warns)
# Check that CUDA_HOME works by removing conda-env
self.remote_do(self.do_clear_envs)
by, info, warns = self.remote_do(self.do_set_cuda_home)
self.assertEqual(by, 'CUDA_HOME')
self.assertFalse(warns)
if IS_WIN32:
self.assertEqual(info, os.path.join('mycudahome', 'bin'))
elif IS_OSX:
self.assertEqual(info, os.path.join('mycudahome', 'lib'))
else:
self.assertEqual(info, os.path.join('mycudahome', 'lib64'))
if get_system_ctk() is None:
# Fake remove conda environment so no cudatoolkit is available
by, info, warns = self.remote_do(self.do_clear_envs)
self.assertEqual(by, "<unknown>")
self.assertIsNone(info)
self.assertFalse(warns)
else:
# Use system available cudatoolkit
by, info, warns = self.remote_do(self.do_clear_envs)
self.assertEqual(by, 'System')
self.assertFalse(warns)
@staticmethod
def do_clear_envs():
remove_env('CUDA_HOME')
remove_env('CUDA_PATH')
return True, _get_cudalib_dir_path_decision()
@staticmethod
def do_set_cuda_home():
os.environ['CUDA_HOME'] = os.path.join('mycudahome')
_fake_non_conda_env()
return True, _get_cudalib_dir_path_decision()
def _fake_non_conda_env():
"""
Monkeypatch sys.prefix to hide the fact we are in a conda-env
"""
sys.prefix = ''
if __name__ == '__main__':
unittest.main()

View File

@@ -0,0 +1,54 @@
from numba.cuda.cudadrv import nvvm
from numba.cuda.testing import skip_on_cudasim
from numba.core import utils
from llvmlite import ir
from llvmlite import binding as llvm
import unittest
original = "call void @llvm.memset.p0i8.i64(" \
"i8* align 4 %arg.x.41, i8 0, i64 %0, i1 false)"
missing_align = "call void @llvm.memset.p0i8.i64(" \
"i8* %arg.x.41, i8 0, i64 %0, i1 false)"
@skip_on_cudasim('libNVVM not supported in simulator')
@unittest.skipIf(utils.MACHINE_BITS == 32, "CUDA not support for 32-bit")
@unittest.skipIf(not nvvm.is_available(), "No libNVVM")
class TestNvvmWithoutCuda(unittest.TestCase):
def test_nvvm_accepts_encoding(self):
# Test that NVVM will accept a constant containing all possible 8-bit
# characters. Taken from the test case added in llvmlite PR #53:
#
# https://github.com/numba/llvmlite/pull/53
#
# This test case is included in Numba to ensure that the encoding used
# by llvmlite (e.g. utf-8, latin1, etc.) does not result in an input to
# NVVM that it cannot parse correctly
# Create a module with a constant containing all 8-bit characters
c = ir.Constant(ir.ArrayType(ir.IntType(8), 256),
bytearray(range(256)))
m = ir.Module()
m.triple = 'nvptx64-nvidia-cuda'
nvvm.add_ir_version(m)
gv = ir.GlobalVariable(m, c.type, "myconstant")
gv.global_constant = True
gv.initializer = c
m.data_layout = nvvm.NVVM().data_layout
# Parse with LLVM then dump the parsed module into NVVM
parsed = llvm.parse_assembly(str(m))
ptx = nvvm.compile_ir(str(parsed))
# Ensure all characters appear in the generated constant array.
elements = ", ".join([str(i) for i in range(256)])
myconstant = f"myconstant[256] = {{{elements}}}".encode('utf-8')
self.assertIn(myconstant, ptx)
if __name__ == '__main__':
unittest.main()