Exemplo n.º 1
0
    def __init__(self, context, library, fndesc, interp):
        self.context = context
        self.library = library
        self.fndesc = fndesc
        self.blocks = utils.SortedMap(utils.iteritems(interp.blocks))
        self.interp = interp
        self.call_conv = context.call_conv

        # Initialize LLVM
        self.module = self.library.create_ir_module(self.fndesc.unique_name)

        # Python execution environment (will be available to the compiled
        # function).
        self.env = _dynfunc.Environment(
            globals=self.fndesc.lookup_module().__dict__)

        # Setup function
        self.function = context.declare_function(self.module, fndesc)
        self.entry_block = self.function.append_basic_block('entry')
        self.builder = Builder.new(self.entry_block)
        self.call_helper = self.call_conv.init_call_helper(self.builder)

        # Internal states
        self.blkmap = {}
        self.varmap = {}
        self.firstblk = min(self.blocks.keys())
        self.loc = -1

        # Subclass initialization
        self.init()
Exemplo n.º 2
0
    def __init__(self, func):
        func = get_function_object(func)
        code = get_code_object(func)
        if not code:
            raise ByteCodeSupportError("%s does not provide its bytecode" %
                                       func)
        if code.co_cellvars:
            raise ByteCodeSupportError("does not support cellvars")

        table = utils.SortedMap(ByteCodeIter(code))
        labels = set(dis.findlabels(code.co_code))
        labels.add(0)

        try:
            func_qualname = func.__qualname__
        except AttributeError:
            func_qualname = func.__name__

        self._mark_lineno(table, code)
        super(ByteCode, self).__init__(func=func,
                                       func_qualname=func_qualname,
                                       argspec=inspect.getargspec(func),
                                       filename=code.co_filename,
                                       co_names=code.co_names,
                                       co_varnames=code.co_varnames,
                                       co_consts=code.co_consts,
                                       co_freevars=code.co_freevars,
                                       table=table,
                                       labels=list(sorted(labels)))
Exemplo n.º 3
0
 def _compute_used_globals(cls, func, table, co_consts, co_names):
     """
     Compute the globals used by the function with the given
     bytecode table.
     """
     d = {}
     globs = func.__globals__
     builtins = globs['__builtins__']
     if isinstance(builtins, ModuleType):
         builtins = builtins.__dict__
     # Look for LOAD_GLOBALs in the bytecode
     for inst in table.values():
         if inst.opname == 'LOAD_GLOBAL':
             name = co_names[inst.arg]
             if name not in d:
                 try:
                     value = globs[name]
                 except KeyError:
                     value = builtins[name]
                 d[name] = value
     # Add globals used by any nested code object
     for co in co_consts:
         if isinstance(co, CodeType):
             subtable = utils.SortedMap(ByteCodeIter(co))
             d.update(
                 cls._compute_used_globals(func, subtable, co.co_consts,
                                           co.co_names))
     return d
Exemplo n.º 4
0
    def __init__(self, func):
        func = get_function_object(func)
        code = get_code_object(func)
        pysig = utils.pysignature(func)
        if not code:
            raise errors.ByteCodeSupportError(
                "%s does not provide its bytecode" % func)
        if code.co_cellvars:
            raise NotImplementedError("cell vars are not supported")

        table = utils.SortedMap(ByteCodeIter(code))
        labels = set(dis.findlabels(code.co_code))
        labels.add(0)

        try:
            func_qualname = func.__qualname__
        except AttributeError:
            func_qualname = func.__name__

        self._mark_lineno(table, code)
        super(ByteCode, self).__init__(func=func,
                                       func_qualname=func_qualname,
                                       is_generator=inspect.isgeneratorfunction(func),
                                       pysig=pysig,
                                       filename=code.co_filename,
                                       co_names=code.co_names,
                                       co_varnames=code.co_varnames,
                                       co_consts=code.co_consts,
                                       co_freevars=code.co_freevars,
                                       table=table,
                                       labels=list(sorted(labels)))
