Beispiel #1
0
    def visit_ArrayNewNode(self, node):
        if self.nopython:
            raise error.NumbaError(
                node, "Cannot yet allocate new array in nopython context")

        PyArray_Type = nodes.ObjectInjectNode(np.ndarray)
        descr = nodes.ObjectInjectNode(node.type.dtype.get_dtype()).cloneable
        ndim = nodes.const(node.type.ndim, int_)
        flags = nodes.const(0, int_)
        args = [PyArray_Type, descr.clone, ndim,
                node.shape, node.strides, node.data, flags]

        incref_descr = nodes.IncrefNode(descr)
        incref_base = None
        setbase = None

        if node.base is None:
            args.append(nodes.NULL_obj)
        else:
            base = nodes.CloneableNode(node.base)
            incref_base = nodes.IncrefNode(base)
            args.append(base.clone)

        array = nodes.PyArray_NewFromDescr(args)
        array = nodes.ObjectTempNode(array).cloneable
        body = [incref_descr, incref_base, array, setbase]

        if node.base is not None:
            body.append(nodes.PyArray_SetBaseObject([array.clone, base.clone]))

        # TODO: PyArray_UpdateFlags()
        result = nodes.ExpressionNode(filter(None, body), array.clone)
        return self.visit(result)
Beispiel #2
0
 def str_to_int(self, dst_type, node):
     # TODO: int <-> string conversions are explicit, this should not
     # TODO: be a coercion
     if self.nopython:
         node = nodes.CoercionNode(
             function_util.external_call(
                 self.context,
                 self.llvm_module,
                 ('atol' if dst_type.is_int else 'atof'),
                 args=[node.node]),
             dst_type, name=node.name, )
     else:
         if dst_type.is_int:
             cvtobj = function_util.external_call(
                 self.context,
                 self.llvm_module,
                 'PyInt_FromString' if not PY3 else 'PyLong_FromString',
                 args=[node.node, nodes.NULL,
                       nodes.const(10, int_)])
         else:
             cvtobj = function_util.external_call(
                 self.context,
                 self.llvm_module,
                 'PyFloat_FromString',
                 args=[node.node,
                       nodes.const(0, Py_ssize_t)])
         node = nodes.CoerceToNative(nodes.ObjectTempNode(cvtobj),
                                     dst_type, name=node.name)
     result = self.visit(node)
     return result
Beispiel #3
0
 def _c_string_slice(self, node):
     ret_val = node
     logger.debug(node.slice)
     node_slice = node.slice
     if isinstance(node_slice, nodes.ObjectInjectNode):
         node_slice = node.slice.object
         lower, upper, step = (
             value if value is None else nodes.const(value, size_t)
             for value in (node_slice.start, node_slice.stop,
                           node_slice.step))
     else:
         lower, upper, step = (node_slice.lower, node_slice.upper,
                               node_slice.step)
     if step is None:
         node_value = self.visit(node.value)
         if lower is None:
             lower = nodes.const(0, size_t)
         if upper is None:
             ret_val = nodes.LLMacroNode(
                 macros.c_string_slice_1.__signature__,
                 macros.c_string_slice_1, self.visit(node.value),
                 self.visit(lower))
         else:
             ret_val = nodes.LLMacroNode(
                 macros.c_string_slice_2.__signature__,
                 macros.c_string_slice_2, self.visit(node.value),
                 self.visit(lower), self.visit(upper))
         logger.debug(ret_val)
     else:
         raise NotImplementedError('String slices where step != None.')
     return ret_val
Beispiel #4
0
 def str_to_int(self, dst_type, node):
     # TODO: int <-> string conversions are explicit, this should not
     # TODO: be a coercion
     if self.nopython:
         node = nodes.CoercionNode(
             function_util.external_call(
                 self.context,
                 self.llvm_module,
                 ('atol' if dst_type.is_int else 'atof'),
                 args=[node.node]),
             dst_type, name=node.name, )
     else:
         if dst_type.is_int:
             cvtobj = function_util.external_call(
                 self.context,
                 self.llvm_module,
                 'PyInt_FromString' if not PY3 else 'PyLong_FromString',
                 args=[node.node, nodes.NULL,
                       nodes.const(10, int_)])
         else:
             cvtobj = function_util.external_call(
                 self.context,
                 self.llvm_module,
                 'PyFloat_FromString',
                 args=[node.node,
                       nodes.const(0, Py_ssize_t)])
         node = nodes.CoerceToNative(nodes.ObjectTempNode(cvtobj),
                                     dst_type, name=node.name)
     result = self.visit(node)
     return result
Beispiel #5
0
    def visit_ArrayNewNode(self, node):
        if self.nopython:
            # Give the codegen (subclass) a chance to handle this
            self.generic_visit(node)
            return node

        PyArray_Type = nodes.ObjectInjectNode(np.ndarray)
        descr = nodes.ObjectInjectNode(node.type.dtype.get_dtype()).cloneable
        ndim = nodes.const(node.type.ndim, int_)
        flags = nodes.const(0, int_)
        args = [PyArray_Type, descr.clone, ndim,
                node.shape, node.strides, node.data, flags]

        incref_descr = nodes.IncrefNode(descr)
        incref_base = None
        setbase = None

        if node.base is None:
            args.append(nodes.NULL_obj)
        else:
            base = nodes.CloneableNode(node.base)
            incref_base = nodes.IncrefNode(base)
            args.append(base.clone)

        array = nodes.PyArray_NewFromDescr(args).cloneable
        body = [incref_descr, incref_base, array, setbase]

        if node.base is not None:
            body.append(nodes.PyArray_SetBaseObject([array.clone, base.clone]))

        # TODO: PyArray_UpdateFlags()
        result = nodes.ExpressionNode(filter(None, body), array.clone)
        return self.visit(result)
Beispiel #6
0
    def visit_ArrayNewNode(self, node):
        if self.nopython:
            raise error.NumbaError(
                node, "Cannot yet allocate new array in nopython context")

        PyArray_Type = nodes.ObjectInjectNode(np.ndarray)
        descr = nodes.ObjectInjectNode(node.type.dtype.get_dtype()).cloneable
        ndim = nodes.const(node.type.ndim, int_)
        flags = nodes.const(0, int_)
        args = [PyArray_Type, descr.clone, ndim,
                node.shape, node.strides, node.data, flags]

        incref_descr = nodes.IncrefNode(descr)
        incref_base = None
        setbase = None

        if node.base is None:
            args.append(nodes.NULL_obj)
        else:
            base = nodes.CloneableNode(node.base)
            incref_base = nodes.IncrefNode(base)
            args.append(base.clone)

        array = nodes.PyArray_NewFromDescr(args)
        array = nodes.ObjectTempNode(array).cloneable
        body = [incref_descr, incref_base, array, setbase]

        if node.base is not None:
            body.append(nodes.PyArray_SetBaseObject([array.clone, base.clone]))

        # TODO: PyArray_UpdateFlags()
        result = nodes.ExpressionNode(filter(None, body), array.clone)
        return self.visit(result)
