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 visit_Attribute(self, node):
        if (self.nopython and not node.value.type.is_module
                and not node.value.type.is_complex):
            raise error.NumbaError(
                node,
                "Cannot access Python attribute in nopython context (%s)" %
                node.attr)

        if node.value.type.is_complex:
            value = self.visit(node.value)
            return nodes.ComplexAttributeNode(value, node.attr)
        elif node.type.is_numpy_attribute:
            return nodes.ObjectInjectNode(node.type.value)
        elif node.type.is_numpy_dtype:
            dtype_type = node.type.dtype
            return nodes.ObjectInjectNode(dtype_type.get_dtype())
        elif is_obj(node.value.type):
            if node.value.type.is_module:
                # Resolve module attributes as constants
                if node.type.is_module_attribute:
                    new_node = nodes.ObjectInjectNode(node.type.value)
                else:
                    new_node = nodes.ConstNode(
                        getattr(node.value.type.module, node.attr))
            else:
                new_node = function_util.external_call(
                    self.context,
                    self.llvm_module,
                    'PyObject_GetAttrString',
                    args=[node.value, nodes.ConstNode(node.attr)])
            return self.visit(new_node)

        self.generic_visit(node)
        return node
Beispiel #3
0
 def _object_Not(self, node):
     callnode = function_util.external_call(self.function_cache,
                                            self.llvm_module,
                                            'PyObject_IsTrue',
                                            args=[node.operand])
     cmpnode = ast.Compare(callnode, [nodes.Eq()], [nodes.ConstNode(0)])
     return self.visit(
         nodes.IfExp(cmpnode, nodes.ObjectInjectNode(True),
                     nodes.ObjectInjectNode(False)))
Beispiel #4
0
    def visit_ClosureNode(self, node):
        """
        Compile the inner function.
        """
        # Compile closure, skip CFA and type inference
        node.func_env.qualified_name = self.get_qname(node)
        numba.pipeline.run_env(self.env,
                               node.func_env,
                               pipeline_name='compile')

        translator = node.func_env.translator
        # translator.link()
        node.lfunc = translator.lfunc
        node.lfunc_pointer = translator.lfunc_pointer

        if node.need_numba_func:
            return self.create_numba_function(node, node.func_env)
        else:
            func_name = node.func_def.name
            self.symtab[func_name] = Variable(name=func_name,
                                              type=node.type,
                                              is_local=True)
            # return nodes.LLVMValueRefNode(node.type, node.lfunc)
            # TODO: Remove assignment altogether!
            # return nodes.NoneNode()
            return nodes.ObjectInjectNode(None, type=object_)
Beispiel #5
0
 def _object_Pow(self, node):
     args = [node.left, node.right, nodes.ObjectInjectNode(None)]
     return self.visit(function_util.external_call(self.context,
                                                   self.llvm_module,
                                                   'PyNumber_Power',
                                                   args=args),
                       llvm_module=self.llvm_module)
Beispiel #6
0
    def visit_Slice(self, node):
        """
        Rewrite slice objects. Do this late in the pipeline so that other
        code can still recognize the code structure.
        """
        slice_values = [node.lower, node.upper, node.step]

        if self.nopython:
            raise error.NumbaError(node, "Cannot slice in nopython context")

        if node.variable.is_constant:
            return self.visit(
                nodes.ObjectInjectNode(node.variable.constant_value))

        bounds = []
        for node in slice_values:
            if node is None:
                bounds.append(nodes.NULL_obj)
            else:
                bounds.append(node)

        new_slice = function_util.external_call(self.context,
                                                self.llvm_module,
                                                'PySlice_New',
                                                args=bounds,
                                                temp_name='slice')
        return self.visit(new_slice)
Beispiel #7
0
    def _print(self, value, dest=None):
        signature, lfunc = self.context.external_library.declare(
            self.llvm_module, 'PyObject_CallMethod')

        if dest is None:
            dest = nodes.ObjectInjectNode(sys.stdout)

        value = function_util.external_call(self.context,
                                            self.llvm_module,
                                            "PyObject_Str",
                                            args=[value])
        args = [dest, nodes.ConstNode("write"), nodes.ConstNode("O"), value]
        return nodes.NativeCallNode(signature, args, lfunc)
Beispiel #8
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 #9
0
    def visit_ConstNode(self, node):
        constant = node.pyval

        if node.type.is_complex:
            real = nodes.ConstNode(constant.real, node.type.base_type)
            imag = nodes.ConstNode(constant.imag, node.type.base_type)
            node = nodes.ComplexNode(real, imag)

        elif node.type.is_pointer:
            addr_int = constnodes.get_pointer_address(constant, node.type)
            node = nodes.ptrfromint(addr_int, node.type)

        elif node.type.is_object and not nodes.is_null_constant(constant):
            node = nodes.ObjectInjectNode(constant, node.type)

        return node