Exemplo n.º 5
0
def describe_function(interp, typemap, restype, calltypes):
    fname, pymod, doc, args, kws = _describe(interp)
    native = True
    sortedblocks = utils.SortedMap(utils.dict_iteritems(interp.blocks))
    fd = FunctionDescriptor(native, pymod, fname, doc, sortedblocks, typemap,
                            restype, calltypes, args, kws)
    return fd
Exemplo n.º 6
0
def make_loop_bytecode(bytecode, loop, args, returns):
    # Add return None
    co_consts = tuple(bytecode.co_consts)
    if None not in co_consts:
        co_consts += (None, )

    if returns:
        for out in returns:
            # Load output
            loadfast = ByteCodeInst.get(loop[-1].next, "LOAD_FAST",
                                        bytecode.co_varnames.index(out))
            loadfast.lineno = loop[-1].lineno
            loop.append(loadfast)

        # Build tuple
        buildtuple = ByteCodeInst.get(loop[-1].next, "BUILD_TUPLE",
                                      len(returns))
        buildtuple.lineno = loop[-1].lineno
        loop.append(buildtuple)

    else:
        # Load None
        load_none = ByteCodeInst.get(loop[-1].next, "LOAD_CONST",
                                     co_consts.index(None))
        load_none.lineno = loop[-1].lineno
        loop.append(load_none)

    # Return TOS
    return_value = ByteCodeInst.get(loop[-1].next, "RETURN_VALUE", 0)
    return_value.lineno = loop[-1].lineno
    loop.append(return_value)

    # Function name
    loop_qualname = bytecode.func_qualname + ".__numba__loop%d__" % loop[
        0].offset

    # Argspec
    argspectype = type(bytecode.argspec)
    argspec = argspectype(args=args, varargs=(), keywords=(), defaults=())

    # Code table
    codetable = utils.SortedMap((i.offset, i) for i in loop)

    # Custom bytecode object
    lbc = CustomByteCode(
        func=bytecode.func,
        func_qualname=loop_qualname,
        # Enforced in separate_loops()
        is_generator=False,
        argspec=argspec,
        filename=bytecode.filename,
        co_names=bytecode.co_names,
        co_varnames=bytecode.co_varnames,
        co_consts=co_consts,
        co_freevars=bytecode.co_freevars,
        table=codetable,
        labels=bytecode.labels)

    return lbc
Exemplo n.º 7
0
def describe_pyfunction(interp):
    fname, pymod, doc, args, kws = _describe(interp)
    defdict = lambda: defaultdict(lambda: types.pyobject)
    typemap = defdict()
    restype = types.pyobject
    calltypes = defdict()
    native = False
    sortedblocks = utils.SortedMap(utils.dict_iteritems(interp.blocks))
    fd = FunctionDescriptor(native, pymod, fname, doc, sortedblocks, typemap,
                            restype, calltypes, args, kws)
    return fd
Exemplo n.º 8
0
def lift_loop(bytecode, dispatcher_factory):
    """Lift the top-level loops.

    Returns (outer, loops)
    ------------------------
    * outer: ByteCode of a copy of the loop-less function.
    * loops: a list of ByteCode of the loops.
    """
    outer = []
    loops = []
    separate_loops(bytecode, outer, loops)

    # Discover variables references
    outer_rds, outer_wrs = find_varnames_uses(bytecode, outer)
    outer_wrs |= set(bytecode.argspec.args)

    dispatchers = []
    outerlabels = set(bytecode.labels)
    outernames = list(bytecode.co_names)

    for loop in loops:
        args, rets = discover_args_and_returns(bytecode, loop, outer_rds,
                                               outer_wrs)
        if rets:
            # Cannot deal with loop that write to variables used in outer body
            # Put the loop back into the outer function
            outer = stitch_instructions(outer, loop)
            # Recompute read-write variable set
            wrs, rds = find_varnames_uses(bytecode, loop)
            outer_wrs |= wrs
            outer_rds |= rds
        else:
            disp = insert_loop_call(bytecode, loop, args, outer, outerlabels,
                                    outernames, dispatcher_factory)
            dispatchers.append(disp)

    # Build outer bytecode
    codetable = utils.SortedMap((i.offset, i) for i in outer)
    outerbc = CustomByteCode(func=bytecode.func,
                             func_qualname=bytecode.func_qualname,
                             argspec=bytecode.argspec,
                             filename=bytecode.filename,
                             co_names=outernames,
                             co_varnames=bytecode.co_varnames,
                             co_consts=bytecode.co_consts,
                             co_freevars=bytecode.co_freevars,
                             table=codetable,
                             labels=outerlabels & set(codetable.keys()))
    return outerbc, dispatchers