Beispiel #7
0
 def _c_string_slice(self, node):
     ret_val = node
     logger.debug(node.slice)
     node_slice = node.slice
     if isinstance(node_slice, nodes.ObjectInjectNode):
         node_slice = node.slice.object
         lower, upper, step = (value if value is None else nodes.const(
             value, size_t) for value in (node_slice.start, node_slice.stop,
                                          node_slice.step))
     else:
         lower, upper, step = (node_slice.lower, node_slice.upper,
                               node_slice.step)
     if step is None:
         node_value = self.visit(node.value)
         if lower is None:
             lower = nodes.const(0, size_t)
         if upper is None:
             ret_val = nodes.LLMacroNode(
                 macros.c_string_slice_1.__signature__,
                 macros.c_string_slice_1, self.visit(node.value),
                 self.visit(lower))
         else:
             ret_val = nodes.LLMacroNode(
                 macros.c_string_slice_2.__signature__,
                 macros.c_string_slice_2, self.visit(node.value),
                 self.visit(lower), self.visit(upper))
         logger.debug(ret_val)
     else:
         raise NotImplementedError('String slices where step != None.')
     return ret_val
Beispiel #8
0
    def create_numba_function(self, node, translator):
        closure_scope = self.ast.cur_scope

        if closure_scope is None:
            closure_scope = nodes.NULL
            scope_type = void.pointer()
        else:
            assert node.func_def.args.args[0].variable.type
            scope_type = closure_scope.type

        node.wrapper_func, node.wrapper_lfunc, methoddef = (
                    translator.build_wrapper_function(get_lfunc=True))

        # Keep methoddef alive
        # assert methoddef in node.py_func.live_objects
        modname = self.module_name
        self.keep_alive(modname)

        # Create function signature with closure scope at runtime
        create_numbafunc_signature = node.type(
            void.pointer(),     # PyMethodDef *ml
            object_,            # PyObject *module
            void.pointer(),     # PyObject *code
            scope_type,         # PyObject *closure
            void.pointer(),     # void *native_func
            object_,            # PyObject *native_signature
            object_,            # PyObject *keep_alive
        )

        # Create function with closure scope at runtime
        create_numbafunc = nodes.ptrfromint(
                        extension_types.NumbaFunction_NewEx_pointer,
                        create_numbafunc_signature.pointer())

        methoddef_p = ctypes.cast(ctypes.byref(methoddef),
                                  ctypes.c_void_p).value

        args = [
            nodes.const(methoddef_p, void.pointer()),
            nodes.const(modname, object_),
            nodes.NULL,
            closure_scope,
            nodes.const(node.lfunc_pointer, void.pointer()),
            nodes.const(node.type.signature, object_),
            nodes.NULL, # nodes.const(node.py_func, object_),
        ]

        func_call = nodes.NativeFunctionCallNode(
                            signature=create_numbafunc_signature,
                            function_node=create_numbafunc,
                            args=args)

        result = func_call

        #stats = [nodes.inject_print(nodes.const("calling...", c_string_type)),
        #         result]
        #result = ast.Suite(body=stats)
        result = self.visit(result)
        return result
Beispiel #9
0
    def visit_ArrayNewEmptyNode(self, node):
        if self.nopython:
            raise error.NumbaError(
                node, "Cannot yet allocate new empty array in nopython context")

        ndim = nodes.const(node.type.ndim, int_)
        dtype = nodes.const(node.type.dtype.get_dtype(), object_).cloneable
        is_fortran = nodes.const(node.is_fortran, int_)
        result = nodes.PyArray_Empty([ndim, node.shape, dtype, is_fortran])
        result = nodes.ObjectTempNode(result)
        incref_descr = nodes.IncrefNode(dtype)
        return self.visit(nodes.ExpressionNode([incref_descr], result))
Beispiel #10
0
    def visit_ArrayNewEmptyNode(self, node):
        if self.nopython:
            raise error.NumbaError(
                node, "Cannot yet allocate new empty array in nopython context")

        ndim = nodes.const(node.type.ndim, int_)
        dtype = nodes.const(node.type.dtype.get_dtype(), object_).cloneable
        is_fortran = nodes.const(node.is_fortran, int_)
        result = nodes.PyArray_Empty([ndim, node.shape, dtype, is_fortran])
        result = nodes.ObjectTempNode(result)
        incref_descr = nodes.IncrefNode(dtype)
        return self.visit(nodes.ExpressionNode([incref_descr], result))
Beispiel #11
0
def unpack_range_args(node):
    start, stop, step = (nodes.const(0, Py_ssize_t), None,
                         nodes.const(1, Py_ssize_t))

    if len(node.args) == 0:
        raise error.NumbaError(node, "Expected at least one argument")
    elif len(node.args) == 1:
        stop, = node.args
    elif len(node.args) == 2:
        start, stop = node.args
    else:
        start, stop, step = node.args

    return [start, stop, step]
Beispiel #12
0
def unpack_range_args(node):
    start, stop, step = (nodes.const(0, Py_ssize_t),
                         None,
                         nodes.const(1, Py_ssize_t))

    if len(node.args) == 0:
        raise error.NumbaError(node, "Expected at least one argument")
    elif len(node.args) == 1:
        stop, = node.args
    elif len(node.args) == 2:
        start, stop = node.args
    else:
        start, stop, step = node.args

    return [start, stop, step]
Beispiel #13
0
    def next(self, context, for_node, llvm_module):
        "Index element and update index"
        index = self.index.load
        value = nodes.CloneableNode(index(for_node.iter, index))
        add = ast.BinOp(index, ast.Add(), nodes.const(1, Py_ssize_t))

        return nodes.ExpressionNode(stmts=[value, assign(self.index.store, add)], expr=value.clone)
Beispiel #14
0
    def next(self, context, for_node, llvm_module):
        "Index element and update index"
        index = self.index.load
        value = nodes.CloneableNode(index(for_node.iter, index))
        add = ast.BinOp(index, ast.Add(), nodes.const(1, Py_ssize_t))

        return nodes.ExpressionNode(
            stmts=[value, assign(self.index.store, add)], expr=value.clone)
Beispiel #15
0
 def coerce_to_function_pointer(self, node, jit_func_type, func_pointer_type):
     jit_func = jit_func_type.jit_func
     if jit_func.signature != func_pointer_type.base_type:
         raise error.NumbaError(node,
                                "Cannot coerce jit funcion %s to function of type %s" % (
                                    jit_func, func_pointer_type))
     pointer = self.env.llvm_context.get_pointer_to_function(jit_func.lfunc)
     new_node = nodes.const(pointer, func_pointer_type)
     return new_node
Beispiel #16
0
 def coerce_to_function_pointer(self, node, jit_func_type, func_pointer_type):
     jit_func = jit_func_type.jit_func
     if jit_func.signature != func_pointer_type.base_type:
         raise error.NumbaError(node,
                                "Cannot coerce jit funcion %s to function of type %s" % (
                                    jit_func, func_pointer_type))
     pointer = self.env.llvm_context.get_pointer_to_function(jit_func.lfunc)
     new_node = nodes.const(pointer, func_pointer_type)
     return new_node
