Пример #1
0
def _create_methoddef(py_func, func_name, func_doc, func_pointer):
    # struct PyMethodDef {
    #     const char  *ml_name;   /* The name of the built-in function/method */
    #     PyCFunction  ml_meth;   /* The C function that implements it */
    #     int      ml_flags;      /* Combination of METH_xxx flags, which mostly
    #                                describe the args expected by the C func */
    #     const char  *ml_doc;    /* The __doc__ attribute, or NULL */
    # };
    PyMethodDef = struct([('name', c_string_type),
                          ('method', void.pointer()),
                          ('flags', int_),
                          ('doc', c_string_type)])
    c_PyMethodDef = PyMethodDef.to_ctypes()

    PyCFunction_NewEx = ctypes.pythonapi.PyCFunction_NewEx
    PyCFunction_NewEx.argtypes = [ctypes.POINTER(c_PyMethodDef),
                                  ctypes.py_object,
                                  ctypes.c_void_p]
    PyCFunction_NewEx.restype = ctypes.py_object

    # It is paramount to put these into variables first, since every
    # access may return a new string object!
    keep_alive(py_func, func_name)
    keep_alive(py_func, func_doc)

    methoddef = c_PyMethodDef()
    methoddef.name = func_name
    methoddef.doc = func_doc
    methoddef.method = ctypes.c_void_p(func_pointer)
    methoddef.flags = 1 # METH_VARARGS

    return methoddef
Пример #2
0
    def keep_alive(self, obj):
        """
        Keep an object alive for the lifetime of the translated unit.

        This is a HACK. Make live objects part of the function-cache
        """
        functions.keep_alive(self.func, obj)
Пример #3
0
    def keep_alive(self, obj):
        """
        Keep an object alive for the lifetime of the translated unit.

        This is a HACK. Make live objects part of the function-cache
        """
        functions.keep_alive(self.func, obj)
Пример #4
0
def numbafunction_new(py_func, func_name, func_doc, module_name, func_pointer,
                      wrapped_lfunc_pointer, wrapped_signature):
    methoddef = _create_methoddef(py_func, func_name, func_doc, func_pointer)
    keep_alive(py_func, methoddef)
    keep_alive(py_func, module_name)

    wrapper = extension_types.create_function(methoddef, py_func,
                                              wrapped_lfunc_pointer,
                                              wrapped_signature, module_name)
    return methoddef, wrapper
Пример #5
0
    def codegen(self, codegen):
        func_env = self.env.translation.crnt

        dependencies = codegen.visitlist(self.dependencies)
        cdef = self.cbuilder_cdefinition(self.dependencies, dependencies)

        self.lfunc = cdef.define(func_env.llvm_module) #, optimize=False)
        functions.keep_alive(func_env.func, self.lfunc)

        return self.lfunc
Пример #6
0
    def codegen(self, codegen):
        func_env = self.env.translation.crnt

        dependencies = codegen.visitlist(self.dependencies)
        cdef = self.cbuilder_cdefinition(self.dependencies, dependencies)

        self.lfunc = cdef.define(func_env.llvm_module) #, optimize=False)
        functions.keep_alive(func_env.func, self.lfunc)

        return self.lfunc
Пример #7
0
def numbafunction_new(
    py_func, func_name, func_doc, module_name, func_pointer, wrapped_lfunc_pointer, wrapped_signature
):
    "Create a NumbaFunction (numbafunction.c)"
    methoddef = _create_methoddef(py_func, func_name, func_doc, func_pointer)

    keep_alive(py_func, methoddef)
    keep_alive(py_func, module_name)

    wrapper = numbawrapper.create_function(methoddef, py_func, wrapped_lfunc_pointer, wrapped_signature, module_name)
    return methoddef, wrapper
Пример #8
0
def numbafunction_new(py_func, func_name, func_doc, module_name, func_pointer,
                      wrapped_lfunc_pointer, wrapped_signature):
    "Create a NumbaFunction (numbafunction.c)"
    methoddef = _create_methoddef(py_func, func_name, func_doc, func_pointer)

    keep_alive(py_func, methoddef)
    keep_alive(py_func, module_name)

    wrapper = numbawrapper.create_function(methoddef, py_func,
                                           wrapped_lfunc_pointer,
                                           wrapped_signature, module_name)
    return methoddef, wrapper
