numba-cuda 0.17.0__py3-none-any.whl → 0.18.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of numba-cuda might be problematic. Click here for more details.

Files changed (64) hide show
  1. numba_cuda/VERSION +1 -1
  2. numba_cuda/numba/cuda/__init__.py +0 -8
  3. numba_cuda/numba/cuda/_internal/cuda_fp16.py +14225 -0
  4. numba_cuda/numba/cuda/api_util.py +6 -0
  5. numba_cuda/numba/cuda/cgutils.py +1291 -0
  6. numba_cuda/numba/cuda/codegen.py +32 -14
  7. numba_cuda/numba/cuda/compiler.py +113 -10
  8. numba_cuda/numba/cuda/core/caching.py +741 -0
  9. numba_cuda/numba/cuda/core/callconv.py +338 -0
  10. numba_cuda/numba/cuda/core/codegen.py +168 -0
  11. numba_cuda/numba/cuda/core/compiler.py +205 -0
  12. numba_cuda/numba/cuda/core/typed_passes.py +139 -0
  13. numba_cuda/numba/cuda/cudadecl.py +0 -268
  14. numba_cuda/numba/cuda/cudadrv/devicearray.py +3 -0
  15. numba_cuda/numba/cuda/cudadrv/driver.py +2 -1
  16. numba_cuda/numba/cuda/cudadrv/nvvm.py +1 -1
  17. numba_cuda/numba/cuda/cudaimpl.py +4 -178
  18. numba_cuda/numba/cuda/debuginfo.py +469 -3
  19. numba_cuda/numba/cuda/device_init.py +0 -1
  20. numba_cuda/numba/cuda/dispatcher.py +310 -11
  21. numba_cuda/numba/cuda/extending.py +2 -1
  22. numba_cuda/numba/cuda/fp16.py +348 -0
  23. numba_cuda/numba/cuda/intrinsics.py +1 -1
  24. numba_cuda/numba/cuda/libdeviceimpl.py +2 -1
  25. numba_cuda/numba/cuda/lowering.py +1833 -8
  26. numba_cuda/numba/cuda/mathimpl.py +2 -90
  27. numba_cuda/numba/cuda/nvvmutils.py +2 -1
  28. numba_cuda/numba/cuda/printimpl.py +2 -1
  29. numba_cuda/numba/cuda/serialize.py +264 -0
  30. numba_cuda/numba/cuda/simulator/__init__.py +2 -0
  31. numba_cuda/numba/cuda/simulator/dispatcher.py +7 -0
  32. numba_cuda/numba/cuda/stubs.py +0 -308
  33. numba_cuda/numba/cuda/target.py +13 -5
  34. numba_cuda/numba/cuda/testing.py +156 -5
  35. numba_cuda/numba/cuda/tests/complex_usecases.py +113 -0
  36. numba_cuda/numba/cuda/tests/core/serialize_usecases.py +110 -0
  37. numba_cuda/numba/cuda/tests/core/test_serialize.py +359 -0
  38. numba_cuda/numba/cuda/tests/cudadrv/test_context_stack.py +10 -4
  39. numba_cuda/numba/cuda/tests/cudadrv/test_cuda_ndarray.py +33 -0
  40. numba_cuda/numba/cuda/tests/cudadrv/test_runtime.py +2 -2
  41. numba_cuda/numba/cuda/tests/cudadrv/test_streams.py +1 -0
  42. numba_cuda/numba/cuda/tests/cudapy/extensions_usecases.py +1 -1
  43. numba_cuda/numba/cuda/tests/cudapy/test_caching.py +5 -10
  44. numba_cuda/numba/cuda/tests/cudapy/test_compiler.py +15 -0
  45. numba_cuda/numba/cuda/tests/cudapy/test_complex.py +1 -1
  46. numba_cuda/numba/cuda/tests/cudapy/test_debuginfo.py +381 -0
  47. numba_cuda/numba/cuda/tests/cudapy/test_enums.py +1 -1
  48. numba_cuda/numba/cuda/tests/cudapy/test_extending.py +1 -1
  49. numba_cuda/numba/cuda/tests/cudapy/test_inspect.py +108 -24
  50. numba_cuda/numba/cuda/tests/cudapy/test_intrinsics.py +37 -23
  51. numba_cuda/numba/cuda/tests/cudapy/test_operator.py +43 -27
  52. numba_cuda/numba/cuda/tests/cudapy/test_ufuncs.py +26 -9
  53. numba_cuda/numba/cuda/tests/cudapy/test_warning.py +27 -2
  54. numba_cuda/numba/cuda/tests/enum_usecases.py +56 -0
  55. numba_cuda/numba/cuda/tests/nocuda/test_library_lookup.py +1 -2
  56. numba_cuda/numba/cuda/tests/nocuda/test_nvvm.py +1 -1
  57. numba_cuda/numba/cuda/utils.py +785 -0
  58. numba_cuda/numba/cuda/vector_types.py +1 -1
  59. {numba_cuda-0.17.0.dist-info → numba_cuda-0.18.1.dist-info}/METADATA +18 -4
  60. {numba_cuda-0.17.0.dist-info → numba_cuda-0.18.1.dist-info}/RECORD +63 -50
  61. numba_cuda/numba/cuda/cpp_function_wrappers.cu +0 -46
  62. {numba_cuda-0.17.0.dist-info → numba_cuda-0.18.1.dist-info}/WHEEL +0 -0
  63. {numba_cuda-0.17.0.dist-info → numba_cuda-0.18.1.dist-info}/licenses/LICENSE +0 -0
  64. {numba_cuda-0.17.0.dist-info → numba_cuda-0.18.1.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,338 @@
1
+ from numba.core import types
2
+ from numba.cuda import cgutils
3
+ from collections import namedtuple
4
+
5
+ from llvmlite import ir
6
+
7
+ int32_t = ir.IntType(32)
8
+ int64_t = ir.IntType(64)
9
+ errcode_t = int32_t
10
+
11
+
12
+ Status = namedtuple(
13
+ "Status",
14
+ (
15
+ "code",
16
+ # If the function returned ok (a value or None)
17
+ "is_ok",
18
+ # If the function returned None
19
+ "is_none",
20
+ # If the function errored out (== not is_ok)
21
+ "is_error",
22
+ # If the generator exited with StopIteration
23
+ "is_stop_iteration",
24
+ # If the function errored with an already set exception
25
+ "is_python_exc",
26
+ # If the function errored with a user exception
27
+ "is_user_exc",
28
+ # The pointer to the exception info structure (for user
29
+ # exceptions)
30
+ "excinfoptr",
31
+ ),
32
+ )
33
+
34
+
35
+ def _const_int(code):
36
+ return ir.Constant(errcode_t, code)
37
+
38
+
39
+ RETCODE_OK = _const_int(0)
40
+ RETCODE_EXC = _const_int(-1)
41
+ RETCODE_NONE = _const_int(-2)
42
+ # StopIteration
43
+ RETCODE_STOPIT = _const_int(-3)
44
+
45
+ FIRST_USEREXC = 1
46
+
47
+ RETCODE_USEREXC = _const_int(FIRST_USEREXC)
48
+
49
+
50
+ class BaseCallConv(object):
51
+ def __init__(self, context):
52
+ self.context = context
53
+
54
+ def return_optional_value(self, builder, retty, valty, value):
55
+ if valty == types.none:
56
+ # Value is none
57
+ self.return_native_none(builder)
58
+
59
+ elif retty == valty:
60
+ # Value is an optional, need a runtime switch
61
+ optval = self.context.make_helper(builder, retty, value=value)
62
+
63
+ validbit = cgutils.as_bool_bit(builder, optval.valid)
64
+ with builder.if_then(validbit):
65
+ retval = self.context.get_return_value(
66
+ builder, retty.type, optval.data
67
+ )
68
+ self.return_value(builder, retval)
69
+
70
+ self.return_native_none(builder)
71
+
72
+ elif not isinstance(valty, types.Optional):
73
+ # Value is not an optional, need a cast
74
+ if valty != retty.type:
75
+ value = self.context.cast(
76
+ builder, value, fromty=valty, toty=retty.type
77
+ )
78
+ retval = self.context.get_return_value(builder, retty.type, value)
79
+ self.return_value(builder, retval)
80
+
81
+ else:
82
+ raise NotImplementedError(
83
+ "returning {0} for {1}".format(valty, retty)
84
+ )
85
+
86
+ def return_native_none(self, builder):
87
+ self._return_errcode_raw(builder, RETCODE_NONE)
88
+
89
+ def return_exc(self, builder):
90
+ self._return_errcode_raw(builder, RETCODE_EXC)
91
+
92
+ def return_stop_iteration(self, builder):
93
+ self._return_errcode_raw(builder, RETCODE_STOPIT)
94
+
95
+ def get_return_type(self, ty):
96
+ """
97
+ Get the actual type of the return argument for Numba type *ty*.
98
+ """
99
+ restype = self.context.data_model_manager[ty].get_return_type()
100
+ return restype.as_pointer()
101
+
102
+ def init_call_helper(self, builder):
103
+ """
104
+ Initialize and return a call helper object for the given builder.
105
+ """
106
+ ch = self._make_call_helper(builder)
107
+ builder.__call_helper = ch
108
+ return ch
109
+
110
+ def _get_call_helper(self, builder):
111
+ return builder.__call_helper
112
+
113
+ def unpack_exception(self, builder, pyapi, status):
114
+ return pyapi.unserialize(status.excinfoptr)
115
+
116
+ def raise_error(self, builder, pyapi, status):
117
+ """
118
+ Given a non-ok *status*, raise the corresponding Python exception.
119
+ """
120
+ bbend = builder.function.append_basic_block()
121
+
122
+ with builder.if_then(status.is_user_exc):
123
+ # Unserialize user exception.
124
+ # Make sure another error may not interfere.
125
+ pyapi.err_clear()
126
+ exc = self.unpack_exception(builder, pyapi, status)
127
+ with cgutils.if_likely(builder, cgutils.is_not_null(builder, exc)):
128
+ pyapi.raise_object(exc) # steals ref
129
+ builder.branch(bbend)
130
+
131
+ with builder.if_then(status.is_stop_iteration):
132
+ pyapi.err_set_none("PyExc_StopIteration")
133
+ builder.branch(bbend)
134
+
135
+ with builder.if_then(status.is_python_exc):
136
+ # Error already raised => nothing to do
137
+ builder.branch(bbend)
138
+
139
+ pyapi.err_set_string(
140
+ "PyExc_SystemError", "unknown error when calling native function"
141
+ )
142
+ builder.branch(bbend)
143
+
144
+ builder.position_at_end(bbend)
145
+
146
+ def decode_arguments(self, builder, argtypes, func):
147
+ """
148
+ Get the decoded (unpacked) Python arguments with *argtypes*
149
+ from LLVM function *func*. A tuple of LLVM values is returned.
150
+ """
151
+ raw_args = self.get_arguments(func)
152
+ arginfo = self._get_arg_packer(argtypes)
153
+ return arginfo.from_arguments(builder, raw_args)
154
+
155
+ def _get_arg_packer(self, argtypes):
156
+ """
157
+ Get an argument packer for the given argument types.
158
+ """
159
+ return self.context.get_arg_packer(argtypes)
160
+
161
+
162
+ class MinimalCallConv(BaseCallConv):
163
+ """
164
+ A minimal calling convention, suitable for e.g. GPU targets.
165
+ The implemented function signature is:
166
+
167
+ retcode_t (<Python return type>*, ... <Python arguments>)
168
+
169
+ The return code will be one of the RETCODE_* constants or a
170
+ function-specific user exception id (>= RETCODE_USEREXC).
171
+
172
+ Caller is responsible for allocating a slot for the return value
173
+ (passed as a pointer in the first argument).
174
+ """
175
+
176
+ def _make_call_helper(self, builder):
177
+ return _MinimalCallHelper()
178
+
179
+ def return_value(self, builder, retval):
180
+ retptr = builder.function.args[0]
181
+ assert retval.type == retptr.type.pointee, (
182
+ str(retval.type),
183
+ str(retptr.type.pointee),
184
+ )
185
+ builder.store(retval, retptr)
186
+ self._return_errcode_raw(builder, RETCODE_OK)
187
+
188
+ def return_user_exc(
189
+ self, builder, exc, exc_args=None, loc=None, func_name=None
190
+ ):
191
+ if exc is not None and not issubclass(exc, BaseException):
192
+ raise TypeError(
193
+ "exc should be None or exception class, got %r" % (exc,)
194
+ )
195
+ if exc_args is not None and not isinstance(exc_args, tuple):
196
+ raise TypeError(
197
+ "exc_args should be None or tuple, got %r" % (exc_args,)
198
+ )
199
+
200
+ # Build excinfo struct
201
+ if loc is not None:
202
+ fname = loc._raw_function_name()
203
+ if fname is None:
204
+ # could be exec(<string>) or REPL, try func_name
205
+ fname = func_name
206
+
207
+ locinfo = (fname, loc.filename, loc.line)
208
+ if None in locinfo:
209
+ locinfo = None
210
+ else:
211
+ locinfo = None
212
+
213
+ call_helper = self._get_call_helper(builder)
214
+ exc_id = call_helper._add_exception(exc, exc_args, locinfo)
215
+ self._return_errcode_raw(builder, _const_int(exc_id))
216
+
217
+ def return_status_propagate(self, builder, status):
218
+ self._return_errcode_raw(builder, status.code)
219
+
220
+ def _return_errcode_raw(self, builder, code):
221
+ if isinstance(code, int):
222
+ code = _const_int(code)
223
+ builder.ret(code)
224
+
225
+ def _get_return_status(self, builder, code):
226
+ """
227
+ Given a return *code*, get a Status instance.
228
+ """
229
+ norm = builder.icmp_signed("==", code, RETCODE_OK)
230
+ none = builder.icmp_signed("==", code, RETCODE_NONE)
231
+ ok = builder.or_(norm, none)
232
+ err = builder.not_(ok)
233
+ exc = builder.icmp_signed("==", code, RETCODE_EXC)
234
+ is_stop_iteration = builder.icmp_signed("==", code, RETCODE_STOPIT)
235
+ is_user_exc = builder.icmp_signed(">=", code, RETCODE_USEREXC)
236
+
237
+ status = Status(
238
+ code=code,
239
+ is_ok=ok,
240
+ is_error=err,
241
+ is_python_exc=exc,
242
+ is_none=none,
243
+ is_user_exc=is_user_exc,
244
+ is_stop_iteration=is_stop_iteration,
245
+ excinfoptr=None,
246
+ )
247
+ return status
248
+
249
+ def get_function_type(self, restype, argtypes):
250
+ """
251
+ Get the implemented Function type for *restype* and *argtypes*.
252
+ """
253
+ arginfo = self._get_arg_packer(argtypes)
254
+ argtypes = list(arginfo.argument_types)
255
+ resptr = self.get_return_type(restype)
256
+ fnty = ir.FunctionType(errcode_t, [resptr] + argtypes)
257
+ return fnty
258
+
259
+ def decorate_function(self, fn, args, fe_argtypes, noalias=False):
260
+ """
261
+ Set names and attributes of function arguments.
262
+ """
263
+ assert not noalias
264
+ arginfo = self._get_arg_packer(fe_argtypes)
265
+ arginfo.assign_names(self.get_arguments(fn), ["arg." + a for a in args])
266
+ fn.args[0].name = ".ret"
267
+
268
+ def get_arguments(self, func):
269
+ """
270
+ Get the Python-level arguments of LLVM *func*.
271
+ """
272
+ return func.args[1:]
273
+
274
+ def call_function(self, builder, callee, resty, argtys, args):
275
+ """
276
+ Call the Numba-compiled *callee*.
277
+ """
278
+ retty = callee.args[0].type.pointee
279
+ retvaltmp = cgutils.alloca_once(builder, retty)
280
+ # initialize return value
281
+ builder.store(cgutils.get_null_value(retty), retvaltmp)
282
+
283
+ arginfo = self._get_arg_packer(argtys)
284
+ args = arginfo.as_arguments(builder, args)
285
+ realargs = [retvaltmp] + list(args)
286
+ code = builder.call(callee, realargs)
287
+ status = self._get_return_status(builder, code)
288
+ retval = builder.load(retvaltmp)
289
+ out = self.context.get_returned_value(builder, resty, retval)
290
+ return status, out
291
+
292
+
293
+ class _MinimalCallHelper(object):
294
+ """
295
+ A call helper object for the "minimal" calling convention.
296
+ User exceptions are represented as integer codes and stored in
297
+ a mapping for retrieval from the caller.
298
+ """
299
+
300
+ def __init__(self):
301
+ self.exceptions = {}
302
+
303
+ def _add_exception(self, exc, exc_args, locinfo):
304
+ """
305
+ Add a new user exception to this helper. Returns an integer that can be
306
+ used to refer to the added exception in future.
307
+
308
+ Parameters
309
+ ----------
310
+ exc :
311
+ exception type
312
+ exc_args : None or tuple
313
+ exception args
314
+ locinfo : tuple
315
+ location information
316
+ """
317
+ exc_id = len(self.exceptions) + FIRST_USEREXC
318
+ self.exceptions[exc_id] = exc, exc_args, locinfo
319
+ return exc_id
320
+
321
+ def get_exception(self, exc_id):
322
+ """
323
+ Get information about a user exception. Returns a tuple of
324
+ (exception type, exception args, location information).
325
+
326
+ Parameters
327
+ ----------
328
+ id : integer
329
+ The ID of the exception to look up
330
+ """
331
+ try:
332
+ return self.exceptions[exc_id]
333
+ except KeyError:
334
+ msg = "unknown error %d in native function" % exc_id
335
+ exc = SystemError
336
+ exc_args = (msg,)
337
+ locinfo = None
338
+ return exc, exc_args, locinfo
@@ -0,0 +1,168 @@
1
+ from abc import abstractmethod, ABCMeta
2
+ from numba.misc.llvm_pass_timings import PassTimingsCollection
3
+
4
+
5
+ class CodeLibrary(metaclass=ABCMeta):
6
+ """
7
+ An interface for bundling LLVM code together and compiling it.
8
+ It is tied to a *codegen* instance (e.g. JITCUDACodegen) that will
9
+ determine how the LLVM code is transformed and linked together.
10
+ """
11
+
12
+ _finalized = False
13
+ _object_caching_enabled = False
14
+ _disable_inspection = False
15
+
16
+ def __init__(self, codegen: "Codegen", name: str):
17
+ self._codegen = codegen
18
+ self._name = name
19
+ ptc_name = f"{self.__class__.__name__}({self._name!r})"
20
+ self._recorded_timings = PassTimingsCollection(ptc_name)
21
+ # Track names of the dynamic globals
22
+ self._dynamic_globals = []
23
+
24
+ @property
25
+ def has_dynamic_globals(self):
26
+ self._ensure_finalized()
27
+ return len(self._dynamic_globals) > 0
28
+
29
+ @property
30
+ def recorded_timings(self):
31
+ return self._recorded_timings
32
+
33
+ @property
34
+ def codegen(self):
35
+ """
36
+ The codegen object owning this library.
37
+ """
38
+ return self._codegen
39
+
40
+ @property
41
+ def name(self):
42
+ return self._name
43
+
44
+ def __repr__(self):
45
+ return "<Library %r at 0x%x>" % (self.name, id(self))
46
+
47
+ def _raise_if_finalized(self):
48
+ if self._finalized:
49
+ raise RuntimeError(
50
+ "operation impossible on finalized object %r" % (self,)
51
+ )
52
+
53
+ def _ensure_finalized(self):
54
+ if not self._finalized:
55
+ self.finalize()
56
+
57
+ def create_ir_module(self, name):
58
+ """
59
+ Create an LLVM IR module for use by this library.
60
+ """
61
+ self._raise_if_finalized()
62
+ ir_module = self._codegen._create_empty_module(name)
63
+ return ir_module
64
+
65
+ @abstractmethod
66
+ def add_linking_library(self, library):
67
+ """
68
+ Add a library for linking into this library, without losing
69
+ the original library.
70
+ """
71
+
72
+ @abstractmethod
73
+ def add_ir_module(self, ir_module):
74
+ """
75
+ Add an LLVM IR module's contents to this library.
76
+ """
77
+
78
+ @abstractmethod
79
+ def finalize(self):
80
+ """
81
+ Finalize the library. After this call, nothing can be added anymore.
82
+ Finalization involves various stages of code optimization and
83
+ linking.
84
+ """
85
+
86
+ @abstractmethod
87
+ def get_function(self, name):
88
+ """
89
+ Return the function named ``name``.
90
+ """
91
+
92
+ @abstractmethod
93
+ def get_llvm_str(self):
94
+ """
95
+ Get the human-readable form of the LLVM module.
96
+ """
97
+
98
+ @abstractmethod
99
+ def get_asm_str(self):
100
+ """
101
+ Get the human-readable assembly.
102
+ """
103
+
104
+ #
105
+ # Object cache hooks and serialization
106
+ #
107
+
108
+ def enable_object_caching(self):
109
+ self._object_caching_enabled = True
110
+ self._compiled_object = None
111
+ self._compiled = False
112
+
113
+ def _get_compiled_object(self):
114
+ if not self._object_caching_enabled:
115
+ raise ValueError("object caching not enabled in %s" % (self,))
116
+ if self._compiled_object is None:
117
+ raise RuntimeError("no compiled object yet for %s" % (self,))
118
+ return self._compiled_object
119
+
120
+ def _set_compiled_object(self, value):
121
+ if not self._object_caching_enabled:
122
+ raise ValueError("object caching not enabled in %s" % (self,))
123
+ if self._compiled:
124
+ raise ValueError("library already compiled: %s" % (self,))
125
+ self._compiled_object = value
126
+ self._disable_inspection = True
127
+
128
+
129
+ class Codegen(metaclass=ABCMeta):
130
+ """
131
+ Base Codegen class. It is expected that subclasses set the class attribute
132
+ ``_library_class``, indicating the CodeLibrary class for the target.
133
+
134
+ Subclasses should also initialize:
135
+
136
+ ``self._data_layout``: the data layout for the target.
137
+ ``self._target_data``: the binding layer ``TargetData`` for the target.
138
+ """
139
+
140
+ @abstractmethod
141
+ def _create_empty_module(self, name):
142
+ """
143
+ Create a new empty module suitable for the target.
144
+ """
145
+
146
+ @abstractmethod
147
+ def _add_module(self, module):
148
+ """
149
+ Add a module to the execution engine. Ownership of the module is
150
+ transferred to the engine.
151
+ """
152
+
153
+ @property
154
+ def target_data(self):
155
+ """
156
+ The LLVM "target data" object for this codegen instance.
157
+ """
158
+ return self._target_data
159
+
160
+ def create_library(self, name, **kwargs):
161
+ """
162
+ Create a :class:`CodeLibrary` object for use with this codegen
163
+ instance.
164
+ """
165
+ return self._library_class(self, name, **kwargs)
166
+
167
+ def unserialize_library(self, serialized):
168
+ return self._library_class._unserialize(self, serialized)
@@ -0,0 +1,205 @@
1
+ from numba.core.tracing import event
2
+
3
+ from numba.core import callconv, bytecode, config, errors
4
+ from numba.core.errors import CompilerError
5
+ from numba.parfors.parfor import ParforDiagnostics
6
+
7
+ from numba.core.untyped_passes import ExtractByteCode, FixupArgs
8
+ from numba.core.targetconfig import ConfigStack
9
+
10
+
11
+ class _CompileStatus(object):
12
+ """
13
+ Describes the state of compilation. Used like a C record.
14
+ """
15
+
16
+ __slots__ = ["fail_reason", "can_fallback"]
17
+
18
+ def __init__(self, can_fallback):
19
+ self.fail_reason = None
20
+ self.can_fallback = can_fallback
21
+
22
+ def __repr__(self):
23
+ vals = []
24
+ for k in self.__slots__:
25
+ vals.append("{k}={v}".format(k=k, v=getattr(self, k)))
26
+ return ", ".join(vals)
27
+
28
+
29
+ class StateDict(dict):
30
+ """
31
+ A dictionary that has an overloaded getattr and setattr to permit getting
32
+ and setting key/values through the use of attributes.
33
+ """
34
+
35
+ def __getattr__(self, attr):
36
+ try:
37
+ return self[attr]
38
+ except KeyError:
39
+ raise AttributeError(attr)
40
+
41
+ def __setattr__(self, attr, value):
42
+ self[attr] = value
43
+
44
+
45
+ class _EarlyPipelineCompletion(Exception):
46
+ """
47
+ Raised to indicate that a pipeline has completed early
48
+ """
49
+
50
+ def __init__(self, result):
51
+ self.result = result
52
+
53
+
54
+ def _make_subtarget(targetctx, flags):
55
+ """
56
+ Make a new target context from the given target context and flags.
57
+ """
58
+ subtargetoptions = {}
59
+ if flags.debuginfo:
60
+ subtargetoptions["enable_debuginfo"] = True
61
+ if flags.boundscheck:
62
+ subtargetoptions["enable_boundscheck"] = True
63
+ if flags.nrt:
64
+ subtargetoptions["enable_nrt"] = True
65
+ if flags.auto_parallel:
66
+ subtargetoptions["auto_parallel"] = flags.auto_parallel
67
+ if flags.fastmath:
68
+ subtargetoptions["fastmath"] = flags.fastmath
69
+ error_model = callconv.create_error_model(flags.error_model, targetctx)
70
+ subtargetoptions["error_model"] = error_model
71
+
72
+ return targetctx.subtarget(**subtargetoptions)
73
+
74
+
75
+ class CompilerBase(object):
76
+ """
77
+ Stores and manages states for the compiler
78
+ """
79
+
80
+ def __init__(
81
+ self, typingctx, targetctx, library, args, return_type, flags, locals
82
+ ):
83
+ # Make sure the environment is reloaded
84
+ config.reload_config()
85
+ typingctx.refresh()
86
+ targetctx.refresh()
87
+
88
+ self.state = StateDict()
89
+
90
+ self.state.typingctx = typingctx
91
+ self.state.targetctx = _make_subtarget(targetctx, flags)
92
+ self.state.library = library
93
+ self.state.args = args
94
+ self.state.return_type = return_type
95
+ self.state.flags = flags
96
+ self.state.locals = locals
97
+
98
+ # Results of various steps of the compilation pipeline
99
+ self.state.bc = None
100
+ self.state.func_id = None
101
+ self.state.func_ir = None
102
+ self.state.lifted = None
103
+ self.state.lifted_from = None
104
+ self.state.typemap = None
105
+ self.state.calltypes = None
106
+ self.state.type_annotation = None
107
+ # holds arbitrary inter-pipeline stage meta data
108
+ self.state.metadata = {}
109
+ self.state.reload_init = []
110
+ # hold this for e.g. with_lifting, null out on exit
111
+ self.state.pipeline = self
112
+
113
+ # parfor diagnostics info, add to metadata
114
+ self.state.parfor_diagnostics = ParforDiagnostics()
115
+ self.state.metadata["parfor_diagnostics"] = (
116
+ self.state.parfor_diagnostics
117
+ )
118
+ self.state.metadata["parfors"] = {}
119
+
120
+ self.state.status = _CompileStatus(
121
+ can_fallback=self.state.flags.enable_pyobject
122
+ )
123
+
124
+ def compile_extra(self, func):
125
+ self.state.func_id = bytecode.FunctionIdentity.from_function(func)
126
+ ExtractByteCode().run_pass(self.state)
127
+
128
+ self.state.lifted = ()
129
+ self.state.lifted_from = None
130
+ return self._compile_bytecode()
131
+
132
+ def compile_ir(self, func_ir, lifted=(), lifted_from=None):
133
+ self.state.func_id = func_ir.func_id
134
+ self.state.lifted = lifted
135
+ self.state.lifted_from = lifted_from
136
+ self.state.func_ir = func_ir
137
+ self.state.nargs = self.state.func_ir.arg_count
138
+
139
+ FixupArgs().run_pass(self.state)
140
+ return self._compile_ir()
141
+
142
+ def define_pipelines(self):
143
+ """Child classes override this to customize the pipelines in use."""
144
+ raise NotImplementedError()
145
+
146
+ def _compile_core(self):
147
+ """
148
+ Populate and run compiler pipeline
149
+ """
150
+ with ConfigStack().enter(self.state.flags.copy()):
151
+ pms = self.define_pipelines()
152
+ for pm in pms:
153
+ pipeline_name = pm.pipeline_name
154
+ func_name = "%s.%s" % (
155
+ self.state.func_id.modname,
156
+ self.state.func_id.func_qualname,
157
+ )
158
+
159
+ event("Pipeline: %s for %s" % (pipeline_name, func_name))
160
+ self.state.metadata["pipeline_times"] = {
161
+ pipeline_name: pm.exec_times
162
+ }
163
+ is_final_pipeline = pm == pms[-1]
164
+ res = None
165
+ try:
166
+ pm.run(self.state)
167
+ if self.state.cr is not None:
168
+ break
169
+ except _EarlyPipelineCompletion as e:
170
+ res = e.result
171
+ break
172
+ except Exception as e:
173
+ if not isinstance(e, errors.NumbaError):
174
+ raise e
175
+ self.state.status.fail_reason = e
176
+ if is_final_pipeline:
177
+ raise e
178
+ else:
179
+ raise CompilerError("All available pipelines exhausted")
180
+
181
+ # Pipeline is done, remove self reference to release refs to user
182
+ # code
183
+ self.state.pipeline = None
184
+
185
+ # organise a return
186
+ if res is not None:
187
+ # Early pipeline completion
188
+ return res
189
+ else:
190
+ assert self.state.cr is not None
191
+ return self.state.cr
192
+
193
+ def _compile_bytecode(self):
194
+ """
195
+ Populate and run pipeline for bytecode input
196
+ """
197
+ assert self.state.func_ir is None
198
+ return self._compile_core()
199
+
200
+ def _compile_ir(self):
201
+ """
202
+ Populate and run pipeline for IR input
203
+ """
204
+ assert self.state.func_ir is not None
205
+ return self._compile_core()