Skip to content
4 changes: 2 additions & 2 deletions docs/source/developer/threading_implementation.rst
Original file line number Diff line number Diff line change
Expand Up @@ -195,10 +195,10 @@ The general pattern for using ``get_num_threads`` in code generation is

.. code:: python

import llvmlite.llvmpy.core as lc
from llvmlite import ir as llvmir

get_num_threads = cgutils.get_or_insert_function(builder.module
lc.Type.function(lc.Type.int(types.intp.bitwidth), []),
llvmir.FunctionType(llvmir.IntType(types.intp.bitwidth), []),
name="get_num_threads")

num_threads = builder.call(get_num_threads, [])
Expand Down
2 changes: 1 addition & 1 deletion numba/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -789,7 +789,7 @@ def printf(self, builder, format_string, *args):
cstr = self.insert_const_string(mod, format_string)
else:
cstr = format_string
fnty = Type.function(Type.int(), (GENERIC_POINTER,), var_arg=True)
fnty = llvmir.FunctionType(llvmir.IntType(32), (GENERIC_POINTER,), var_arg=True)
Comment thread
esc marked this conversation as resolved.
fn = cgutils.get_or_insert_function(mod, fnty, "printf")
return builder.call(fn, (cstr,) + tuple(args))

Expand Down
26 changes: 26 additions & 0 deletions numba/core/boxing.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from numba.core import types, cgutils
from numba.core.pythonapi import box, unbox, reflect, NativeValue
from numba.core.errors import NumbaNotImplementedError
from numba.core.typing.typeof import typeof, Purpose

from numba.cpython import setobj, listobj
from numba.np import numpy_support
Expand Down Expand Up @@ -379,6 +380,31 @@ def unbox_slice(typ, obj, c):
sli.step = step
return NativeValue(sli._getvalue(), is_error=c.builder.not_(ok))

@box(types.SliceLiteral)
def box_slice_literal(typ, val, c):
# Check for integer overflows at compile time.
slice_lit = typ.literal_value
for field_name in ("start", "stop", "step"):
field_obj = getattr(slice_lit, field_name)
if isinstance(field_obj, int):
try:
typeof(field_obj, Purpose)
except ValueError as e:
raise ValueError((
f"Unable to create literal slice. "
f"Error encountered with {field_name} "
f"attribute. {str(e)}")
)

py_ctor, py_args = typ.literal_value.__reduce__()
serialized_ctor = c.pyapi.serialize_object(py_ctor)
serialized_args = c.pyapi.serialize_object(py_args)
ctor = c.pyapi.unserialize(serialized_ctor)
args = c.pyapi.unserialize(serialized_args)
obj = c.pyapi.call(ctor, args)
c.pyapi.decref(ctor)
c.pyapi.decref(args)
return obj

@unbox(types.StringLiteral)
def unbox_string_literal(typ, obj, c):
Expand Down
1 change: 0 additions & 1 deletion numba/core/pythonapi.py
Original file line number Diff line number Diff line change
Expand Up @@ -662,7 +662,6 @@ def complex_imag_as_double(self, cobj):
#
# Concrete slice API
#

def slice_as_ints(self, obj):
"""
Read the members of a slice of integers.
Expand Down
8 changes: 7 additions & 1 deletion numba/core/types/abstract.py
Original file line number Diff line number Diff line change
Expand Up @@ -443,7 +443,13 @@ def literal_type(self):
ctx = typing.Context()
try:
res = ctx.resolve_value_type(self.literal_value)
except ValueError:
except ValueError as e:

if "Int value is too large" in str(e):
# If a string literal cannot create an IntegerLiteral
# because of overflow we generate this message.
msg = f"Cannot create literal type. {str(e)}"
raise TypeError(msg)
# Not all literal types have a literal_value that can be
# resolved to a type, for example, LiteralStrKeyDict has a
# literal_value that is a python dict for which there's no
Expand Down
33 changes: 32 additions & 1 deletion numba/tests/test_cgutils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import unittest
from numba.core import types, typing, cgutils, cpu
from numba.core.compiler_lock import global_compiler_lock
from numba.tests.support import TestCase
from numba.tests.support import TestCase, run_in_subprocess


machine_int = ir.IntType(types.intp.bitwidth)
Expand Down Expand Up @@ -117,5 +117,36 @@ class S(cgutils.Structure):
inst.b = ir.Constant(ir.FloatType(), 4.56)


class TestCGContext(TestCase):
"""Tests for code generation context functionality"""

def test_printf(self):
# Tests the printf() method

value = 123456

code = f"""if 1:
from numba import njit, types
from numba.extending import intrinsic

@intrinsic
def printf(tyctx, int_arg):
sig = types.void(int_arg)
def codegen(cgctx, builder, sig, llargs):
cgctx.printf(builder, \"%d\\n\", *llargs)
return sig, codegen

@njit
def foo():
printf({value})

foo()
"""

out, _ = run_in_subprocess(code)
self.assertIn(str(value), out.decode())



if __name__ == '__main__':
unittest.main()
49 changes: 48 additions & 1 deletion numba/tests/test_slices.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import numpy as np

from numba import jit, typeof, TypingError
from numba import jit, literally, njit, typeof, TypingError
from numba.core import utils, types
from numba.tests.support import TestCase, MemoryLeakMixin
from numba.core.types.functions import _header_lead
Expand Down Expand Up @@ -207,6 +207,53 @@ def test_literal_slice_distinct(self):
self.assertNotEqual(sl1, sl2)
self.assertEqual(sl1, sl3)

def test_literal_slice_boxing(self):
Comment thread
esc marked this conversation as resolved.
# Tests that a literal slice can be
# returned from a JIT function.
@njit
def f(x):
return literally(x)

slices = (
slice(1, 4, 2),
slice(1, 2),
slice(1),
slice(None, 1, 1),
slice(1, None, 1),
slice(None, None, 1),
slice(None),
slice(None, None, None)
)
for sl in slices:
self.assertEqual(sl, f(sl))

Comment thread
esc marked this conversation as resolved.

def test_literal_slice_freevar(self):
# Tests passing a literal slice as a freevar
# in a closure.
z = slice(1, 2, 3)
@njit
def foo():
return z

self.assertEqual(z, foo())

def test_literal_slice_maxint(self):
# Tests that passing a slice with an integer
# that exceeds the maxint size throws a reasonable
# error message.
@njit()
def foo(z):
return literally(z)

maxval = int(2**63)
with self.assertRaises(ValueError) as e:
foo(slice(None, None, -maxval-1))
self.assertIn(
"Int value is too large",
str(e.exception)
)


if __name__ == '__main__':
unittest.main()