Source

pypy / pypy / translator / unsimplify.py

Alex Gaynor 9e5a2dd 


Armin Rigo e349d42 
Anders Chrigströ… e92d6e8 
Armin Rigo e349d42 


Anders Chrigströ… e92d6e8 

Armin Rigo e349d42 



Samuele Pedroni 038c77f 




Anders Chrigströ… e92d6e8 
Armin Rigo e349d42 
Armin Rigo 76d301c 









Armin Rigo e349d42 

Anders Chrigströ… e92d6e8 
Armin Rigo e349d42 
Armin Rigo 0617478 
Armin Rigo e349d42 





Anders Chrigströ… e92d6e8 

Armin Rigo 8703b30 



Armin Rigo bfdf11a 




Samuele Pedroni 863ecda 
holger krekel ad71587 
Alex Gaynor 9e5a2dd 
Armin Rigo 7373ba6 
Samuele Pedroni f243c37 
Carl Friedrich B… 75a53fd 
Armin Rigo ec62924 
Carl Friedrich B… 75a53fd 













Anders Chrigströ… e92d6e8 
Carl Friedrich B… 75a53fd 

Samuele Pedroni 7e0d3c7 
Carl Friedrich B… 75a53fd 
Samuele Pedroni 7e0d3c7 



Carl Friedrich B… 75a53fd 
Samuele Pedroni 7e0d3c7 



Carl Friedrich B… 75a53fd 







Samuele Pedroni 863ecda 


Armin Rigo e2a9e7d 






Armin Rigo f2805b6 







Armin Rigo e2a9e7d 








Samuele Pedroni 863ecda 
Samuele Pedroni f243c37 
Samuele Pedroni 863ecda 
Carl Friedrich B… 75a53fd 
Armin Rigo e1d4237 
Carl Friedrich B… 75a53fd 
Samuele Pedroni f243c37 
Carl Friedrich B… 75a53fd 
Armin Rigo e1d4237 
Carl Friedrich B… 75a53fd 
holger krekel ad71587 
Carl Friedrich B… 75a53fd 
Samuele Pedroni 863ecda 




Armin Rigo e512a53 






















Armin Rigo 1f6820a 
Armin Rigo cfc84f3 




Armin Rigo 1f6820a 


Armin Rigo cfc84f3 
Armin Rigo 1f6820a 

Armin Rigo cfc84f3 
Jean-Philippe St… c775f9d 
Armin Rigo cfc84f3 










from pypy.objspace.flow.model import (Variable, Constant, Block, Link,
    SpaceOperation, c_last_exception, checkgraph)


def copyvar(annotator, v):
    """Make a copy of the Variable v, preserving annotations and concretetype."""
    assert isinstance(v, Variable)
    newvar = Variable(v)
    if annotator is not None and v in annotator.bindings:
        annotator.transfer_binding(newvar, v)
    if hasattr(v, 'concretetype'):
        newvar.concretetype = v.concretetype
    return newvar

def varoftype(concretetype, name=None):
    var = Variable(name)
    var.concretetype = concretetype
    return var

def insert_empty_block(annotator, link, newops=[]):
    """Insert and return a new block along the given link."""
    vars = {}
    for v in link.args:
        if isinstance(v, Variable):
            vars[v] = True
    for op in newops:
        for v in op.args:
            if isinstance(v, Variable):
                vars.setdefault(v, True)
        vars[op.result] = False
    vars = [v for v, keep in vars.items() if keep]
    mapping = {}
    for v in vars:
        mapping[v] = copyvar(annotator, v)
    newblock = Block(vars)
    newblock.operations.extend(newops)
    newblock.closeblock(Link(link.args, link.target))
    newblock.renamevariables(mapping)
    link.args[:] = vars
    link.target = newblock
    return newblock

def insert_empty_startblock(annotator, graph):
    vars = [copyvar(annotator, v) for v in graph.startblock.inputargs]
    newblock = Block(vars)
    newblock.closeblock(Link(vars, graph.startblock))
    graph.startblock = newblock

def starts_with_empty_block(graph):
    return (not graph.startblock.operations
            and graph.startblock.exitswitch is None
            and graph.startblock.exits[0].args == graph.getargs())