Beispiel #17
0
    def visit_CoercionNode(self, node):
        if not isinstance(node, nodes.CoercionNode):
            # CoercionNode.__new__ returns the node to be coerced if it doesn't
            # need coercion
            return node

        node_type = node.node.type
        dst_type = node.dst_type
        if __debug__ and self.env and self.env.debug_coercions:
            logger.debug('coercion: %s --> %s\n%s', node_type, dst_type,
                         utils.pformat_ast(node))

        # TODO: the below is a problem due to implicit string <-> int coercions!
        if (node_type.is_string and dst_type.is_numeric
                and not (node_type.is_pointer or node_type.is_null)):
            if dst_type.typename in ('char', 'uchar'):
                raise error.NumbaError(
                    node,
                    "Conversion from string to (u)char not yet supported")
            result = self.str_to_int(dst_type, node)
        elif self.nopython and (is_obj(node_type) ^ is_obj(dst_type)):
            raise error.NumbaError(
                node, "Cannot coerce to or from object in "
                "nopython context")
        elif is_obj(node.dst_type) and not is_obj(node_type):
            node = nodes.ObjectTempNode(
                nodes.CoerceToObject(node.node, node.dst_type, name=node.name))
            result = self.visit(node)
        elif is_obj(node_type) and not is_obj(node.dst_type):
            node = nodes.CoerceToNative(node.node,
                                        node.dst_type,
                                        name=node.name)
            result = self.visit(node)
        elif node_type.is_null:
            if not dst_type.is_pointer:
                raise error.NumbaError(
                    node.node, "NULL must be cast or implicitly "
                    "coerced to a pointer type")
            result = self.visit(nodes.NULL.coerce(dst_type))
        elif node_type.is_numeric and dst_type.is_bool:
            to_bool = ast.Compare(node.node, [ast.NotEq()],
                                  [nodes.const(0, node_type)])
            to_bool = nodes.typednode(to_bool, bool_)
            result = self.visit(to_bool)
        else:
            self.generic_visit(node)

            if dst_type == node.node.type:
                result = node.node
            else:
                result = node

        if __debug__ and self.env and self.env.debug_coercions:
            logger.debug('result = %s', utils.pformat_ast(result))

        return result
Beispiel #18
0
def parse_signature(node, func_type):
    types = []
    for arg in node.args:
        if not arg.variable.type.is_cast:
            raise error.NumbaError(arg, "Expected a numba type")
        else:
            types.append(arg.variable.type)

    signature = func_type.dst_type(*types)
    new_node = nodes.const(signature, typesystem.CastType(signature))
    return new_node
Beispiel #19
0
    def visit_CoercionNode(self, node):
        if not isinstance(node, nodes.CoercionNode):
            # CoercionNode.__new__ returns the node to be coerced if it doesn't
            # need coercion
            return node

        node_type = node.node.type
        dst_type = node.dst_type
        if __debug__ and self.env and self.env.debug_coercions:
            logger.debug('coercion: %s --> %s\n%s',
                         node_type, dst_type, utils.pformat_ast(node))

        # TODO: the below is a problem due to implicit string <-> int coercions!
        if (node_type.is_string and dst_type.is_numeric and not
            (node_type.is_pointer or node_type.is_null)):
            if dst_type.typename in ('char', 'uchar'):
                raise error.NumbaError(
                    node, "Conversion from string to (u)char not yet supported")
            result = self.str_to_int(dst_type, node)
        elif self.nopython and (is_obj(node_type) ^ is_obj(dst_type)):
            raise error.NumbaError(node, "Cannot coerce to or from object in "
                                         "nopython context")
        elif is_obj(node.dst_type) and not is_obj(node_type):
            node = nodes.ObjectTempNode(nodes.CoerceToObject(
                    node.node, node.dst_type, name=node.name))
            result = self.visit(node)
        elif is_obj(node_type) and not is_obj(node.dst_type):
            node = nodes.CoerceToNative(node.node, node.dst_type,
                                        name=node.name)
            result = self.visit(node)
        elif node_type.is_null:
            if not dst_type.is_pointer:
                raise error.NumbaError(node.node,
                                       "NULL must be cast or implicitly "
                                       "coerced to a pointer type")
            result = self.visit(nodes.NULL.coerce(dst_type))
        elif node_type.is_numeric and dst_type.is_bool:
            to_bool = ast.Compare(node.node, [ast.NotEq()],
                                  [nodes.const(0, node_type)])
            to_bool = nodes.typednode(to_bool, bool_)
            result = self.visit(to_bool)
        else:
            self.generic_visit(node)

            if dst_type == node.node.type:
                result = node.node
            else:
                result = node

        if __debug__ and self.env and self.env.debug_coercions:
            logger.debug('result = %s', utils.pformat_ast(result))

        return result
Beispiel #20
0
    def visit_Print(self, node):
        if self.nopython:
            printfunc = self._print_nopython
            dst_type = c_string_type
        else:
            printfunc = self._print
            dst_type = object_

        result = []

        if node.values:
            print_space = printfunc(nodes.const(" ", dst_type), node.dest)
            for value in node.values:
                result.append(printfunc(value, node.dest))
                result.append(print_space)

            if node.nl:
                result.pop()  # pop last space

        if node.nl:
            result.append(printfunc(nodes.const("\n", dst_type), node.dest))

        return ast.Suite(body=self.visitlist(result))
Beispiel #21
0
    def visit_Print(self, node):
        if self.nopython:
            printfunc = self._print_nopython
            dst_type = string_
        else:
            printfunc = self._print
            dst_type = object_

        result = []

        if node.values:
            print_space = printfunc(nodes.const(" ", dst_type), node.dest)
            for value in node.values:
                result.append(printfunc(value, node.dest))
                result.append(print_space)

            if node.nl:
                result.pop() # pop last space

        if node.nl:
            result.append(printfunc(nodes.const("\n", dst_type), node.dest))

        return ast.Suite(body=self.visitlist(result))
Beispiel #22
0
    def visit_ArrayNewNode(self, node):
        if self.nopython:
            # Give the codegen (subclass) a chance to handle this
            self.generic_visit(node)
            return node

        PyArray_Type = nodes.ObjectInjectNode(np.ndarray)
        descr = nodes.ObjectInjectNode(node.type.dtype.get_dtype()).cloneable
        ndim = nodes.const(node.type.ndim, int_)
        flags = nodes.const(0, int_)
        args = [
            PyArray_Type, descr.clone, ndim, node.shape, node.strides,
            node.data, flags
        ]

        incref_descr = nodes.IncrefNode(descr)
        incref_base = None
        setbase = None

        if node.base is None:
            args.append(nodes.NULL_obj)
        else:
            base = nodes.CloneableNode(node.base)
            incref_base = nodes.IncrefNode(base)
            args.append(base.clone)

        array = nodes.PyArray_NewFromDescr(args)
        array = nodes.ObjectTempNode(array).cloneable
        body = [incref_descr, incref_base, array, setbase]

        if node.base is not None:
            body.append(nodes.PyArray_SetBaseObject([array.clone, base.clone]))

        # TODO: PyArray_UpdateFlags()
        result = nodes.ExpressionNode(filter(None, body), array.clone)
        return self.visit(result)