Пример #9
0
def _create_methoddef(py_func, func_name, func_doc, func_pointer):
    """
    Create a PyMethodDef ctypes struct.

    struct PyMethodDef {
         const char  *ml_name;   /* The name of the built-in function/method */
         PyCFunction  ml_meth;   /* The C function that implements it */
         int      ml_flags;      /* Combination of METH_xxx flags, which mostly
                                    describe the args expected by the C func */
         const char  *ml_doc;    /* The __doc__ attribute, or NULL */
    };
    """
    PyMethodDef = struct([('name',   char.pointer()),
                          ('method', void.pointer()),
                          ('flags',  int_),
                          ('doc',    char.pointer())])
    c_PyMethodDef = PyMethodDef.to_ctypes()

    PyCFunction_NewEx = ctypes.pythonapi.PyCFunction_NewEx
    PyCFunction_NewEx.argtypes = [ctypes.POINTER(c_PyMethodDef),
                                  ctypes.py_object,
                                  ctypes.c_void_p]
    PyCFunction_NewEx.restype = ctypes.py_object

    # It is paramount to put these into variables first, since every
    # access may return a new string object!
    keep_alive(py_func, func_name)
    keep_alive(py_func, func_doc)

    methoddef = c_PyMethodDef()
    if PY3:
        if func_name is not None:
            func_name = func_name.encode('utf-8')
        if func_doc is not None:
            func_doc = func_doc.encode('utf-8')

    methoddef.name = func_name
    methoddef.doc = func_doc
    methoddef.method = ctypes.c_void_p(func_pointer)
    methoddef.flags = 1 # METH_VARARGS

    return methoddef
Пример #10
0
def build_wrapper_translation(env, llvm_module=None):
    """
    Generate a wrapper function in the given llvm module.
    """
    from numba import pipeline

    if llvm_module:
        wrapper_module = llvm_module
    else:
        wrapper_module = env.llvm_context.module

    # Create wrapper code generator and wrapper AST
    func_name = '__numba_wrapper_%s' % env.crnt.func_name
    signature = object_(void.pointer(), object_)
    symtab = dict(self=Variable(object_, is_local=True),
                  args=Variable(object_, is_local=True))

    func_env = env.crnt.inherit(
            func=fake_pyfunc,
            name=func_name,
            mangled_name=None, # Force FunctionEnvironment.init()
                               # to generate a new mangled name.
            func_signature=signature,
            locals={},
            symtab=symtab,
            refcount_args=False,
            llvm_module=wrapper_module)

    # Create wrapper LLVM function
    func_env.lfunc = pipeline.get_lfunc(env, func_env)

    # Build wrapper ast
    wrapper_node = build_wrapper_function_ast(env,
                                              wrapper_lfunc=func_env.lfunc,
                                              llvm_module=wrapper_module)
    func_env.ast = wrapper_node

    # Specialize and compile wrapper
    pipeline.run_env(env, func_env, pipeline_name='late_translate')
    keep_alive(fake_pyfunc, func_env.lfunc)

    return func_env.translator # TODO: Amend callers to eat func_env
Пример #11
0
def _create_methoddef(py_func, func_name, func_doc, func_pointer):
    """
    Create a PyMethodDef ctypes struct.

    struct PyMethodDef {
         const char  *ml_name;   /* The name of the built-in function/method */
         PyCFunction  ml_meth;   /* The C function that implements it */
         int      ml_flags;      /* Combination of METH_xxx flags, which mostly
                                    describe the args expected by the C func */
         const char  *ml_doc;    /* The __doc__ attribute, or NULL */
    };
    """
    PyMethodDef = struct([("name", c_string_type), ("method", void.pointer()), ("flags", int_), ("doc", c_string_type)])
    c_PyMethodDef = PyMethodDef.to_ctypes()

    PyCFunction_NewEx = ctypes.pythonapi.PyCFunction_NewEx
    PyCFunction_NewEx.argtypes = [ctypes.POINTER(c_PyMethodDef), ctypes.py_object, ctypes.c_void_p]
    PyCFunction_NewEx.restype = ctypes.py_object

    # It is paramount to put these into variables first, since every
    # access may return a new string object!
    keep_alive(py_func, func_name)
    keep_alive(py_func, func_doc)

    methoddef = c_PyMethodDef()
    if PY3:
        if func_name is not None:
            func_name = func_name.encode("utf-8")
        if func_doc is not None:
            func_doc = func_doc.encode("utf-8")

    methoddef.name = func_name
    methoddef.doc = func_doc
    methoddef.method = ctypes.c_void_p(func_pointer)
    methoddef.flags = 1  # METH_VARARGS

    return methoddef
