Repository: numba/numba

Issue:
Numba/CFFI regression
I discovered what looks like a regression when calling functions via cffi in numba. I've put a minimal reproducible example in the following repository:

https://github.com/synapticarbors/numba_cffi_bug

After building the cffi module, and running `python testlib.py`, I get the following error with numba 0.30.0 and 0.30.1 on OSX but it runs without error on numba 0.29.0 and earlier. I'm using cffi 1.9.1. 

```
$ python testlib.py
Traceback (most recent call last):
  File "testlib.py", line 53, in <module>
    run()
  File "testlib.py", line 48, in run
    print(_run())
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/numba/dispatcher.py", line 286, in _compile_for_args
    return self.compile(tuple(argtypes))
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/numba/dispatcher.py", line 532, in compile
    cres = self._compiler.compile(args, return_type)
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/numba/dispatcher.py", line 81, in compile
    flags=flags, locals=self.locals)
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/numba/compiler.py", line 693, in compile_extra
    return pipeline.compile_extra(func)
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/numba/compiler.py", line 350, in compile_extra
    return self._compile_bytecode()
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/numba/compiler.py", line 658, in _compile_bytecode
    return self._compile_core()
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/numba/compiler.py", line 645, in _compile_core
    res = pm.run(self.status)
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/numba/compiler.py", line 236, in run
    raise patched_exception
RuntimeError: Caused By:
Traceback (most recent call last):
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/numba/compiler.py", line 228, in run
    stage()
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/numba/compiler.py", line 583, in stage_nopython_backend
    self._backend(lowerfn, objectmode=False)
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/numba/compiler.py", line 538, in _backend
    lowered = lowerfn()
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/numba/compiler.py", line 525, in backend_nopython_mode
    self.flags)
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/numba/compiler.py", line 824, in native_lowering_stage
    cfunc = targetctx.get_executable(library, fndesc, env)
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/numba/targets/cpu.py", line 156, in get_executable
    baseptr = library.get_pointer_to_function(fndesc.llvm_func_name)
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/numba/targets/codegen.py", line 403, in get_pointer_to_function
    self._ensure_finalized()
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/numba/targets/codegen.py", line 75, in _ensure_finalized
    self.finalize()
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/numba/targets/codegen.py", line 192, in finalize
    library._get_module_for_linking(), preserve=True)
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/llvmlite/binding/module.py", line 147, in link_in
    link_modules(self, other)
  File "/Users/zzz/anaconda/envs/nbtest/lib/python2.7/site-packages/llvmlite/binding/linker.py", line 12, in link_modules
    raise RuntimeError(str(outerr))
RuntimeError: Linking globals named 'numba.dynamic.globals': symbol multiply defined!

Failed at nopython (nopython mode backend)
Linking globals named 'numba.dynamic.globals': symbol multiply defined!
```





Discussion:
Thanks for the bug report.  I am able to replicate the bug with your sample code. 

Resolving patch:
diff --git a/numba/targets/base.py b/numba/targets/base.py
--- a/numba/targets/base.py
+++ b/numba/targets/base.py
@@ -978,7 +978,12 @@ def add_dynamic_addr(self, builder, intaddr, info):
         mod = builder.module
         llvoidptr = self.get_value_type(types.voidptr)
         addr = self.get_constant(types.uintp, intaddr).inttoptr(llvoidptr)
-        gv = mod.add_global_variable(llvoidptr, name='numba.dynamic.globals')
+        # Use a unique name by embedding the address value
+        symname = 'numba.dynamic.globals.{:x}'.format(intaddr)
+        gv = mod.add_global_variable(llvoidptr, name=symname)
+        # Use linkonce linkage to allow merging with other GV of the same name.
+        # And, avoid optimization from assuming its value.
+        gv.linkage = 'linkonce'
         gv.initializer = addr
         return builder.load(gv)
 


Test patch:
diff --git a/numba/tests/test_cffi.py b/numba/tests/test_cffi.py
--- a/numba/tests/test_cffi.py
+++ b/numba/tests/test_cffi.py
@@ -117,7 +117,6 @@ def test_from_buffer_struct(self):
         imag_cfunc(x, y)
         np.testing.assert_equal(x.imag, y)
 
-
     @unittest.skipIf(sys.version_info < (3,),
                      "buffer protocol on array.array needs Python 3+")
     def test_from_buffer_pyarray(self):
@@ -138,6 +137,28 @@ def test_from_buffer_error(self):
         self.assertIn("from_buffer() unsupported on non-contiguous buffers",
                       str(raises.exception))
 
+    def test_indirect_multiple_use(self):
+        """
+        Issue #2263
+
+        Linkage error due to multiple definition of global tracking symbol.
+        """
+        my_sin = mod.cffi_sin
+
+        # Use two jit functions that references `my_sin` to ensure multiple
+        # modules
+        @jit(nopython=True)
+        def inner(x):
+            return my_sin(x)
+
+        @jit(nopython=True)
+        def foo(x):
+            return inner(x) + my_sin(x + 1)
+
+        # Error occurs when foo is being compiled
+        x = 1.123
+        self.assertEqual(foo(x), my_sin(x) + my_sin(x + 1))
+
 
 if __name__ == '__main__':
     unittest.main()