Beispiel #23
0
    def lookup(self, env, always_present, node, args):
        """
        :param node: ExtensionMethodNode
        :param args: [vtable_node, prehash_node]
        :return: The virtual method as a Node
        """
        from numba.utility import virtuallookup

        if always_present and False:
            lookup = virtuallookup.lookup_method
        else:
            lookup = virtuallookup.lookup_and_assert_method
            args.append(nodes.const(node.attr, c_string_type))

        vmethod = call_jit(lookup, args)
        return vmethod
Beispiel #24
0
    def lookup(self, env, always_present, node, args):
        """
        :param node: ExtensionMethodNode
        :param args: [vtable_node, prehash_node]
        :return: The virtual method as a Node
        """
        from numba.utility import virtuallookup

        if always_present and False:
            lookup = virtuallookup.lookup_method
        else:
            lookup = virtuallookup.lookup_and_assert_method
            args.append(nodes.const(node.attr, c_string_type))

        vmethod = call_jit(lookup, args)
        return vmethod
Beispiel #25
0
    def single_compare_objects(self, node):
        op = type(node.ops[0])
        if op not in opmap:
            raise error.NumbaError(
                    node, "%s comparisons not yet implemented" % (op,))

        # Build arguments for PyObject_RichCompareBool
        operator = nodes.const(opmap[op], int_)
        args = [node.left, node.comparators[0], operator]

        # Call PyObject_RichCompareBool
        compare = function_util.external_call(self.context,
                                              self.llvm_module,
                                              'PyObject_RichCompareBool',
                                              args=args)

        # Coerce int result to bool
        return nodes.CoercionNode(compare, bool_)
Beispiel #26
0
    def visit_Name(self, node):
        if (is_obj(node.type) and isinstance(node.ctx, ast.Load) and
            getattr(node, 'cf_maybe_null', False)):
            # Check for unbound objects and raise UnboundLocalError if so
            value = nodes.LLVMValueRefNode(Py_uintptr_t, None)
            node.loaded_name = value

            exc_msg = node.variable.name
            if hasattr(node, 'lineno'):
                exc_msg = '%s%s' % (error.format_pos(node), exc_msg)

            check_unbound = nodes.CheckErrorNode(
                value, badval=nodes.const(0, Py_uintptr_t),
                exc_type=UnboundLocalError,
                exc_msg=exc_msg)
            node.check_unbound = self.visit(check_unbound)

        return node
Beispiel #27
0
    def single_compare_objects(self, node):
        op = type(node.ops[0])
        if op not in opmap:
            raise error.NumbaError(
                node, "%s comparisons not yet implemented" % (op, ))

        # Build arguments for PyObject_RichCompareBool
        operator = nodes.const(opmap[op], int_)
        args = [node.left, node.comparators[0], operator]

        # Call PyObject_RichCompareBool
        compare = function_util.external_call(self.context,
                                              self.llvm_module,
                                              'PyObject_RichCompare',
                                              args=args)

        # Coerce int result to bool
        return nodes.CoercionNode(compare, node.type)
Beispiel #28
0
def get_closure_scope(func_signature, func_obj):
    """
    Retrieve the closure from the NumbaFunction from the func_closure
    attribute.

        func_signature:
            signature of closure function

        func_obj:
            LLVM Value referencing the closure function as a Python object
    """
    closure_scope_type = func_signature.args[0]
    offset = numbawrapper.numbafunc_closure_field_offset
    closure = nodes.LLVMValueRefNode(void.pointer(), func_obj)
    closure = nodes.CoercionNode(closure, char.pointer())
    closure_field = nodes.pointer_add(closure, nodes.const(offset, size_t))
    closure_field = nodes.CoercionNode(closure_field, closure_scope_type.pointer())
    closure_scope = nodes.DereferenceNode(closure_field)
    return closure_scope
Beispiel #29
0
    def visit_Name(self, node):
        if (is_obj(node.type) and isinstance(node.ctx, ast.Load)
                and getattr(node, 'cf_maybe_null', False)):
            # Check for unbound objects and raise UnboundLocalError if so
            value = nodes.LLVMValueRefNode(Py_uintptr_t, None)
            node.loaded_name = value

            exc_msg = node.variable.name
            if hasattr(node, 'lineno'):
                exc_msg = '%s%s' % (error.format_pos(node), exc_msg)

            check_unbound = nodes.CheckErrorNode(value,
                                                 badval=nodes.const(
                                                     0, Py_uintptr_t),
                                                 exc_type=UnboundLocalError,
                                                 exc_msg=exc_msg)
            node.check_unbound = self.visit(check_unbound)

        return node
Beispiel #30
0
    def _print_nopython(self, value, dest=None):
        if dest is not None:
            raise error.NumbaError(dest,
                                   "No file may be given in nopython mode")

        # stdin, stdout, stderr = stdio_util.get_stdio_streams()
        # stdout = stdio_util.get_stream_as_node(stdout)

        format = codegen.get_printf_specifier(value.type)
        if format is None:
            raise error.NumbaError(
                value, "Printing values of type '%s' is not supported "
                "in nopython mode" % (value.type, ))

        return function_util.external_call(
            self.context,
            self.llvm_module,
            'printf',
            args=[nodes.const(format, c_string_type), value])
Beispiel #31
0
    def _print_nopython(self, value, dest=None):
        if dest is not None:
            raise error.NumbaError(dest, "No file may be given in nopython mode")

        # stdin, stdout, stderr = stdio_util.get_stdio_streams()
        # stdout = stdio_util.get_stream_as_node(stdout)

        format = codegen.get_printf_specifier(value.type)
        if format is None:
            raise error.NumbaError(
                value, "Printing values of type '%s' is not supported "
                       "in nopython mode" % (value.type,))

        return function_util.external_call(
                                       self.context,
                                       self.llvm_module,
                                       'printf',
                                       args=[nodes.const(format, c_string_type),
                                             value])
Beispiel #32
0
def get_closure_scope(func_signature, func_obj):
    """
    Retrieve the closure from the NumbaFunction from the func_closure
    attribute.

        func_signature:
            signature of closure function

        func_obj:
            LLVM Value referencing the closure function as a Python object
    """
    closure_scope_type = func_signature.args[0]
    offset = numbawrapper.numbafunc_closure_field_offset
    closure = nodes.LLVMValueRefNode(void.pointer(), func_obj)
    closure = nodes.CoercionNode(closure, char.pointer())
    closure_field = nodes.pointer_add(closure, nodes.const(offset, size_t))
    closure_field = nodes.CoercionNode(closure_field,
                                       closure_scope_type.pointer())
    closure_scope = nodes.DereferenceNode(closure_field)
    return closure_scope
Beispiel #33
0
    def _trap(self, body, node):
        if node.exc_msg and node.print_on_trap:
            pos = error.format_pos(node)
            if node.exception_type:
                exc_type = '%s: ' % node.exception_type.__name__
            else:
                exc_type = ''

            msg = '%s%s%%s' % (exc_type, pos)
            format = nodes.const(msg, c_string_type)
            print_msg = function_util.external_call(self.context,
                                                    self.llvm_module,
                                                    'printf',
                                                    args=[format,
                                                          node.exc_msg])
            body.append(print_msg)

        trap = nodes.LLVMIntrinsicNode(signature=void(), args=[],
                                       func_name='TRAP')
        body.append(trap)