Beispiel #10
0
    def visit_CoerceToObject(self, node):
        new_node = node

        node_type = node.node.type
        if node_type.is_bool:
            new_node = function_util.external_call(self.context,
                                                   self.llvm_module,
                                                   "PyBool_FromLong",
                                                   args=[node.node])
        elif node_type.is_numeric:
            cls = None
            args = node.node,
            if node_type.is_int:
                cls = self._get_int_conversion_func(node_type,
                                                    pyapi._from_long)
            elif node_type.is_float:
                cls = pyapi.PyFloat_FromDouble
            elif node_type.is_complex:
                cls = pyapi.PyComplex_FromDoubles
                complex_value = nodes.CloneableNode(node.node)
                args = [
                    nodes.ComplexAttributeNode(complex_value, "real"),
                    nodes.ComplexAttributeNode(complex_value.clone, "imag")
                ]
            else:
                raise error.NumbaError(
                    node,
                    "Don't know how to coerce type %r to PyObject" % node_type)

            if cls:
                new_node = function_util.external_call(self.context,
                                                       self.llvm_module,
                                                       cls.__name__,
                                                       args=args)
        elif node_type.is_pointer and not node_type.is_string():
            # Create ctypes pointer object
            ctypes_pointer_type = node_type.to_ctypes()
            args = [
                nodes.CoercionNode(node.node, int64),
                nodes.ObjectInjectNode(ctypes_pointer_type, object_)
            ]
            new_node = nodes.call_pyfunc(ctypes.cast, args)

        self.generic_visit(new_node)
        return new_node
Beispiel #11
0
    def register_array_expression(self, node, lhs=None):
        super(ArrayExpressionRewriteUfunc, self).register_array_expression(node,
                                                                           lhs)
        py_ufunc, signature, ufunc_builder = self.get_py_ufunc(lhs, node)

        # Vectorize Python function
        vectorizer = self.vectorizer_cls(py_ufunc)
        vectorizer.add(restype=signature.return_type, argtypes=signature.args)
        ufunc = vectorizer.build_ufunc()

        # Call ufunc
        args = ufunc_builder.operands
        if lhs is None:
            keywords = None
        else:
            keywords = [ast.keyword('out', lhs)]

        func = nodes.ObjectInjectNode(ufunc)
        call_ufunc = nodes.ObjectCallNode(signature=None, func=func, args=args,
                                          keywords=keywords, py_func=ufunc)
        return nodes.ObjectTempNode(call_ufunc)
Beispiel #12
0
def build_wrapper_function_ast(env, wrapper_lfunc, llvm_module):
    """
    Build AST for LLVM function wrapper.

        lfunc: LLVM function to wrap
        llvm_module: module the wrapper is being defined in

    The resulting AST has a NativeCallNode to the wrapped function. The
    arguments are  LLVMValueRefNode nodes which still need their llvm_value
    set to the object from the tuple. This happens in visit_FunctionWrapperNode
    during codegen.
    """
    func = env.crnt.func
    func_signature = env.crnt.func_signature
    func_name = env.crnt.func_name

    # Insert external declaration
    lfunc = llvm_module.get_or_insert_function(
        func_signature.to_llvm(env.context),
        env.crnt.lfunc.name)

    # Build AST
    wrapper = nodes.FunctionWrapperNode(lfunc,
                                        func_signature,
                                        func,
                                        fake_pyfunc,
                                        func_name)

    error_return = ast.Return(nodes.CoercionNode(nodes.NULL_obj,
                                                 object_))

    is_closure = bool(closures.is_closure_signature(func_signature))
    nargs = len(func_signature.args) - is_closure

    # Call wrapped function with unpacked object arguments
    # (delay actual arguments)
    args = [nodes.LLVMValueRefNode(object_, None)
                for i in range(nargs)]

    if is_closure:
        # Insert m_self as scope argument type
        closure_scope = get_closure_scope(func_signature, wrapper_lfunc.args[0])
        args.insert(0, closure_scope)

    func_call = nodes.NativeCallNode(func_signature, args, lfunc)

    if not is_obj(func_signature.return_type):
        # Check for error using PyErr_Occurred()
        func_call = nodes.PyErr_OccurredNode(func_call)

    # Coerce and return result
    if func_signature.return_type.is_void:
        wrapper.body = func_call
        result_node = nodes.ObjectInjectNode(None)
    else:
        wrapper.body = None
        result_node = func_call

    wrapper.return_result = ast.Return(value=nodes.CoercionNode(result_node,
                                                                object_))

    # Update wrapper
    wrapper.error_return = error_return
    wrapper.cellvars = []

    wrapper.wrapped_nargs = nargs
    wrapper.wrapped_args = args[is_closure:]

    return wrapper