Example #1
0
def make_intrinsic(intrinsic):
    """
    Create an intrinsic function given an Intrinsic.
    """
    if intrinsic in cache:
        return cache[intrinsic]

    # NOTE: don't use numba.jit() and 'exec', it will make inspect.getsource()
    # NOTE: fail, and hence won't work in python 2.6 (since meta doesn't work
    # NOTE: there)

    # Build argument names
    nargs = len(intrinsic.func_signature.args)
    assert nargs < len(string.ascii_letters)
    argnames = ", ".join(string.ascii_letters[:nargs])

    # Build source code and environment
    args = (intrinsic.name, argnames, argnames)
    source = ("def %s(%s): return intrinsic(%s)\n" % args)
    func_globals = {'intrinsic': intrinsic}

    mod_ast = ast.parse(source)
    func_ast = mod_ast.body[0]

    # Compile
    func_env, _ = pipeline.run_pipeline2(
        env, func=None, func_ast=func_ast,
        func_signature=intrinsic.func_signature,
        function_globals=func_globals)
    jitted_func = func_env.numba_wrapper_func

    # Populate cache
    cache[intrinsic] = jitted_func
    return jitted_func
Example #2
0
def cf_from_source(source, func_globals):
    "Render the SSA graph given python source code"
    from numba import pipeline
    from numba import environment

    mod = ast.parse(source)
    func_ast = mod.body[0]

    env = environment.NumbaEnvironment.get_environment()
    func_env, _ = pipeline.run_pipeline2(
        env, None, func_ast, void(), pipeline_name="cf", function_globals=dict(func_globals)
    )
    return func_env.symtab, func_env.flow  # func_env.cfg
Example #3
0
def cf_from_source(source, func_globals):
    "Render the SSA graph given python source code"
    from numba import pipeline
    from numba import environment

    mod = ast.parse(source)
    func_ast = mod.body[0]

    env = environment.NumbaEnvironment.get_environment()
    func_env, _ = pipeline.run_pipeline2(env,
                                         None,
                                         func_ast,
                                         void(),
                                         pipeline_name='cf',
                                         function_globals=dict(func_globals))
    return func_env.symtab, func_env.flow  #func_env.cfg
Example #4
0
def infer(func, signature=functype(), warn=True, **kwargs):
    func_ast = functions._get_ast(func)
    env = environment.NumbaEnvironment.get_environment(kwargs.get('env', None))
    infer_pipe = env.get_or_add_pipeline('infer', construct_infer_pipeline)
    kwargs.update(warn=warn, pipeline_name='infer')
    pipe, (signature, symtab, func_ast) = pipeline.run_pipeline2(
        env, func, func_ast, signature, **kwargs)
    last_block = func_ast.flow.blocks[-2]
    symbols = {}
    #for block in ast.flow.blocks: print block.symtab
    for var_name, var in symtab.iteritems():
        if not var.parent_var and not var.is_constant:
            var = lookup(last_block, var_name)
            if var:
                symbols[var_name] = var

    return signature, symbols
def infer(func, signature=functype(), warn=True, **kwargs):
    func_ast = functions._get_ast(func)
    env = environment.NumbaEnvironment.get_environment(kwargs.get('env', None))
    infer_pipe = env.get_or_add_pipeline('infer', construct_infer_pipeline)
    kwargs.update(warn=warn, pipeline_name='infer')
    pipe, (signature, symtab, func_ast) = pipeline.run_pipeline2(
        env, func, func_ast, signature, **kwargs)
    last_block = func_ast.flow.blocks[-2]
    symbols = {}
    #for block in ast.flow.blocks: print block.symtab
    for var_name, var in symtab.iteritems():
        if not var.parent_var and not var.is_constant:
            var = lookup(last_block, var_name)
            if var:
                symbols[var_name] = var

    return signature, symbols
Example #6
0
    def register_array_expression(self, node, lhs=None):
        super(ArrayExpressionRewriteNative, self).register_array_expression(
            node, lhs)

        # llvm_module = llvm.core.Module.new(temp_name("array_expression_module"))
        # llvm_module = self.env.llvm_context.module

        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 = get_py_ufunc_ast(self.env, lhs, node)

        # Compile ufunc scalar kernel with numba
        ast.fix_missing_locations(ufunc_ast)
        # func_env = self.env.crnt.inherit(
        #     func=None, ast=ufunc_ast, func_signature=signature,
        #     wrap=False, #link=False, #llvm_module=llvm_module,
        # )
        # pipeline.run_env(self.env, func_env) #, pipeline_name='codegen')

        func_env, (_, _, _) = pipeline.run_pipeline2(
            self.env, None, ufunc_ast, signature,
            function_globals=self.env.crnt.function_globals,
            wrap=False, link=False, nopython=True,
            #llvm_module=llvm_module, # pipeline_name='codegen',
        )
        llvm_module = func_env.llvm_module

        operands = ufunc_builder.operands
        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 = NumbaStaticArgsContext()
        context.llvm_module = llvm_module
        # context.llvm_ee = self.env.llvm_context.execution_engine

        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(func_env.lfunc.name, signature,
                                           miniargs, b)

        minikernel = b.function_from_numpy(
            temp_name("array_expression"), body, miniargs)
        lminikernel, = context.run_simple(minikernel,
                                          specializers.StridedSpecializer)
        # lminikernel.linkage = llvm.core.LINKAGE_LINKONCE_ODR

        # pipeline.run_env(self.env, func_env, pipeline_name='post_codegen')
        # llvm_module.verify()
        del func_env

        assert lminikernel.module is llvm_module
        # print("---------")
        # print(llvm_module)
        # print("~~~~~~~~~~~~")
        lminikernel = self.env.llvm_context.link(lminikernel)

        # 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)
Example #7
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)