Beispiel #34
0
    def _trap(self, body, node):
        if node.exc_msg and node.print_on_trap:
            pos = error.format_pos(node)
            if node.exception_type:
                exc_type = '%s: ' % node.exception_type.__name__
            else:
                exc_type = ''

            msg = '%s%s%%s' % (exc_type, pos)
            format = nodes.const(msg, c_string_type)
            print_msg = function_util.external_call(
                self.context,
                self.llvm_module,
                'printf',
                args=[format, node.exc_msg])
            body.append(print_msg)

        trap = nodes.LLVMIntrinsicNode(signature=void(),
                                       args=[],
                                       func_name='TRAP')
        body.append(trap)
Beispiel #35
0
def typedcontainer_infer(compile_typedcontainer, type_node, iterable_node):
    """
    Type inferer for typed containers, register with numba.register_inferer().

    :param compile_typedcontainer: item_type -> typed container extension class
    :param type_node: type parameter to typed container constructor
    :param iterable_node: value parameter to typed container constructor (optional)
    """
    assert type_node is not None

    type = get_type(type_node)
    if type.is_cast:
        elem_type = type.dst_type

        # Pre-compile typed list implementation
        typedcontainer_ctor = compile_typedcontainer(elem_type)

        # Inject the typedlist directly to avoid runtime implementation lookup
        iterable_node = iterable_node or nodes.const(None, object_)
        result = nodes.call_pyfunc(typedcontainer_ctor, (iterable_node,))
        return nodes.CoercionNode(result, typedcontainer_ctor.exttype)

    return object_
Beispiel #36
0
def typedcontainer_infer(compile_typedcontainer, type_node, iterable_node):
    """
    Type inferer for typed containers, register with numba.register_inferer().

    :param compile_typedcontainer: item_type -> typed container extension class
    :param type_node: type parameter to typed container constructor
    :param iterable_node: value parameter to typed container constructor (optional)
    """
    assert type_node is not None

    type = get_type(type_node)
    if type.is_cast:
        elem_type = type.dst_type

        # Pre-compile typed list implementation
        typedcontainer_ctor = compile_typedcontainer(elem_type)

        # Inject the typedlist directly to avoid runtime implementation lookup
        iterable_node = iterable_node or nodes.const(None, object_)
        result = nodes.call_pyfunc(typedcontainer_ctor, (iterable_node,))
        return nodes.CoercionNode(result, typedcontainer_ctor.exttype)

    return object_
Beispiel #37
0
    def visit_For(self, node):
        while_node = make_while_from_for(node)

        test = nodes.const(True, bool_)
        while_node.test = test

        impl = loopimpl.find_iterator_impl(node)

        # Get the iterator, loop body, and the item
        iter = impl.getiter(self.context, node, self.llvm_module)
        body = impl.body(self.context, node, self.llvm_module)
        item = impl.next(self.context, node, self.llvm_module)

        # Coerce item to LHS and assign
        item = nodes.CoercionNode(item, node.target.type)
        target_assmnt = ast.Assign(targets=[node.target], value=item)

        # Update While node body
        body.insert(0, target_assmnt)
        while_node.body = body

        nodes.merge_cfg_in_while(while_node)

        return ast.Suite(body=[iter, while_node])
Beispiel #38
0
    def visit_For(self, node):
        while_node = make_while_from_for(node)

        test = nodes.const(True, bool_)
        while_node.test = test

        impl = loopimpl.find_iterator_impl(node)

        # Get the iterator, loop body, and the item
        iter = impl.getiter(self.context, node, self.llvm_module)
        body = impl.body(self.context, node, self.llvm_module)
        item = impl.next(self.context, node, self.llvm_module)

        # Coerce item to LHS and assign
        item = nodes.CoercionNode(item, node.target.type)
        target_assmnt = ast.Assign(targets=[node.target], value=item)

        # Update While node body
        body.insert(0, target_assmnt)
        while_node.body = body

        nodes.merge_cfg_in_while(while_node)

        return ast.Suite(body=[iter, while_node])
Beispiel #39
0
def rewrite_prange(env, prange_node, target, locals_dict, closures_dict):
    func_def = prange_node.func_def
    struct_type = prange_node.privates_struct_type

    templ = templating.TemplateContext(env.context,
                                       prange_template % func_def.name)

    # Allocate context for each thread
    num_threads = NUM_THREADS
    contexts_array_type = minitypes.CArrayType(struct_type, num_threads)

    # Create variables for template substitution
    nsteps = templ.temp_var('nsteps')
    temp_i = templ.temp_var('i', int32)
    contexts = templ.temp_var('contexts', contexts_array_type)
    temp_struct = templ.temp_var('temp_struct', struct_type)
    lastprivates = templ.temp_var("lastprivates")

    pack_struct = templ.code_var('pack_struct')

    if isinstance(target, ast.Name):
        target_name = target.id
        struct_type.add_field(target_name, Py_ssize_t)
    else:
        raise error.NumbaError(
            prange_node, "Only name target for prange is currently supported")

    # Create code for reductions and (last)privates
    for name, reduction_op in prange_node.reductions.iteritems():
        default = get_reduction_default(reduction_op)
        pack_struct.codes.append("%s.%s = %s" % (temp_struct, name, default))

    # Update struct type with closure scope, index variable, start,
    # stop and step
    struct_type.add_field('__numba_closure_scope', void.pointer())
    struct_type.add_field('__numba_start', npy_intp)
    struct_type.add_field('__numba_stop', npy_intp)
    struct_type.add_field('__numba_step', npy_intp)

    # Interpolate code and variables and run type inference
    # TODO: UNDO monkeypatching
    func_def.type = prange_node.func_env.func_signature
    func_def.is_prange_body = True
    func_def.prange_node = prange_node

    num_threads_node = nodes.const(num_threads, Py_ssize_t)

    invoke = InvokeAndJoinThreads(env,
                                  contexts=contexts.node,
                                  func_def_name=func_def.name,
                                  struct_type=struct_type,
                                  target_name=target_name,
                                  num_threads=num_threads_node,
                                  closures=closures_dict)

    closure_scope = nodes.ClosureScopeLoadNode()
    subs = dict(
        func_def=func_def,
        func_def_name=func_def.name,
        closure_scope=closure_scope,
        invoke_and_join_threads=invoke,
        num_threads=num_threads_node,
        start=nodes.UntypedCoercion(prange_node.start, Py_ssize_t),
        stop=nodes.UntypedCoercion(prange_node.stop, Py_ssize_t),
        step=nodes.UntypedCoercion(prange_node.step, Py_ssize_t),
    )

    tree = templ.template(subs)

    temporaries = {}
    templ.update_locals(temporaries)
    locals_dict.update(temporaries)

    kill_attribute_assignments(env, prange_node, temporaries)

    # TODO: Make this an SSA variable
    locals_dict[target_name] = Py_ssize_t

    prange_node.target = target
    prange_node.num_threads_node = num_threads_node  #.clone
    prange_node.template_vars = {
        'contexts': contexts,
        'i': temp_i,
        'lastprivates': lastprivates,
        'nsteps': nsteps,
    }

    # print(templ.substituted_template)
    return tree
