Ejemplo n.º 1
0
def cprint_lower(context, builder, sig, args):
    from sdc.str_ext import string_type, char_type

    for i, val in enumerate(args):
        typ = sig.args[i]
        if typ == string_type:
            fnty = lir.FunctionType(lir.VoidType(),
                                    [lir.IntType(8).as_pointer()])
            fn = builder.module.get_or_insert_function(fnty, name="print_str")
            builder.call(fn, [val])
            cgutils.printf(builder, " ")
            continue
        if typ == char_type:
            fnty = lir.FunctionType(lir.VoidType(), [lir.IntType(8)])
            fn = builder.module.get_or_insert_function(fnty, name="print_char")
            builder.call(fn, [val])
            cgutils.printf(builder, " ")
            continue
        if isinstance(typ, types.ArrayCTypes):
            cgutils.printf(builder, "%p ", val)
            continue
        format_str = typ_to_format[typ]
        cgutils.printf(builder, "%{} ".format(format_str), val)
    cgutils.printf(builder, "\n")
    return context.get_dummy_value()
Ejemplo n.º 2
0
def _define_nrt_incref(module, atomic_incr):
    """
    Implement NRT_incref in the module
    """
    fn_incref = module.get_or_insert_function(incref_decref_ty, name="NRT_incref")
    # Cannot inline this for refcount pruning to work
    fn_incref.attributes.add("noinline")
    builder = ir.IRBuilder(fn_incref.append_basic_block())
    [ptr] = fn_incref.args
    is_null = builder.icmp_unsigned("==", ptr, cgutils.get_null_value(ptr.type))
    with cgutils.if_unlikely(builder, is_null):
        builder.ret_void()

    if _debug_print:
        cgutils.printf(builder, "*** NRT_Incref %zu [%p]\n", builder.load(ptr), ptr)
    builder.call(atomic_incr, [builder.bitcast(ptr, atomic_incr.args[0].type)])
    builder.ret_void()
Ejemplo n.º 3
0
def _define_nrt_decref(module, atomic_decr):
    """
    Implement NRT_decref in the module
    """
    fn_decref = cgutils.get_or_insert_function(module, incref_decref_ty,
                                               "NRT_decref")
    # Cannot inline this for refcount pruning to work
    fn_decref.attributes.add('noinline')
    calldtor = ir.Function(module,
                           ir.FunctionType(ir.VoidType(), [_pointer_type]),
                           name="NRT_MemInfo_call_dtor")

    builder = ir.IRBuilder(fn_decref.append_basic_block())
    [ptr] = fn_decref.args
    is_null = builder.icmp_unsigned("==", ptr,
                                    cgutils.get_null_value(ptr.type))
    with cgutils.if_unlikely(builder, is_null):
        builder.ret_void()

    # For memory fence usage, see https://llvm.org/docs/Atomics.html

    # A release fence is used before the relevant write operation.
    # No-op on x86.  On POWER, it lowers to lwsync.
    builder.fence("release")

    word_ptr = builder.bitcast(ptr, atomic_decr.args[0].type)

    if config.DEBUG_NRT:
        cgutils.printf(builder, "*** NRT_Decref %zu [%p]\n",
                       builder.load(word_ptr), ptr)
    newrefct = builder.call(atomic_decr, [word_ptr])

    refct_eq_0 = builder.icmp_unsigned("==", newrefct,
                                       ir.Constant(newrefct.type, 0))
    with cgutils.if_unlikely(builder, refct_eq_0):
        # An acquire fence is used after the relevant read operation.
        # No-op on x86.  On POWER, it lowers to lwsync.
        builder.fence("acquire")
        builder.call(calldtor, [ptr])
    builder.ret_void()