def split_block(annotator, block, index, _forcelink=None):
    """return a link where prevblock is the block leading up but excluding the
    index'th operation and target is a new block with the neccessary variables
    passed on.
    """
    assert 0 <= index <= len(block.operations)
    if block.exitswitch == c_last_exception:
        assert index < len(block.operations)
    #varmap is the map between names in the new and the old block
    #but only for variables that are produced in the old block and needed in
    #the new one
    varmap = {}
    vars_produced_in_new_block = {}
    def get_new_name(var):
        if var is None:
            return None
        if isinstance(var, Constant):
            return var
        if var in vars_produced_in_new_block:
            return var
        if var not in varmap:
            varmap[var] = copyvar(annotator, var)
        return varmap[var]
    moved_operations = block.operations[index:]
    new_moved_ops = []
    for op in moved_operations:
        newop = SpaceOperation(op.opname,
                               [get_new_name(arg) for arg in op.args],
                               op.result)
        new_moved_ops.append(newop)
        vars_produced_in_new_block[op.result] = True
    moved_operations = new_moved_ops
    links = block.exits
    block.exits = None
    for link in links:
        for i, arg in enumerate(link.args):
            #last_exception and last_exc_value are considered to be created
            #when the link is entered
            if link.args[i] not in [link.last_exception, link.last_exc_value]:
                link.args[i] = get_new_name(link.args[i])
    exitswitch = get_new_name(block.exitswitch)
    #the new block gets all the attributes relevant to outgoing links
    #from block the old block
    if _forcelink is not None:
        assert index == 0
        linkargs = list(_forcelink)
        for v in varmap:
            if v not in linkargs:
                # 'v' was not specified by _forcelink, but we found out that
                # we need it!  Hack: if it is 'concretetype is lltype.Void'
                # then it's ok to recreate its value in the target block.
                # If not, then we have a problem :-)
                from pypy.rpython.lltypesystem import lltype
                if v.concretetype is not lltype.Void:
                    raise Exception(
                        "The variable %r of type %r was not explicitly listed"
                        " in _forcelink.  This issue can be caused by a"
                        " jitdriver.jit_merge_point() where some variable"
                        " containing an int or str or instance is actually"
                        " known to be constant, e.g. always 42." % (
                        v, v.concretetype))
                c = Constant(None, lltype.Void)
                w = varmap[v]
                newop = SpaceOperation('same_as', [c], w)
                i = 0
                while i < len(moved_operations):
                    if w in moved_operations[i].args:
                        break
                    i += 1
                moved_operations.insert(i, newop)
    else:
        linkargs = varmap.keys()
    newblock = Block([get_new_name(v) for v in linkargs])
    newblock.operations = moved_operations
    newblock.recloseblock(*links)
    newblock.exitswitch = exitswitch
    link = Link(linkargs, newblock)
    block.operations = block.operations[:index]
    block.recloseblock(link)
    block.exitswitch = None
    return link

def split_block_at_start(annotator, block):
    # split before the first op, preserve order and inputargs
    # in the second block!
    return split_block(annotator, block, 0, _forcelink=block.inputargs)

def call_initial_function(translator, initial_func, annhelper=None):
    """Before the program starts, call 'initial_func()'."""
    from pypy.annotation import model as annmodel
    from pypy.rpython.lltypesystem import lltype
    from pypy.rpython.annlowlevel import MixLevelHelperAnnotator

    own_annhelper = (annhelper is None)
    if own_annhelper:
        annhelper = MixLevelHelperAnnotator(translator.rtyper)
    c_initial_func = annhelper.constfunc(initial_func, [], annmodel.s_None)
    if own_annhelper:
        annhelper.finish()

    entry_point = translator.entry_point_graph
    args = [copyvar(translator.annotator, v) for v in entry_point.getargs()]
    extrablock = Block(args)
    v_none = varoftype(lltype.Void)
    newop = SpaceOperation('direct_call', [c_initial_func], v_none)
    extrablock.operations = [newop]
    extrablock.closeblock(Link(args, entry_point.startblock))
    entry_point.startblock = extrablock
    checkgraph(entry_point)

def call_final_function(translator, final_func, annhelper=None):
    """When the program finishes normally, call 'final_func()'."""
    from pypy.annotation import model as annmodel
    from pypy.rpython.lltypesystem import lltype
    from pypy.rpython.annlowlevel import MixLevelHelperAnnotator

    own_annhelper = (annhelper is None)
    if own_annhelper:
        annhelper = MixLevelHelperAnnotator(translator.rtyper)
    c_final_func = annhelper.constfunc(final_func, [], annmodel.s_None)
    if own_annhelper:
        annhelper.finish()

    entry_point = translator.entry_point_graph
    v = copyvar(translator.annotator, entry_point.getreturnvar())
    extrablock = Block([v])
    v_none = varoftype(lltype.Void)
    newop = SpaceOperation('direct_call', [c_final_func], v_none)
    extrablock.operations = [newop]
    extrablock.closeblock(Link([v], entry_point.returnblock))
    for block in entry_point.iterblocks():
        if block is not extrablock:
            for link in block.exits:
                if link.target is entry_point.returnblock:
                    link.target = extrablock
    checkgraph(entry_point)