Beispiel #40
0
    def visit_CoercionNode(self, node):
        if not isinstance(node, nodes.CoercionNode):
            # CoercionNode.__new__ returns the node to be coerced if it doesn't
            # need coercion
            return node

        node_type = node.node.type
        dst_type = node.dst_type
        if __debug__ and self.env and self.env.debug_coercions:
            logger.debug('coercion: %s --> %s\n%s', node_type, dst_type,
                         utils.pformat_ast(node))

        if self.nopython and (is_obj(node_type) ^ is_obj(dst_type)):
            raise error.NumbaError(
                node, "Cannot coerce to or from object in "
                "nopython context")

        if is_obj(node.dst_type) and not is_obj(node_type):
            node = nodes.ObjectTempNode(
                nodes.CoerceToObject(node.node, node.dst_type, name=node.name))
            result = self.visit(node)
        elif is_obj(node_type) and not is_obj(node.dst_type):
            node = nodes.CoerceToNative(node.node,
                                        node.dst_type,
                                        name=node.name)
            result = self.visit(node)
        elif node_type.is_null:
            if not dst_type.is_pointer:
                raise error.NumbaError(
                    node.node, "NULL must be cast or implicitly "
                    "coerced to a pointer type")
            result = self.visit(nodes.NULL.coerce(dst_type))
        elif node_type.is_numeric and dst_type.is_bool:
            to_bool = ast.Compare(node.node, [ast.NotEq()],
                                  [nodes.const(0, node_type)])
            to_bool = nodes.typednode(to_bool, bool_)
            result = self.visit(to_bool)
        elif node_type.is_c_string and dst_type.is_numeric:
            # TODO: int <-> string conversions are explicit, this should not
            # TODO: be a coercion
            if self.nopython:
                node = nodes.CoercionNode(
                    function_util.external_call(
                        self.context,
                        self.llvm_module,
                        ('atol' if dst_type.is_int else 'atof'),
                        args=[node.node]),
                    dst_type,
                    name=node.name,
                )
            else:
                if dst_type.is_int:
                    cvtobj = function_util.external_call(
                        self.context,
                        self.llvm_module,
                        'PyInt_FromString' if not PY3 else 'PyLong_FromString',
                        args=[node.node, nodes.NULL,
                              nodes.const(10, int_)])
                else:
                    cvtobj = function_util.external_call(
                        self.context,
                        self.llvm_module,
                        'PyFloat_FromString',
                        args=[node.node, nodes.const(0, Py_ssize_t)])
                node = nodes.CoerceToNative(nodes.ObjectTempNode(cvtobj),
                                            dst_type,
                                            name=node.name)
            result = self.visit(node)
        else:
            self.generic_visit(node)

            if dst_type == node.node.type:
                result = node.node
            else:
                result = node

        if __debug__ and self.env and self.env.debug_coercions:
            logger.debug('result = %s', utils.pformat_ast(result))

        return result
Beispiel #41
0
 def visit_ArrayNewEmptyNode(self, node):
     ndim = nodes.const(node.type.ndim, int_)
     dtype = nodes.const(node.type.dtype.get_dtype(), object_)
     is_fortran = nodes.const(node.is_fortran, int_)
     result = nodes.PyArray_Empty([ndim, node.shape, dtype, is_fortran])
     return self.visit(result)
Beispiel #42
0
    def create_numba_function(self, node, p):
        closure_scope = self.ast.cur_scope

        if closure_scope is None:
            closure_scope = nodes.NULL
            scope_type = void.pointer()
        else:
            assert node.func_def.args.args[0].variable.type
            scope_type = closure_scope.type

        node.wrapper_func, node.wrapper_lfunc, methoddef = (
            p.translator.build_wrapper_function(get_lfunc=True))

        # Keep methoddef alive
        assert methoddef in node.py_func.live_objects
        modname = self.func.__module__
        node.py_func.live_objects.append(modname)

        # Create function with closure scope at runtime
        create_numbafunc_signature = node.type(
            void.pointer(),  # PyMethodDef *ml
            object_,  # PyObject *module
            void.pointer(),  # PyObject *code
            scope_type,  # PyObject *closure
            void.pointer(),  # void *native_func
            object_,  # PyObject *native_signature
            object_,  # PyObject *keep_alive
        )
        create_numbafunc = nodes.ptrfromint(
            extension_types.NumbaFunction_NewEx_pointer,
            create_numbafunc_signature.pointer())

        methoddef_p = ctypes.cast(ctypes.byref(methoddef),
                                  ctypes.c_void_p).value

        args = [
            nodes.const(methoddef_p, void.pointer()),
            nodes.const(modname, object_),
            nodes.NULL,
            closure_scope,
            nodes.const(node.lfunc_pointer, void.pointer()),
            nodes.const(node.type.signature, object_),
            nodes.const(node.py_func, object_),
        ]

        func_call = nodes.NativeFunctionCallNode(
            signature=create_numbafunc_signature,
            function_node=create_numbafunc,
            args=args)

        # Assign closure to its name
        func_name = node.func_def.name
        dst = self._load_name(func_name, self.symtab[func_name].is_cellvar)
        dst.ctx = ast.Store()
        result = ast.Assign(targets=[dst], value=func_call)

        #stats = [nodes.inject_print(nodes.const("calling...", c_string_type)),
        #         result]
        #result = ast.Suite(body=stats)
        result = self.visit(result)
        return result
Beispiel #43
0
 def lookup(self, env, always_present, node, args):
     args.append(nodes.const(node.attr, c_string_type))
     vmethod = function_util.utility_call(
         env.context, env.crnt.llvm_module,
         "lookup_method", args)
     return vmethod
Beispiel #44
0
 def visit_ArrayNewEmptyNode(self, node):
     ndim = nodes.const(node.type.ndim, int_)
     dtype = nodes.const(node.type.dtype.get_dtype(), object_)
     is_fortran = nodes.const(node.is_fortran, int_)
     result = nodes.PyArray_Empty([ndim, node.shape, dtype, is_fortran])
     return self.visit(result)