Exemplo n.º 9
0
def lift_loop(bytecode, dispatcher_factory):
    """Lift the top-level loops.

    Returns (outer, loops)
    ------------------------
    * outer: ByteCode of a copy of the loop-less function.
    * loops: a list of ByteCode of the loops.
    """
    outer = []
    loops = []
    # Discover variables references
    outer_rds, outer_wrs = find_varnames_uses(bytecode, iter(bytecode))
    # Separate loops and outer
    separate_loops(bytecode, outer, loops)

    # Prepend arguments as negative bytecode offset
    for a in bytecode.pysig.parameters:
        outer_wrs[a] = [-1] + outer_wrs[a]

    dispatchers = []
    outerlabels = set(bytecode.labels)
    outernames = list(bytecode.co_names)

    for loop in loops:
        args, rets = discover_args_and_returns(bytecode, loop, outer_rds,
                                               outer_wrs)

        disp = insert_loop_call(bytecode, loop, args,
                                outer, outerlabels, rets,
                                dispatcher_factory)
        dispatchers.append(disp)

    # Build outer bytecode
    codetable = utils.SortedMap((i.offset, i) for i in outer)
    outerbc = CustomByteCode(func=bytecode.func,
                             func_qualname=bytecode.func_qualname,
                             is_generator=bytecode.is_generator,
                             pysig=bytecode.pysig,
                             filename=bytecode.filename,
                             co_names=outernames,
                             co_varnames=bytecode.co_varnames,
                             co_consts=bytecode.co_consts,
                             co_freevars=bytecode.co_freevars,
                             table=codetable,
                             labels=outerlabels & set(codetable.keys()))

    return outerbc, dispatchers
Exemplo n.º 10
0
def make_loop_bytecode(bytecode, loop, args):
    # Add return None
    co_consts = tuple(bytecode.co_consts)
    if None not in co_consts:
        co_consts += (None, )

    # Load None
    load_none = ByteCodeInst.get(loop[-1].next, "LOAD_CONST",
                                 co_consts.index(None))
    load_none.lineno = loop[-1].lineno
    loop.append(load_none)

    # Return None
    return_value = ByteCodeInst.get(loop[-1].next, "RETURN_VALUE", 0)
    return_value.lineno = loop[-1].lineno
    loop.append(return_value)

    # Function name
    loop_qualname = bytecode.func_qualname + ".__numba__loop%d__" % loop[
        0].offset

    # Argspec
    argspectype = type(bytecode.argspec)
    argspec = argspectype(args=args, varargs=(), keywords=(), defaults=())

    # Code table
    codetable = utils.SortedMap((i.offset, i) for i in loop)

    # Custom bytecode object
    lbc = CustomByteCode(func=bytecode.func,
                         func_qualname=loop_qualname,
                         argspec=argspec,
                         filename=bytecode.filename,
                         co_names=bytecode.co_names,
                         co_varnames=bytecode.co_varnames,
                         co_consts=co_consts,
                         co_freevars=bytecode.co_freevars,
                         table=codetable,
                         labels=bytecode.labels)

    return lbc
Exemplo n.º 11
0
 def _from_python_function(cls,
                           interp,
                           typemap,
                           restype,
                           calltypes,
                           native,
                           mangler=None):
     (qualname, unique_name, modname, doc, args, kws,
      func_globals) = cls._get_function_info(interp)
     sortedblocks = utils.SortedMap(utils.dict_iteritems(interp.blocks))
     self = cls(native,
                modname,
                qualname,
                unique_name,
                doc,
                sortedblocks,
                typemap,
                restype,
                calltypes,
                args,
                kws,
                mangler=mangler,
                globals=func_globals)
     return self