Repository: numba/numba

Issue:
floordiv segfault in cuda
Floordiv cause segfault inside nvvm due use of LLVM instrinsic `llvm.floor.f64` which is unsupported by NVVM.
In addition, it generates an internal helper function with name starting with a dot (".").  NVVM forbids symbol names with a dot.

floordiv segfault in cuda
Floordiv cause segfault inside nvvm due use of LLVM instrinsic `llvm.floor.f64` which is unsupported by NVVM.
In addition, it generates an internal helper function with name starting with a dot (".").  NVVM forbids symbol names with a dot.



Discussion:

Resolving patch:
diff --git a/numba/targets/base.py b/numba/targets/base.py
--- a/numba/targets/base.py
+++ b/numba/targets/base.py
@@ -13,7 +13,7 @@
 from llvmlite.llvmpy.core import Type, Constant, LLVMException
 import llvmlite.binding as ll
 
-from numba import types, utils, cgutils, typing
+from numba import types, utils, cgutils, typing, funcdesc
 from numba import _dynfunc, _helperlib
 from numba.pythonapi import PythonAPI
 from . import arrayobj, builtins, imputils
@@ -187,9 +187,6 @@ class BaseContext(object):
     # Causes exception to be raised if the record members are not aligned.
     strict_alignment = False
 
-    # Use default mangler (no specific requirement)
-    mangler = None
-
     # Force powi implementation as math.pow call
     implement_powi_as_math_call = False
     implement_pow_as_math_call = False
@@ -260,6 +257,12 @@ def load_additional_registries(self):
         Load target-specific registries.  Can be overriden by subclasses.
         """
 
+    def mangler(self, name, types):
+        """
+        Perform name mangling.
+        """
+        return funcdesc.default_mangler(name, types)
+
     def get_arg_packer(self, fe_args):
         return datamodel.ArgPacker(self.data_model_manager, fe_args)
 
diff --git a/numba/targets/numbers.py b/numba/targets/numbers.py
--- a/numba/targets/numbers.py
+++ b/numba/targets/numbers.py
@@ -571,7 +571,7 @@ def real_divmod(context, builder, x, y):
     floatty = x.type
 
     module = builder.module
-    fname = ".numba.python.rem.%s" % x.type
+    fname = context.mangler(".numba.python.rem", [x.type])
     fnty = Type.function(floatty, (floatty, floatty, Type.pointer(floatty)))
     fn = module.get_or_insert_function(fnty, fname)
 
@@ -674,9 +674,12 @@ def real_divmod_func_body(context, builder, vx, wx):
     div_istrue = builder.fcmp(lc.FCMP_ONE, div, ZERO)
 
     with builder.if_then(div_istrue):
-        module = builder.module
-        floorfn = lc.Function.intrinsic(module, lc.INTR_FLOOR, [wx.type])
-        floordiv = builder.call(floorfn, [div])
+        realtypemap = {'float': types.float32,
+                       'double': types.float64}
+        realtype = realtypemap[str(wx.type)]
+        floorfn = context.get_function(math.floor,
+                                       typing.signature(realtype, realtype))
+        floordiv = floorfn(builder, [div])
         floordivdiff = builder.fsub(div, floordiv)
         floordivincr = builder.fadd(floordiv, ONE)
         HALF = Constant.real(wx.type, 0.5)


Test patch:
diff --git a/numba/cuda/tests/cudapy/test_operator.py b/numba/cuda/tests/cudapy/test_operator.py
--- a/numba/cuda/tests/cudapy/test_operator.py
+++ b/numba/cuda/tests/cudapy/test_operator.py
@@ -35,6 +35,9 @@ def test_mul(self):
     def test_truediv(self):
         self.operator_template(operator.truediv)
 
+    def test_floordiv(self):
+        self.operator_template(operator.floordiv)
+
 
 if __name__ == '__main__':
     unittest.main()