Ejemplo n.º 4
0
def init_gdb_codegen(cgctx,
                     builder,
                     signature,
                     args,
                     const_args,
                     do_break=False):

    int8_t = ir.IntType(8)
    int32_t = ir.IntType(32)
    intp_t = ir.IntType(utils.MACHINE_BITS)
    char_ptr = ir.PointerType(ir.IntType(8))
    zero_i32t = int32_t(0)

    mod = builder.module
    pid = cgutils.alloca_once(builder, int32_t, size=1)

    # 32bit pid, 11 char max + terminator
    pidstr = cgutils.alloca_once(builder, int8_t, size=12)

    # str consts
    intfmt = cgctx.insert_const_string(mod, '%d')
    gdb_str = cgctx.insert_const_string(mod, config.GDB_BINARY)
    attach_str = cgctx.insert_const_string(mod, 'attach')

    new_args = []
    # add break point command to known location
    # this command file thing is due to commands attached to a breakpoint
    # requiring an interactive prompt
    # https://sourceware.org/bugzilla/show_bug.cgi?id=10079
    new_args.extend(['-x', os.path.join(_path, 'cmdlang.gdb')])
    # issue command to continue execution from sleep function
    new_args.extend(['-ex', 'c'])
    # then run the user defined args if any
    new_args.extend([x.literal_value for x in const_args])
    cmdlang = [cgctx.insert_const_string(mod, x) for x in new_args]

    # insert getpid, getpid is always successful, call without concern!
    fnty = ir.FunctionType(int32_t, tuple())
    getpid = mod.get_or_insert_function(fnty, "getpid")

    # insert snprintf
    # int snprintf(char *str, size_t size, const char *format, ...);
    fnty = ir.FunctionType(int32_t, (char_ptr, intp_t, char_ptr), var_arg=True)
    snprintf = mod.get_or_insert_function(fnty, "snprintf")

    # insert fork
    fnty = ir.FunctionType(int32_t, tuple())
    fork = mod.get_or_insert_function(fnty, "fork")

    # insert execl
    fnty = ir.FunctionType(int32_t, (char_ptr, char_ptr), var_arg=True)
    execl = mod.get_or_insert_function(fnty, "execl")

    # insert sleep
    fnty = ir.FunctionType(int32_t, (int32_t, ))
    sleep = mod.get_or_insert_function(fnty, "sleep")

    # insert break point
    fnty = ir.FunctionType(ir.VoidType(), tuple())
    breakpoint = mod.get_or_insert_function(fnty, "numba_gdb_breakpoint")

    # do the work
    parent_pid = builder.call(getpid, tuple())
    builder.store(parent_pid, pid)
    pidstr_ptr = builder.gep(pidstr, [zero_i32t], inbounds=True)
    pid_val = builder.load(pid)

    # call snprintf to write the pid into a char *
    stat = builder.call(snprintf, (pidstr_ptr, intp_t(12), intfmt, pid_val))
    invalid_write = builder.icmp_signed('>', stat, int32_t(12))
    with builder.if_then(invalid_write, likely=False):
        msg = "Internal error: `snprintf` buffer would have overflowed."
        cgctx.call_conv.return_user_exc(builder, RuntimeError, (msg, ))

    # fork, check pids etc
    child_pid = builder.call(fork, tuple())
    fork_failed = builder.icmp_signed('==', child_pid, int32_t(-1))
    with builder.if_then(fork_failed, likely=False):
        msg = "Internal error: `fork` failed."
        cgctx.call_conv.return_user_exc(builder, RuntimeError, (msg, ))

    is_child = builder.icmp_signed('==', child_pid, zero_i32t)
    with builder.if_else(is_child) as (then, orelse):
        with then:
            # is child
            nullptr = ir.Constant(char_ptr, None)
            gdb_str_ptr = builder.gep(gdb_str, [zero_i32t], inbounds=True)
            attach_str_ptr = builder.gep(attach_str, [zero_i32t],
                                         inbounds=True)
            cgutils.printf(builder, "Attaching to PID: %s\n", pidstr)
            buf = (gdb_str_ptr, gdb_str_ptr, attach_str_ptr, pidstr_ptr)
            buf = buf + tuple(cmdlang) + (nullptr, )
            builder.call(execl, buf)
        with orelse:
            # is parent
            builder.call(sleep, (int32_t(10), ))
            # if breaking is desired, break now
            if do_break is True:
                builder.call(breakpoint, tuple())