Пример #12
0
    def register_array_expression(self, node, lhs=None):
        super(ArrayExpressionRewriteNative, self).register_array_expression(
            node, lhs)

        lhs_type = lhs.type if lhs else node.type
        is_expr = lhs is None

        if node.type.is_array and lhs_type.ndim < node.type.ndim:
            # TODO: this is valid in NumPy if the leading dimensions of the
            # TODO: RHS have extent 1
            raise error.NumbaError(
                node, "Right hand side must have a "
                      "dimensionality <= %d" % lhs_type.ndim)

        # Create ufunc scalar kernel
        ufunc_ast, signature, ufunc_builder = self.get_py_ufunc_ast(lhs, node)
        signature.struct_by_reference = True

        # Compile ufunc scalar kernel with numba
        ast.fix_missing_locations(ufunc_ast)
        func_env, (_, _, _) = pipeline.run_pipeline2(
            self.env, None, ufunc_ast, signature,
            function_globals={},
        )

        # Manual linking
        lfunc = func_env.lfunc

        # print lfunc
        operands = ufunc_builder.operands
        functions.keep_alive(self.func, lfunc)

        operands = [nodes.CloneableNode(operand) for operand in operands]

        if lhs is not None:
            lhs = nodes.CloneableNode(lhs)
            broadcast_operands = [lhs] + operands
            lhs = lhs.clone
        else:
            broadcast_operands = operands[:]

        shape = slicenodes.BroadcastNode(lhs_type, broadcast_operands)
        operands = [op.clone for op in operands]

        if lhs is None and self.nopython:
            raise error.NumbaError(
                node, "Cannot allocate new memory in nopython context")
        elif lhs is None:
            # TODO: determine best output order at runtime
            shape = shape.cloneable
            lhs = nodes.ArrayNewEmptyNode(lhs_type, shape.clone,
                                          lhs_type.is_f_contig).cloneable

        # Build minivect wrapper kernel
        context = NumbaproStaticArgsContext()
        context.llvm_module = self.env.llvm_context.module
        # context.debug = True
        context.optimize_broadcasting = False
        b = context.astbuilder

        variables = [b.variable(name_node.type, "op%d" % i)
                     for i, name_node in enumerate([lhs] + operands)]
        miniargs = [b.funcarg(variable) for variable in variables]
        body = miniutils.build_kernel_call(lfunc.name, signature, miniargs, b)

        minikernel = b.function_from_numpy(
            templating.temp_name("array_expression"), body, miniargs)
        lminikernel, ctypes_kernel = context.run_simple(
            minikernel, specializers.StridedSpecializer)

        # Build call to minivect kernel
        operands.insert(0, lhs)
        args = [shape]
        scalar_args = []
        for operand in operands:
            if operand.type.is_array:
                data_p = self.array_attr(operand, 'data')
                data_p = nodes.CoercionNode(data_p,
                                            operand.type.dtype.pointer())
                if not isinstance(operand, nodes.CloneNode):
                    operand = nodes.CloneNode(operand)
                strides_p = self.array_attr(operand, 'strides')
                args.extend((data_p, strides_p))
            else:
                scalar_args.append(operand)

        args.extend(scalar_args)
        result = nodes.NativeCallNode(minikernel.type, args, lminikernel)

        # Use native slicing in array expressions
        slicenodes.mark_nopython(ast.Suite(body=result.args))

        if not is_expr:
            # a[:] = b[:] * c[:]
            return result

        # b[:] * c[:], return new array as expression
        return nodes.ExpressionNode(stmts=[result], expr=lhs.clone)