Beispiel #45
0
    def handle_method_call(self, env, node, call_node):
        """
        Resolve an extension method of a dynamic hash-based vtable:

            PyCustomSlots_Table ***vtab_slot = (((char *) obj) + vtab_offset)
            lookup_virtual_method(*vtab_slot)

        We may cache (*vtab_slot), but we may not cache (**vtab_slot), since
        compilations may regenerate the table.

        However, we could *preload* (**vtab_slot), where function calls
        invalidate the preload, if we were so inclined.
        """
        from numba.utility import virtuallookup

        # Make the object we call the method on clone-able
        node.value = nodes.CloneableNode(node.value)

        ext_type = node.ext_type
        func_signature = node.type
        offset = ext_type.vtab_offset

        # __________________________________________________________________
        # Retrieve vtab

        vtab_ppp = nodes.value_at_offset(node.value, offset,
                                         void.pointer().pointer())
        vtab_struct_pp = nodes.DereferenceNode(vtab_ppp)

        # __________________________________________________________________
        # Calculate pre-hash

        prehash = virtual.hash_signature(func_signature, func_signature.name)
        prehash_node = nodes.ConstNode(prehash, uint64)

        # __________________________________________________________________
        # Retrieve method pointer

        # A method is always present when it was given a static signature,
        # e.g. @double(double)
        always_present = node.attr in ext_type.vtab_type.methodnames

        args = [vtab_struct_pp, prehash_node]

        if always_present:
            lookup = virtuallookup.lookup_method
        else:
            lookup = virtuallookup.lookup_and_assert_method
            args.append(nodes.const(node.attr, c_string_type))

        vmethod = call_jit(lookup, args).coerce(func_signature.pointer())
        vmethod = vmethod.cloneable

        # __________________________________________________________________
        # Call method pointer

        # Insert first argument 'self' in args list
        args = call_node.args
        args.insert(0, nodes.CloneNode(node.value))
        method_call = nodes.NativeFunctionCallNode(func_signature, vmethod, args)

        # __________________________________________________________________
        # Generate fallback

        # TODO: Subclassing!
        # if not always_present:
        #     # TODO: Enable this path and generate a phi for the result
        #     # Generate object call
        #     obj_args = [nodes.CoercionNode(arg, object_) for arg in args]
        #     obj_args.append(nodes.NULL)
        #     object_call = function_util.external_call(
        #         env.context, env.crnt.llvm_module,
        #         'PyObject_CallMethodObjArgs', obj_args)
        #
        #     # if vmethod != NULL: vmethod(obj, ...)
        #     # else: obj.method(...)
        #     method_call = nodes.if_else(
        #         ast.NotEq(),
        #         vmethod.clone, nodes.NULL,
        #         lhs=method_call, rhs=object_call)

        return method_call
Beispiel #46
0
 def getiter(self, context, for_node, llvm_module):
     self.index = nodes.TempNode(Py_ssize_t, "iterator_index")
     return assign(self.index, nodes.const(0, Py_ssize_t))
Beispiel #47
0
def rewrite_prange(env, prange_node, target, locals_dict, closures_dict):
    func_def = prange_node.func_def
    struct_type = prange_node.privates_struct_type

    templ = templating.TemplateContext(env.context,
                                       prange_template % func_def.name)

    # Allocate context for each thread
    num_threads = NUM_THREADS
    contexts_array_type = minitypes.CArrayType(struct_type,
                                               num_threads)

    # Create variables for template substitution
    nsteps = templ.temp_var('nsteps')
    temp_i = templ.temp_var('i', int32)
    contexts = templ.temp_var('contexts', contexts_array_type)
    temp_struct = templ.temp_var('temp_struct', struct_type)
    lastprivates = templ.temp_var("lastprivates")

    pack_struct = templ.code_var('pack_struct')

    if isinstance(target, ast.Name):
        target_name = target.id
        struct_type.add_field(target_name, Py_ssize_t)
    else:
        raise error.NumbaError(
            prange_node, "Only name target for prange is currently supported")

    # Create code for reductions and (last)privates
    for name, reduction_op in prange_node.reductions.iteritems():
        default = get_reduction_default(reduction_op)
        pack_struct.codes.append("%s.%s = %s" % (temp_struct, name,
                                                 default))

    # Update struct type with closure scope, index variable, start,
    # stop and step
    struct_type.add_field('__numba_closure_scope', void.pointer())
    struct_type.add_field('__numba_start', npy_intp)
    struct_type.add_field('__numba_stop', npy_intp)
    struct_type.add_field('__numba_step', npy_intp)

    # Interpolate code and variables and run type inference
    # TODO: UNDO monkeypatching
    func_def.type = prange_node.func_env.func_signature
    func_def.is_prange_body = True
    func_def.prange_node = prange_node

    num_threads_node = nodes.const(num_threads, Py_ssize_t)

    invoke = InvokeAndJoinThreads(env, contexts=contexts.node,
                                  func_def_name=func_def.name,
                                  struct_type=struct_type,
                                  target_name=target_name,
                                  num_threads=num_threads_node,
                                  closures=closures_dict)

    closure_scope = nodes.ClosureScopeLoadNode()
    subs = dict(
        func_def=func_def,
        func_def_name=func_def.name,
        closure_scope=closure_scope,
        invoke_and_join_threads=invoke,
        num_threads=num_threads_node,
        start=nodes.UntypedCoercion(prange_node.start, Py_ssize_t),
        stop=nodes.UntypedCoercion(prange_node.stop, Py_ssize_t),
        step=nodes.UntypedCoercion(prange_node.step, Py_ssize_t),
    )

    tree = templ.template(subs)

    temporaries = {}
    templ.update_locals(temporaries)
    locals_dict.update(temporaries)

    kill_attribute_assignments(env, prange_node, temporaries)

    # TODO: Make this an SSA variable
    locals_dict[target_name] = Py_ssize_t

    prange_node.target = target
    prange_node.num_threads_node = num_threads_node #.clone
    prange_node.template_vars = {
                                  'contexts': contexts,
                                  'i': temp_i,
                                  'lastprivates': lastprivates,
                                  'nsteps': nsteps,
                                }

    # print(templ.substituted_template)
    return tree
Beispiel #48
0
def typeof(expr_type):
    from numba import nodes

    type = typesystem.CastType(expr_type)
    return nodes.const(expr_type, type)
Beispiel #49
0
    def visit_Name(self, node):
        if node.variable.is_constant:
            obj = node.variable.constant_value
            return self.visit(nodes.const(obj, node.type))

        return node