Ejemplo n.º 5
0
def make_wrapper(fname,
                 atypes,
                 rtype,
                 cres,
                 target: TargetInfo,
                 verbose=False):
    """Make wrapper function to numba compile result.

    The compilation result contains a function with prototype::

      <status> <function name>(<rtype>** result, <arguments>)

    The make_wrapper adds a wrapper function to compilation result
    library with the following prototype::

      <rtype> <fname>(<arguments>)

    or, if <rtype>.return_as_first_argument == True, then

      void <fname>(<rtype>* <arguments>)

    Parameters
    ----------
    fname : str
      Function name.
    atypes : tuple
      A tuple of argument Numba types.
    rtype : numba.Type
      The return Numba type
    cres : CompileResult
      Numba compilation result.
    verbose: bool
      When True, insert printf statements for debugging errors. For
      CUDA target this feature is disabled.

    """
    fndesc = cres.fndesc
    module = cres.library.create_ir_module(fndesc.unique_name)
    context = cres.target_context
    ll_argtypes = [context.get_value_type(ty) for ty in atypes]
    ll_return_type = context.get_value_type(rtype)

    return_as_first_argument = getattr(rtype, 'return_as_first_argument',
                                       False)
    assert isinstance(return_as_first_argument, bool)
    if return_as_first_argument:
        wrapty = ir.FunctionType(ir.VoidType(), [ll_return_type] + ll_argtypes)
        wrapfn = ir.Function(module, wrapty, fname)
        builder = ir.IRBuilder(wrapfn.append_basic_block('entry'))
        fnty = context.call_conv.get_function_type(rtype, atypes)
        fn = ir.Function(builder.module, fnty, cres.fndesc.llvm_func_name)
        status, out = context.call_conv.call_function(builder, fn, rtype,
                                                      atypes, wrapfn.args[1:])
        with cgutils.if_unlikely(builder, status.is_error):
            if verbose and target.is_cpu:
                cgutils.printf(builder,
                               f"rbc: {fname} failed with status code %i\n",
                               status.code)
                externals.stdio._cg_fflush(builder)
            builder.ret_void()
        builder.store(builder.load(out), wrapfn.args[0])
        builder.ret_void()
    else:
        wrapty = ir.FunctionType(ll_return_type, ll_argtypes)
        wrapfn = ir.Function(module, wrapty, fname)
        builder = ir.IRBuilder(wrapfn.append_basic_block('entry'))
        fnty = context.call_conv.get_function_type(rtype, atypes)
        fn = ir.Function(builder.module, fnty, cres.fndesc.llvm_func_name)
        status, out = context.call_conv.call_function(builder, fn, rtype,
                                                      atypes, wrapfn.args)
        if verbose and target.is_cpu:
            with cgutils.if_unlikely(builder, status.is_error):
                cgutils.printf(builder,
                               f"rbc: {fname} failed with status code %i\n",
                               status.code)
                externals.stdio._cg_fflush(builder)
        builder.ret(out)

    cres.library.add_ir_module(module)
Ejemplo n.º 6
0
 def codegen(context, builder, signature, args):
     target_info = TargetInfo()
     if target_info.is_cpu:
         cgutils.printf(builder, format_type.literal_value, *args[1:])
         _cg_fflush(builder)
Ejemplo n.º 7
0
 def codegen(context, builder, signature, args):
     cgutils.printf(builder, format_type.literal_value, *args[1:])
Ejemplo n.º 8
0
def make_wrapper(fname, atypes, rtype, cres):
    """Make wrapper function to numba compile result.

    The compilation result contains a function with prototype::

      <status> <function name>(<rtype>** result, <arguments>)

    The make_wrapper adds a wrapper function to compilation result
    library with the following prototype::

      <rtype> <fname>(<arguments>)

    or, if <rtype> is Omnisci Array, then

      void <fname>(<rtype>* <arguments>)

    Parameters
    ----------
    fname : str
      Function name.
    atypes : tuple
      A tuple of argument Numba types.
    rtype : numba.Type
      The return Numba type
    cres : CompileResult
      Numba compilation result.

    """
    fndesc = cres.fndesc
    module = cres.library.create_ir_module(fndesc.unique_name)
    context = cres.target_context
    ll_argtypes = [context.get_value_type(ty) for ty in atypes]
    ll_return_type = context.get_value_type(rtype)

    # TODO: design a API for custom wrapping
    if type(rtype).__name__ == 'ArrayPointer':
        wrapty = ir.FunctionType(ir.VoidType(), [ll_return_type] + ll_argtypes)
        wrapfn = module.add_function(wrapty, fname)
        builder = ir.IRBuilder(wrapfn.append_basic_block('entry'))
        fnty = context.call_conv.get_function_type(rtype, atypes)
        fn = builder.module.add_function(fnty, cres.fndesc.llvm_func_name)
        status, out = context.call_conv.call_function(builder, fn, rtype,
                                                      atypes, wrapfn.args[1:])
        with cgutils.if_unlikely(builder, status.is_error):
            cgutils.printf(builder,
                           f"rbc: {fname} failed with status code %i\n",
                           status.code)
            builder.ret_void()
        builder.store(builder.load(out), wrapfn.args[0])
        builder.ret_void()
    else:
        wrapty = ir.FunctionType(ll_return_type, ll_argtypes)
        wrapfn = module.add_function(wrapty, fname)
        builder = ir.IRBuilder(wrapfn.append_basic_block('entry'))
        fnty = context.call_conv.get_function_type(rtype, atypes)
        fn = builder.module.add_function(fnty, cres.fndesc.llvm_func_name)
        status, out = context.call_conv.call_function(builder, fn, rtype,
                                                      atypes, wrapfn.args)
        with cgutils.if_unlikely(builder, status.is_error):
            cgutils.printf(builder,
                           f"rbc: {fname} failed with status code %i\n",
                           status.code)
        builder.ret(out)

    cres.library.add_ir_module(module)