Beispiel #50
0
    def visit_CoercionNode(self, node):
        if not isinstance(node, nodes.CoercionNode):
            # CoercionNode.__new__ returns the node to be coerced if it doesn't
            # need coercion
            return node

        node_type = node.node.type
        dst_type = node.dst_type
        if __debug__ and self.env and self.env.debug_coercions:
            logger.debug('coercion: %s --> %s\n%s',
                         node_type, dst_type, utils.pformat_ast(node))

        if self.nopython and is_obj(node_type):
            raise error.NumbaError(node, "Cannot coerce to or from object in "
                                         "nopython context")

        if is_obj(node.dst_type) and not is_obj(node_type):
            node = nodes.ObjectTempNode(nodes.CoerceToObject(
                    node.node, node.dst_type, name=node.name))
            result = self.visit(node)
        elif is_obj(node_type) and not is_obj(node.dst_type):
            node = nodes.CoerceToNative(node.node, node.dst_type,
                                        name=node.name)
            result = self.visit(node)
        elif node_type.is_null:
            if not dst_type.is_pointer:
                raise error.NumbaError(node.node,
                                       "NULL must be cast or implicitly "
                                       "coerced to a pointer type")
            result = self.visit(nodes.NULL.coerce(dst_type))
        elif node_type.is_numeric and dst_type.is_bool:
            to_bool = ast.Compare(node.node, [ast.NotEq()],
                                  [nodes.const(0, node_type)])
            to_bool = nodes.typednode(to_bool, bool_)
            result = self.visit(to_bool)
        elif node_type.is_c_string and dst_type.is_numeric:
            # TODO: int <-> string conversions are explicit, this should not
            # TODO: be a coercion
            if self.nopython:
                node = nodes.CoercionNode(
                    function_util.external_call(
                                self.context,
                                self.llvm_module,
                                ('atol' if dst_type.is_int else 'atof'),
                                args=[node.node]),
                    dst_type, name=node.name,)
            else:
                if dst_type.is_int:
                    cvtobj = function_util.external_call(
                                              self.context,
                                              self.llvm_module,
                                              'PyInt_FromString' if not PY3 else 'PyLong_FromString',
                                              args=[node.node, nodes.NULL,
                                                    nodes.const(10, int_)])
                else:
                    cvtobj = function_util.external_call(
                                          self.context,
                                          self.llvm_module,
                                          'PyFloat_FromString',
                                          args=[node.node,
                                                nodes.const(0, Py_ssize_t)])
                node = nodes.CoerceToNative(nodes.ObjectTempNode(cvtobj),
                                            dst_type, name=node.name)
            result = self.visit(node)
        else:
            self.generic_visit(node)

            if dst_type == node.node.type:
                result = node.node
            else:
                result = node

        if __debug__ and self.env and self.env.debug_coercions:
            logger.debug('result = %s', utils.pformat_ast(result))

        return result
Beispiel #51
0
 def lookup(self, env, always_present, node, args):
     args.append(nodes.const(node.attr, c_string_type))
     vmethod = function_util.utility_call(env.context, env.crnt.llvm_module,
                                          "lookup_method", args)
     return vmethod
Beispiel #52
0
    def create_numba_function(self, node, func_env):
        from numba.codegen import llvmwrapper

        closure_scope = self.ast.cur_scope

        if closure_scope is None:
            closure_scope = nodes.NULL
            scope_type = void.pointer()
        else:
            assert node.func_def.args.args[0].variable.type
            scope_type = closure_scope.type

        self.env.translation.push_env(func_env)
        try:
            node.wrapper_func, node.wrapper_lfunc, methoddef = (
                llvmwrapper.build_wrapper_function(self.env))
        finally:
            self.env.translation.pop()

        # Keep methoddef alive
        # assert methoddef in node.py_func.live_objects
        modname = self.module_name
        self.keep_alive(modname)

        # Create function signature with closure scope at runtime
        create_numbafunc_signature = node.type(
            void.pointer(),  # PyMethodDef *ml
            object_,  # PyObject *module
            void.pointer(),  # PyObject *code
            scope_type,  # PyObject *closure
            void.pointer(),  # void *native_func
            object_,  # PyObject *native_signature
            object_,  # PyObject *keep_alive
        )

        # Create function with closure scope at runtime
        create_numbafunc = nodes.ptrfromint(
            numbawrapper.NumbaFunction_NewEx_pointer,
            create_numbafunc_signature.pointer())

        methoddef_p = ctypes.cast(ctypes.byref(methoddef),
                                  ctypes.c_void_p).value

        args = [
            nodes.const(methoddef_p, void.pointer()),
            nodes.const(modname, object_),
            nodes.NULL,
            closure_scope,
            nodes.const(node.lfunc_pointer, void.pointer()),
            nodes.const(node.type.signature, object_),
            nodes.NULL,  # nodes.const(node.py_func, object_),
        ]

        func_call = nodes.NativeFunctionCallNode(
            signature=create_numbafunc_signature,
            function_node=create_numbafunc,
            args=args)

        result = func_call

        #stats = [nodes.inject_print(nodes.const("calling...", c_string_type)),
        #         result]
        #result = ast.Suite(body=stats)
        result = self.visit(result)
        return result
Beispiel #53
0
 def getiter(self, context, for_node, llvm_module):
     self.index = nodes.TempNode(Py_ssize_t, "iterator_index")
     return assign(self.index, nodes.const(0, Py_ssize_t))
Beispiel #54
0
    def visit_Name(self, node):
        if node.variable.is_constant:
            obj = node.variable.constant_value
            return self.visit(nodes.const(obj, node.type))

        return node
Beispiel #55
0
    def typeof(self, expr):
        from numba import nodes

        obj = expr.variable.type
        type = typesystem.CastType(obj)
        return nodes.const(obj, type)
Beispiel #56
0
    def handle_method_call(self, env, node, call_node):
        """
        Resolve an extension method of a dynamic hash-based vtable:

            PyCustomSlots_Table ***vtab_slot = (((char *) obj) + vtab_offset)
            lookup_virtual_method(*vtab_slot)

        We may cache (*vtab_slot), but we may not cache (**vtab_slot), since
        compilations may regenerate the table.

        However, we could *preload* (**vtab_slot), where function calls
        invalidate the preload, if we were so inclined.
        """
        from numba.utility import virtuallookup

        # Make the object we call the method on clone-able
        node.value = nodes.CloneableNode(node.value)

        ext_type = node.ext_type
        func_signature = node.type
        offset = ext_type.vtab_offset

        # __________________________________________________________________
        # Retrieve vtab

        vtab_ppp = nodes.value_at_offset(node.value, offset,
                                         void.pointer().pointer())
        vtab_struct_pp = nodes.DereferenceNode(vtab_ppp)

        # __________________________________________________________________
        # Calculate pre-hash

        prehash = virtual.hash_signature(func_signature, func_signature.name)
        prehash_node = nodes.ConstNode(prehash, uint64)

        # __________________________________________________________________
        # Retrieve method pointer

        # A method is always present when it was given a static signature,
        # e.g. @double(double)
        always_present = node.attr in ext_type.vtab_type.methodnames

        args = [vtab_struct_pp, prehash_node]

        if always_present:
            lookup = virtuallookup.lookup_method
        else:
            lookup = virtuallookup.lookup_and_assert_method
            args.append(nodes.const(node.attr, c_string_type))

        vmethod = call_jit(lookup, args).coerce(func_signature.pointer())
        vmethod = vmethod.cloneable

        # __________________________________________________________________
        # Call method pointer

        # Insert first argument 'self' in args list
        args = call_node.args
        args.insert(0, nodes.CloneNode(node.value))
        method_call = nodes.NativeFunctionCallNode(func_signature, vmethod,
                                                   args)

        # __________________________________________________________________
        # Generate fallback

        # TODO: Subclassing!
        # if not always_present:
        #     # TODO: Enable this path and generate a phi for the result
        #     # Generate object call
        #     obj_args = [nodes.CoercionNode(arg, object_) for arg in args]
        #     obj_args.append(nodes.NULL)
        #     object_call = function_util.external_call(
        #         env.context, env.crnt.llvm_module,
        #         'PyObject_CallMethodObjArgs', obj_args)
        #
        #     # if vmethod != NULL: vmethod(obj, ...)
        #     # else: obj.method(...)
        #     method_call = nodes.if_else(
        #         ast.NotEq(),
        #         vmethod.clone, nodes.NULL,
        #         lhs=method_call, rhs=object_call)

        return method_call