예제 #1
0
def test_funny_links():
    from rpython.flowspace.model import Block, FunctionGraph, \
         Variable, Constant, Link
    from rpython.flowspace.operation import op
    for i in range(2):
        v_i = Variable("i")
        block = Block([v_i])
        g = FunctionGraph("is_one", block)
        op1 = op.eq(v_i, Constant(1))
        block.operations.append(op1)
        block.exitswitch = op1.result
        tlink = Link([Constant(1)], g.returnblock, True)
        flink = Link([Constant(0)], g.returnblock, False)
        links = [tlink, flink]
        if i:
            links.reverse()
        block.closeblock(*links)
        t = TranslationContext()
        a = t.buildannotator()
        a.build_graph_types(g, [annmodel.SomeInteger()])
        rtyper = t.buildrtyper()
        rtyper.specialize()
        interp = LLInterpreter(rtyper)
        assert interp.eval_graph(g, [1]) == 1
        assert interp.eval_graph(g, [0]) == 0
예제 #2
0
 def test_regalloc_lists(self):
     v1 = Variable()
     v1.concretetype = lltype.Signed
     v2 = Variable()
     v2.concretetype = lltype.Signed
     v3 = Variable()
     v3.concretetype = lltype.Signed
     v4 = Variable()
     v4.concretetype = lltype.Signed
     v5 = Variable()
     v5.concretetype = lltype.Signed
     block = Block([v1])
     block.operations = [
         SpaceOperation('int_add', [v1, Constant(1, lltype.Signed)], v2),
         SpaceOperation('rescall', [ListOfKind('int', [v1, v2])], v5),
         SpaceOperation('rescall', [ListOfKind('int', [v1, v2])], v3),
     ]
     graph = FunctionGraph('f', block, v4)
     block.closeblock(Link([v3], graph.returnblock))
     #
     self.check_assembler(
         graph, """
         int_add %i0, $1 -> %i1
         rescall I[%i0, %i1] -> %i2
         rescall I[%i0, %i1] -> %i0
         int_return %i0
     """)
예제 #3
0
 def builder(translator, func):
     # build a hacked graph that doesn't take a *arg any more, but
     # individual extra arguments
     graph = translator.buildflowgraph(func)
     argnames, vararg, kwarg = graph.signature
     assert vararg, "graph should have a *arg at this point"
     assert not kwarg, "where does this **arg come from??"
     argscopy = [Variable(v) for v in graph.getargs()]
     starargs = [
         Variable('stararg%d' % i) for i in range(nb_extra_args)
     ]
     newstartblock = Block(argscopy[:-1] + starargs)
     newtup = op.newtuple(*starargs)
     newtup.result = argscopy[-1]
     newstartblock.operations.append(newtup)
     newstartblock.closeblock(Link(argscopy, graph.startblock))
     graph.startblock = newstartblock
     argnames = argnames + ['.star%d' % i for i in range(nb_extra_args)]
     graph.signature = Signature(argnames)
     # note that we can mostly ignore defaults: if nb_extra_args > 0,
     # then defaults aren't applied.  if nb_extra_args == 0, then this
     # just removes the *arg and the defaults keep their meaning.
     if nb_extra_args > 0:
         graph.defaults = None  # shouldn't be used in this case
     checkgraph(graph)
     return graph
예제 #4
0
파일: test_ssa.py 프로젝트: Darriall/pypy
def test_SSA_to_SSI():
    c = Variable('c')
    x = Variable('x')
    y = Variable('y')
    b1 = Block([c])
    b2 = Block([x])
    b3 = Block([])

    graph = FunctionGraph('x', b1)
    b2.operations.append(SpaceOperation('add', [x, c], y))
    b2.exitswitch = y

    b1.closeblock(Link([Constant(0)], b2))
    b2.closeblock(Link([y], b2), Link([], b3))
    b3.closeblock(Link([y, c], graph.exceptblock))
    SSA_to_SSI(graph)

    assert len(b1.inputargs) == 1
    assert len(b2.inputargs) == 2
    assert len(b3.inputargs) == 2

    assert b2.inputargs == b2.operations[0].args
    assert len(b1.exits[0].args) == 2
    assert b1.exits[0].args[1] is c
    assert len(b2.exits[0].args) == 2
    assert b2.exits[0].args == [y, b2.inputargs[1]]
    assert len(b2.exits[1].args) == 2
    assert len(b3.exits[0].args) == 2

    index = b3.inputargs.index(b3.exits[0].args[0])
    assert b2.exits[1].args[index] is b2.operations[0].result

    index = b3.inputargs.index(b3.exits[0].args[1])
    assert b2.exits[1].args[index] is b2.inputargs[1]
예제 #5
0
def test_func_simple():
    # -------------------- flowgraph building --------------------
    #     def f(x):
    #         return x+1
    x = Variable("x")
    x.concretetype = Signed
    result = Variable("result")
    result.concretetype = Signed
    one = Constant(1)
    one.concretetype = Signed
    op = SpaceOperation("int_add", [x, one], result)
    block = Block([x])
    graph = FunctionGraph("f", block)
    block.operations.append(op)
    block.closeblock(Link([result], graph.returnblock))
    graph.getreturnvar().concretetype = Signed
    # --------------------         end        --------------------

    F = FuncType([Signed], Signed)
    f = functionptr(F, "f", graph=graph)
    db = LowLevelDatabase()
    db.get(f)
    db.complete()
    dump_on_stdout(db)

    S = GcStruct('testing', ('fptr', Ptr(F)))
    s = malloc(S)
    s.fptr = f
    db = LowLevelDatabase()
    db.get(s)
    db.complete()
    dump_on_stdout(db)
예제 #6
0
파일: unsimplify.py 프로젝트: charred/pypy
def call_final_function(translator, final_func, annhelper=None):
    """When the program finishes normally, call 'final_func()'."""
    from rpython.annotator import model as annmodel
    from rpython.rtyper.lltypesystem import lltype
    from rpython.rtyper.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)
예제 #7
0
def test_optimize_goto_if_not__incoming():
    v1 = Variable()
    v1.concretetype = lltype.Bool
    block = Block([v1])
    block.exitswitch = v1
    block.exits = [FakeLink(False), FakeLink(True)]
    assert not Transformer().optimize_goto_if_not(block)
예제 #8
0
파일: unsimplify.py 프로젝트: sbw111/lab4
def call_final_function(translator, final_func, annhelper=None):
    """When the program finishes normally, call 'final_func()'."""
    from rpython.annotator import model as annmodel
    from rpython.rtyper.lltypesystem import lltype
    from rpython.rtyper.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 = entry_point.getreturnvar().copy()
    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)
예제 #9
0
def test_funny_links():
    from rpython.flowspace.model import Block, FunctionGraph, \
         Variable, Constant, Link
    from rpython.flowspace.operation import op
    for i in range(2):
        v_i = Variable("i")
        block = Block([v_i])
        g = FunctionGraph("is_one", block)
        op1 = op.eq(v_i, Constant(1))
        block.operations.append(op1)
        block.exitswitch = op1.result
        tlink = Link([Constant(1)], g.returnblock, True)
        flink = Link([Constant(0)], g.returnblock, False)
        links = [tlink, flink]
        if i:
            links.reverse()
        block.closeblock(*links)
        t = TranslationContext()
        a = t.buildannotator()
        a.build_graph_types(g, [annmodel.SomeInteger()])
        rtyper = t.buildrtyper()
        rtyper.specialize()
        interp = LLInterpreter(rtyper)
        assert interp.eval_graph(g, [1]) == 1
        assert interp.eval_graph(g, [0]) == 0
예제 #10
0
def test_func_simple():
    # -------------------- flowgraph building --------------------
    #     def f(x):
    #         return x+1
    x = Variable("x")
    x.concretetype = Signed
    result = Variable("result")
    result.concretetype = Signed
    one = Constant(1)
    one.concretetype = Signed
    op = SpaceOperation("int_add", [x, one], result)
    block = Block([x])
    graph = FunctionGraph("f", block)
    block.operations.append(op)
    block.closeblock(Link([result], graph.returnblock))
    graph.getreturnvar().concretetype = Signed
    # --------------------         end        --------------------

    F = FuncType([Signed], Signed)
    f = functionptr(F, "f", graph=graph)
    db = LowLevelDatabase()
    db.get(f)
    db.complete()
    dump_on_stdout(db)

    S = GcStruct('testing', ('fptr', Ptr(F)))
    s = malloc(S)
    s.fptr = f
    db = LowLevelDatabase()
    db.get(s)
    db.complete()
    dump_on_stdout(db)
예제 #11
0
def test_optimize_goto_if_not__unknownop():
    v3 = Variable()
    v3.concretetype = lltype.Bool
    block = Block([])
    block.operations = [SpaceOperation("foobar", [], v3)]
    block.exitswitch = v3
    block.exits = [FakeLink(False), FakeLink(True)]
    assert not Transformer().optimize_goto_if_not(block)
예제 #12
0
 def insert_along_link(link, opname, args, cache):
     b2 = link.target
     if b2 not in cache:
         newblock = Block([v.copy() for v in b2.inputargs])
         newblock.operations.append(
             SpaceOperation(opname, args, varoftype(lltype.Void)))
         newblock.closeblock(Link(list(newblock.inputargs), b2))
         cache[b2] = newblock
     link.target = cache[b2]
예제 #13
0
 def make_dispatcher(self, shape, index, argtypes, resulttype):
     inputargs = [varoftype(t) for t in [Char] + argtypes]
     startblock = Block(inputargs)
     startblock.exitswitch = inputargs[0]
     graph = FunctionGraph("dispatcher", startblock, varoftype(resulttype))
     row_of_graphs = self.callfamily.calltables[shape][index]
     links = []
     descs = list(self.s_pbc.descriptions)
     if self.s_pbc.can_be_None:
         descs.insert(0, None)
     for desc in descs:
         if desc is None:
             continue
         args_v = [varoftype(t) for t in argtypes]
         b = Block(args_v)
         llfn = self.rtyper.getcallable(row_of_graphs[desc])
         v_fn = inputconst(typeOf(llfn), llfn)
         v_result = varoftype(resulttype)
         b.operations.append(
             SpaceOperation("direct_call", [v_fn] + args_v, v_result))
         b.closeblock(Link([v_result], graph.returnblock))
         i = self.descriptions.index(desc)
         links.append(Link(inputargs[1:], b, chr(i)))
         links[-1].llexitcase = chr(i)
     startblock.closeblock(*links)
     return graph
예제 #14
0
 def dispatcher(self, shape, index, argtypes, resulttype):
     key = shape, index, tuple(argtypes), resulttype
     if key in self._dispatch_cache:
         return self._dispatch_cache[key]
     from rpython.translator.unsimplify import varoftype
     from rpython.flowspace.model import FunctionGraph, Link, Block, SpaceOperation
     inputargs = [varoftype(t) for t in [Char] + argtypes]
     startblock = Block(inputargs)
     startblock.exitswitch = inputargs[0]
     graph = FunctionGraph("dispatcher", startblock, varoftype(resulttype))
     row_of_graphs = self.callfamily.calltables[shape][index]
     links = []
     descs = list(self.s_pbc.descriptions)
     if self.s_pbc.can_be_None:
         descs.insert(0, None)
     for desc in descs:
         if desc is None:
             continue
         args_v = [varoftype(t) for t in argtypes]
         b = Block(args_v)
         llfn = self.rtyper.getcallable(row_of_graphs[desc])
         v_fn = inputconst(typeOf(llfn), llfn)
         v_result = varoftype(resulttype)
         b.operations.append(
             SpaceOperation("direct_call", [v_fn] + args_v, v_result))
         b.closeblock(Link([v_result], graph.returnblock))
         i = self.descriptions.index(desc)
         links.append(Link(inputargs[1:], b, chr(i)))
         links[-1].llexitcase = chr(i)
     startblock.closeblock(*links)
     self.rtyper.annotator.translator.graphs.append(graph)
     ll_ret = getfunctionptr(graph)
     #FTYPE = FuncType
     c_ret = self._dispatch_cache[key] = inputconst(typeOf(ll_ret), ll_ret)
     return c_ret
예제 #15
0
파일: inline.py 프로젝트: yuyichao/pypy
 def copy_block(self, block):
     if block in self._copied_blocks:
         return self._copied_blocks[block]
     args = ([self.get_new_name(var) for var in block.inputargs] +
             self.passon_vars(block))
     newblock = Block(args)
     self._copied_blocks[block] = newblock
     newblock.operations = [self.copy_operation(op) for op in block.operations]
     newblock.closeblock(*[self.copy_link(link, block) for link in block.exits])
     newblock.exitswitch = self.get_new_name(block.exitswitch)
     self.search_for_calls(newblock)
     return newblock
예제 #16
0
파일: generator.py 프로젝트: sota/pypy-old
def replace_graph_with_bootstrap(GeneratorIterator, graph):
    Entry = GeneratorIterator.Entry
    newblock = Block(graph.startblock.inputargs)
    op_entry = op.simple_call(const(Entry))
    v_entry = op_entry.result
    newblock.operations.append(op_entry)
    assert len(graph.startblock.inputargs) == len(Entry.varnames)
    for v, name in zip(graph.startblock.inputargs, Entry.varnames):
        newblock.operations.append(op.setattr(v_entry, Constant(name), v))
    op_generator = op.simple_call(const(GeneratorIterator), v_entry)
    newblock.operations.append(op_generator)
    newblock.closeblock(Link([op_generator.result], graph.returnblock))
    graph.startblock = newblock
예제 #17
0
파일: generator.py 프로젝트: bukzor/pypy
def replace_graph_with_bootstrap(GeneratorIterator, graph):
    Entry = GeneratorIterator.Entry
    newblock = Block(graph.startblock.inputargs)
    op_entry = op.simple_call(const(Entry))
    v_entry = op_entry.result
    newblock.operations.append(op_entry)
    assert len(graph.startblock.inputargs) == len(Entry.varnames)
    for v, name in zip(graph.startblock.inputargs, Entry.varnames):
        newblock.operations.append(op.setattr(v_entry, Constant(name), v))
    op_generator = op.simple_call(const(GeneratorIterator), v_entry)
    newblock.operations.append(op_generator)
    newblock.closeblock(Link([op_generator.result], graph.returnblock))
    graph.startblock = newblock
예제 #18
0
def test_optimize_goto_if_not__ptr_iszero():
    for opname in ["ptr_iszero", "ptr_nonzero"]:
        v1 = Variable()
        v3 = Variable()
        v3.concretetype = lltype.Bool
        block = Block([v1])
        block.operations = [SpaceOperation(opname, [v1], v3)]
        block.exitswitch = v3
        block.exits = exits = [FakeLink(False), FakeLink(True)]
        res = Transformer().optimize_goto_if_not(block)
        assert res == True
        assert block.operations == []
        assert block.exitswitch == (opname, v1, "-live-before")
        assert block.exits == exits
예제 #19
0
def test_rename_on_links():
    v1 = Variable()
    v2 = Variable()
    v2.concretetype = llmemory.Address
    v3 = Variable()
    block = Block([v1])
    block.operations = [SpaceOperation("cast_pointer", [v1], v2)]
    block2 = Block([v3])
    block.closeblock(Link([v2], block2))
    Transformer().optimize_block(block)
    assert block.inputargs == [v1]
    assert block.operations == []
    assert block.exits[0].target is block2
    assert block.exits[0].args == [v1]
예제 #20
0
def normalize_calltable_row_annotation(annotator, graphs):
    if len(graphs) <= 1:
        return False  # nothing to do
    graph_bindings = {}
    for graph in graphs:
        graph_bindings[graph] = [annotator.binding(v) for v in graph.getargs()]
    iterbindings = graph_bindings.itervalues()
    nbargs = len(iterbindings.next())
    for binding in iterbindings:
        assert len(binding) == nbargs

    generalizedargs = []
    for i in range(nbargs):
        args_s = []
        for graph, bindings in graph_bindings.items():
            args_s.append(bindings[i])
        s_value = annmodel.unionof(*args_s)
        generalizedargs.append(s_value)
    result_s = [
        annotator.binding(graph.getreturnvar()) for graph in graph_bindings
    ]
    generalizedresult = annmodel.unionof(*result_s)

    conversion = False
    for graph in graphs:
        bindings = graph_bindings[graph]
        need_conversion = (generalizedargs != bindings)
        if need_conversion:
            conversion = True
            oldblock = graph.startblock
            inlist = []
            for j, s_value in enumerate(generalizedargs):
                v = Variable(graph.getargs()[j])
                annotator.setbinding(v, s_value)
                inlist.append(v)
            newblock = Block(inlist)
            # prepare the output args of newblock and link
            outlist = inlist[:]
            newblock.closeblock(Link(outlist, oldblock))
            graph.startblock = newblock
            # finished
            checkgraph(graph)
            annotator.annotated[newblock] = annotator.annotated[oldblock]
        # convert the return value too
        if annotator.binding(graph.getreturnvar()) != generalizedresult:
            conversion = True
            annotator.setbinding(graph.getreturnvar(), generalizedresult)

    return conversion
예제 #21
0
def normalize_calltable_row_annotation(annotator, graphs):
    if len(graphs) <= 1:
        return False   # nothing to do
    graph_bindings = {}
    for graph in graphs:
        graph_bindings[graph] = [annotator.binding(v)
                                 for v in graph.getargs()]
    iterbindings = graph_bindings.itervalues()
    nbargs = len(iterbindings.next())
    for binding in iterbindings:
        assert len(binding) == nbargs

    generalizedargs = []
    for i in range(nbargs):
        args_s = []
        for graph, bindings in graph_bindings.items():
            args_s.append(bindings[i])
        s_value = annmodel.unionof(*args_s)
        generalizedargs.append(s_value)
    result_s = [annotator.binding(graph.getreturnvar())
                for graph in graph_bindings]
    generalizedresult = annmodel.unionof(*result_s)

    conversion = False
    for graph in graphs:
        bindings = graph_bindings[graph]
        need_conversion = (generalizedargs != bindings)
        if need_conversion:
            conversion = True
            oldblock = graph.startblock
            inlist = []
            for j, s_value in enumerate(generalizedargs):
                v = Variable(graph.getargs()[j])
                annotator.setbinding(v, s_value)
                inlist.append(v)
            newblock = Block(inlist)
            # prepare the output args of newblock and link
            outlist = inlist[:]
            newblock.closeblock(Link(outlist, oldblock))
            graph.startblock = newblock
            # finished
            checkgraph(graph)
            annotator.annotated[newblock] = annotator.annotated[oldblock]
        # convert the return value too
        if annotator.binding(graph.getreturnvar()) != generalizedresult:
            conversion = True
            annotator.setbinding(graph.getreturnvar(), generalizedresult)

    return conversion
예제 #22
0
def test_optimize_goto_if_not():
    v1 = Variable()
    v2 = Variable()
    v3 = Variable()
    v3.concretetype = lltype.Bool
    sp1 = SpaceOperation("foobar", [], None)
    sp2 = SpaceOperation("foobaz", [], None)
    block = Block([v1, v2])
    block.operations = [sp1, SpaceOperation("int_gt", [v1, v2], v3), sp2]
    block.exitswitch = v3
    block.exits = exits = [FakeLink(False), FakeLink(True)]
    res = Transformer().optimize_goto_if_not(block)
    assert res == True
    assert block.operations == [sp1, sp2]
    assert block.exitswitch == ("int_gt", v1, v2)
    assert block.exits == exits
예제 #23
0
    def create_proxy_graph(self, op):
        """ creates a graph which calls the original function, checks for
        raised exceptions, fetches and then raises them again. If this graph is
        inlined, the correct exception matching blocks are produced."""
        # XXX slightly annoying: construct a graph by hand
        # but better than the alternative
        result = op.result.copy()
        opargs = []
        inputargs = []
        callargs = []
        ARGTYPES = []
        for var in op.args:
            if isinstance(var, Variable):
                v = Variable()
                v.concretetype = var.concretetype
                inputargs.append(v)
                opargs.append(v)
                callargs.append(var)
                ARGTYPES.append(var.concretetype)
            else:
                opargs.append(var)
        newop = SpaceOperation(op.opname, opargs, result)
        startblock = Block(inputargs)
        startblock.operations.append(newop)
        newgraph = FunctionGraph("dummy_exc1", startblock)
        startblock.closeblock(Link([result], newgraph.returnblock))
        newgraph.returnblock.inputargs[0].concretetype = op.result.concretetype
        self.gen_exc_check(startblock, newgraph.returnblock)
        excblock = Block([])

        llops = rtyper.LowLevelOpList(None)
        var_value = self.gen_getfield('exc_value', llops)
        var_type = self.gen_getfield('exc_type', llops)
        #
        c_check1 = self.c_assertion_error_ll_exc_type
        c_check2 = self.c_n_i_error_ll_exc_type
        llops.genop('debug_catch_exception', [var_type, c_check1, c_check2])
        #
        self.gen_setfield('exc_value', self.c_null_evalue, llops)
        self.gen_setfield('exc_type', self.c_null_etype, llops)
        excblock.operations[:] = llops
        newgraph.exceptblock.inputargs[
            0].concretetype = self.lltype_of_exception_type
        newgraph.exceptblock.inputargs[
            1].concretetype = self.lltype_of_exception_value
        excblock.closeblock(Link([var_type, var_value], newgraph.exceptblock))
        startblock.exits[True].target = excblock
        startblock.exits[True].args = []
        fptr = self.constant_func("dummy_exc1", ARGTYPES,
                                  op.result.concretetype, newgraph)
        return newgraph, SpaceOperation("direct_call", [fptr] + callargs,
                                        op.result)
예제 #24
0
파일: generator.py 프로젝트: charred/pypy
def replace_graph_with_bootstrap(GeneratorIterator, graph):
    Entry = GeneratorIterator.Entry
    newblock = Block(graph.startblock.inputargs)
    v_generator = Variable('generator')
    v_entry = Variable('entry')
    newblock.operations.append(
        SpaceOperation('simple_call', [Constant(Entry)], v_entry))
    assert len(graph.startblock.inputargs) == len(Entry.varnames)
    for v, name in zip(graph.startblock.inputargs, Entry.varnames):
        newblock.operations.append(
            SpaceOperation('setattr', [v_entry, Constant(name), v],
                           Variable()))
    newblock.operations.append(
        SpaceOperation('simple_call', [Constant(GeneratorIterator), v_entry],
                       v_generator))
    newblock.closeblock(Link([v_generator], graph.returnblock))
    graph.startblock = newblock
예제 #25
0
파일: rpbc.py 프로젝트: cimarieta/usp
 def make_dispatcher(self, shape, index, argtypes, resulttype):
     inputargs = [varoftype(t) for t in [Char] + argtypes]
     startblock = Block(inputargs)
     startblock.exitswitch = inputargs[0]
     graph = FunctionGraph("dispatcher", startblock, varoftype(resulttype))
     row_of_graphs = self.callfamily.calltables[shape][index]
     links = []
     descs = list(self.s_pbc.descriptions)
     if self.s_pbc.can_be_None:
         descs.insert(0, None)
     for desc in descs:
         if desc is None:
             continue
         args_v = [varoftype(t) for t in argtypes]
         b = Block(args_v)
         llfn = self.rtyper.getcallable(row_of_graphs[desc])
         v_fn = inputconst(typeOf(llfn), llfn)
         v_result = varoftype(resulttype)
         b.operations.append(
             SpaceOperation("direct_call", [v_fn] + args_v, v_result))
         b.closeblock(Link([v_result], graph.returnblock))
         i = self.descriptions.index(desc)
         links.append(Link(inputargs[1:], b, chr(i)))
         links[-1].llexitcase = chr(i)
     startblock.closeblock(*links)
     return graph
예제 #26
0
 def get_exc_reconstruction_block(self, typedesc):
     exceptblock = self.graph.exceptblock
     self.mallocv.fixup_except_block(exceptblock)
     TEXC = exceptblock.inputargs[0].concretetype
     TVAL = exceptblock.inputargs[1].concretetype
     #
     v_ignored_type = varoftype(TEXC)
     v_incoming_value = varoftype(TVAL)
     block = Block([v_ignored_type, v_incoming_value])
     #
     c_EXCTYPE = Constant(typedesc.MALLOCTYPE, lltype.Void)
     v = varoftype(lltype.Ptr(typedesc.MALLOCTYPE))
     c_flavor = Constant({'flavor': 'gc'}, lltype.Void)
     op = SpaceOperation('malloc', [c_EXCTYPE, c_flavor], v)
     block.operations.append(op)
     #
     for name, FIELDTYPE in typedesc.names_and_types:
         EXACTPTR = lltype.Ptr(typedesc.name2subtype[name])
         c_name = Constant(name)
         c_name.concretetype = lltype.Void
         #
         v_in = varoftype(EXACTPTR)
         op = SpaceOperation('cast_pointer', [v_incoming_value], v_in)
         block.operations.append(op)
         #
         v_field = varoftype(FIELDTYPE)
         op = SpaceOperation('getfield', [v_in, c_name], v_field)
         block.operations.append(op)
         #
         v_out = varoftype(EXACTPTR)
         op = SpaceOperation('cast_pointer', [v], v_out)
         block.operations.append(op)
         #
         v0 = varoftype(lltype.Void)
         op = SpaceOperation('setfield', [v_out, c_name, v_field], v0)
         block.operations.append(op)
     #
     v_exc_value = varoftype(TVAL)
     op = SpaceOperation('cast_pointer', [v], v_exc_value)
     block.operations.append(op)
     #
     exc_type = self.mallocv.EXCTYPE_to_vtable[typedesc.MALLOCTYPE]
     c_exc_type = Constant(exc_type, TEXC)
     block.closeblock(Link([c_exc_type, v_exc_value], exceptblock))
     return block
예제 #27
0
 def get_exc_reconstruction_block(self, typedesc):
     exceptblock = self.graph.exceptblock
     self.mallocv.fixup_except_block(exceptblock)
     TEXC = exceptblock.inputargs[0].concretetype
     TVAL = exceptblock.inputargs[1].concretetype
     #
     v_ignored_type = varoftype(TEXC)
     v_incoming_value = varoftype(TVAL)
     block = Block([v_ignored_type, v_incoming_value])
     #
     c_EXCTYPE = Constant(typedesc.MALLOCTYPE, lltype.Void)
     v = varoftype(lltype.Ptr(typedesc.MALLOCTYPE))
     c_flavor = Constant({'flavor': 'gc'}, lltype.Void)
     op = SpaceOperation('malloc', [c_EXCTYPE, c_flavor], v)
     block.operations.append(op)
     #
     for name, FIELDTYPE in typedesc.names_and_types:
         EXACTPTR = lltype.Ptr(typedesc.name2subtype[name])
         c_name = Constant(name)
         c_name.concretetype = lltype.Void
         #
         v_in = varoftype(EXACTPTR)
         op = SpaceOperation('cast_pointer', [v_incoming_value], v_in)
         block.operations.append(op)
         #
         v_field = varoftype(FIELDTYPE)
         op = SpaceOperation('getfield', [v_in, c_name], v_field)
         block.operations.append(op)
         #
         v_out = varoftype(EXACTPTR)
         op = SpaceOperation('cast_pointer', [v], v_out)
         block.operations.append(op)
         #
         v0 = varoftype(lltype.Void)
         op = SpaceOperation('setfield', [v_out, c_name, v_field], v0)
         block.operations.append(op)
     #
     v_exc_value = varoftype(TVAL)
     op = SpaceOperation('cast_pointer', [v], v_exc_value)
     block.operations.append(op)
     #
     exc_type = self.mallocv.EXCTYPE_to_vtable[typedesc.MALLOCTYPE]
     c_exc_type = Constant(exc_type, TEXC)
     block.closeblock(Link([c_exc_type, v_exc_value], exceptblock))
     return block
예제 #28
0
def test_optimize_goto_if_not__exit():
    # this case occurs in practice, e.g. with RPython code like:
    #     return bool(p) and p.somefield > 0
    v1 = Variable()
    v2 = Variable()
    v3 = Variable()
    v3.concretetype = lltype.Bool
    block = Block([v1, v2])
    block.operations = [SpaceOperation("int_gt", [v1, v2], v3)]
    block.exitswitch = v3
    block.exits = exits = [FakeLink(False), FakeLink(True)]
    block.exits[1].args = [v3]
    res = Transformer().optimize_goto_if_not(block)
    assert res == True
    assert block.operations == []
    assert block.exitswitch == ("int_gt", v1, v2)
    assert block.exits == exits
    assert exits[1].args == [const(True)]
예제 #29
0
파일: test_ssa.py 프로젝트: Darriall/pypy
def test_SSA_to_SSI_2():
    x = Variable('x')
    y = Variable('y')
    z = Variable('z')
    b1 = Block([x])
    b2 = Block([y])
    b3 = Block([])

    b3.operations.append(SpaceOperation('hello', [y], z))
    b1.closeblock(Link([x], b2), Link([], b3))
    graph = FunctionGraph('x', b1)
    SSA_to_SSI(graph)

    assert b1.inputargs == [x]
    assert b2.inputargs == [y]
    assert b3.inputargs == [b3.operations[0].args[0]]
    assert b1.exits[0].args == [x]
    assert b1.exits[1].args == [x]
예제 #30
0
 def test_regalloc_call(self):
     v1 = Variable(); v1.concretetype = lltype.Signed
     v2 = Variable(); v2.concretetype = lltype.Signed
     v3 = Variable(); v3.concretetype = lltype.Signed
     v4 = Variable(); v4.concretetype = lltype.Signed
     block = Block([v1])
     block.operations = [
         SpaceOperation('int_add', [v1, Constant(1, lltype.Signed)], v2),
         SpaceOperation('rescall', [ListOfKind('int', [v1, v2])], v3),
         ]
     graph = FunctionGraph('f', block, v4)
     block.closeblock(Link([v3], graph.returnblock))
     #
     self.check_assembler(graph, """
         int_add %i0, $1 -> %i1
         rescall I[%i0, %i1] -> %i0
         int_return %i0
     """)
예제 #31
0
파일: test_ssa.py 프로젝트: charred/pypy
def test_SSA_to_SSI_2():
    x = Variable('x')
    y = Variable('y')
    z = Variable('z')
    b1 = Block([x])
    b2 = Block([y])
    b3 = Block([])

    b3.operations.append(SpaceOperation('hello', [y], z))
    b1.closeblock(Link([x], b2), Link([], b3))

    SSA_to_SSI({b1: True,     # reachable from outside
                b2: False,
                b3: False})

    assert b1.inputargs == [x]
    assert b2.inputargs == [y]
    assert b3.inputargs == [b3.operations[0].args[0]]
    assert b1.exits[0].args == [x]
    assert b1.exits[1].args == [x]
예제 #32
0
파일: inline.py 프로젝트: juokaz/pypy
    def generic_exception_matching(self, afterblock, copiedexceptblock):
        #XXXXX don't look: insert blocks that do exception matching
        #for the cases where direct matching did not work
        exc_match = Constant(
            self.translator.rtyper.exceptiondata.fn_exception_match)
        exc_match.concretetype = typeOf(exc_match.value)
        blocks = []
        for i, link in enumerate(afterblock.exits[1:]):
            etype = copiedexceptblock.inputargs[0].copy()
            evalue = copiedexceptblock.inputargs[1].copy()
            passon_vars = self.passon_vars(i)
            block = Block([etype, evalue] + passon_vars)
            res = Variable()
            res.concretetype = Bool
            cexitcase = Constant(link.llexitcase)
            cexitcase.concretetype = typeOf(cexitcase.value)
            args = [exc_match, etype, cexitcase]
            block.operations.append(SpaceOperation("direct_call", args, res))
            block.exitswitch = res
            linkargs = self.find_args_in_exceptional_case(link, link.target,
                                                          etype, evalue, afterblock,
                                                          passon_vars)
            l = Link(linkargs, link.target)
            l.prevblock = block
            l.exitcase = True
            l.llexitcase = True
            block.closeblock(l)
            if i > 0:
                l = Link(blocks[-1].inputargs, block)
                l.exitcase = False
                l.llexitcase = False
                blocks[-1].recloseblock(l, *blocks[-1].exits)
            blocks.append(block)

        blocks[-1].recloseblock(*blocks[-1].exits[:1])
        blocks[-1].operations = []
        blocks[-1].exitswitch = None
        blocks[-1].exits[0].exitcase = None
        del blocks[-1].exits[0].llexitcase
        linkargs = copiedexceptblock.inputargs
        copiedexceptblock.recloseblock(Link(linkargs, blocks[0]))
예제 #33
0
파일: inline.py 프로젝트: yuyichao/pypy
    def generic_exception_matching(self, afterblock, copiedexceptblock):
        #XXXXX don't look: insert blocks that do exception matching
        #for the cases where direct matching did not work
        exc_match = Constant(
            self.translator.rtyper.exceptiondata.fn_exception_match)
        exc_match.concretetype = typeOf(exc_match.value)
        blocks = []
        for i, link in enumerate(afterblock.exits[1:]):
            etype = copyvar(None, copiedexceptblock.inputargs[0])
            evalue = copyvar(None, copiedexceptblock.inputargs[1])
            passon_vars = self.passon_vars(i)
            block = Block([etype, evalue] + passon_vars)
            res = Variable()
            res.concretetype = Bool
            cexitcase = Constant(link.llexitcase)
            cexitcase.concretetype = typeOf(cexitcase.value)
            args = [exc_match, etype, cexitcase]
            block.operations.append(SpaceOperation("direct_call", args, res))
            block.exitswitch = res
            linkargs = self.find_args_in_exceptional_case(link, link.target,
                                                          etype, evalue, afterblock,
                                                          passon_vars)
            l = Link(linkargs, link.target)
            l.prevblock = block
            l.exitcase = True
            l.llexitcase = True
            block.closeblock(l)
            if i > 0:
                l = Link(blocks[-1].inputargs, block)
                l.exitcase = False
                l.llexitcase = False
                blocks[-1].recloseblock(l, *blocks[-1].exits)
            blocks.append(block)

        blocks[-1].recloseblock(*blocks[-1].exits[:1])
        blocks[-1].operations = []
        blocks[-1].exitswitch = None
        blocks[-1].exits[0].exitcase = None
        del blocks[-1].exits[0].llexitcase
        linkargs = copiedexceptblock.inputargs
        copiedexceptblock.recloseblock(Link(linkargs, blocks[0]))
예제 #34
0
def create_instantiate_function(annotator, classdef):
    # build the graph of a function that looks like
    #
    # def my_instantiate():
    #     return instantiate(cls)
    #
    if hasattr(classdef, 'my_instantiate_graph'):
        return
    v = Variable()
    block = Block([])
    block.operations.append(SpaceOperation('instantiate1', [], v))
    name = valid_identifier('instantiate_' + classdef.name)
    graph = FunctionGraph(name, block)
    block.closeblock(Link([v], graph.returnblock))
    annotator.setbinding(v, annmodel.SomeInstance(classdef))
    annotator.annotated[block] = graph
    # force the result to be converted to a generic OBJECTPTR
    generalizedresult = annmodel.SomeInstance(classdef=None)
    annotator.setbinding(graph.getreturnvar(), generalizedresult)
    classdef.my_instantiate_graph = graph
    annotator.translator.graphs.append(graph)
예제 #35
0
def create_instantiate_function(annotator, classdef):
    # build the graph of a function that looks like
    #
    # def my_instantiate():
    #     return instantiate(cls)
    #
    if hasattr(classdef, 'my_instantiate_graph'):
        return
    v = Variable()
    block = Block([])
    block.operations.append(SpaceOperation('instantiate1', [], v))
    name = valid_identifier('instantiate_' + classdef.name)
    graph = FunctionGraph(name, block)
    block.closeblock(Link([v], graph.returnblock))
    annotator.setbinding(v, annmodel.SomeInstance(classdef))
    annotator.annotated[block] = graph
    # force the result to be converted to a generic OBJECTPTR
    generalizedresult = annmodel.SomeInstance(classdef=None)
    annotator.setbinding(graph.getreturnvar(), generalizedresult)
    classdef.my_instantiate_graph = graph
    annotator.translator.graphs.append(graph)
예제 #36
0
 def test_regalloc_exitswitch_2(self):
     v1 = Variable(); v1.concretetype = rclass.CLASSTYPE
     v2 = Variable(); v2.concretetype = rclass.CLASSTYPE
     v3 = Variable(); v3.concretetype = rclass.CLASSTYPE
     v4 = Variable(); v4.concretetype = rclass.CLASSTYPE
     block = Block([])
     block.operations = [
         SpaceOperation('res_call', [], v1),
         SpaceOperation('-live-', [], None),
         ]
     graph = FunctionGraph('f', block, v4)
     exclink = Link([v2], graph.returnblock)
     exclink.llexitcase = 123     # normally an exception class
     exclink.last_exception = v2
     exclink.last_exc_value = "unused"
     block.exitswitch = c_last_exception
     block.closeblock(Link([v1], graph.returnblock),
                      exclink)
     #
     self.check_assembler(graph, """
         res_call -> %i0
         -live-
         catch_exception L1
         int_return %i0
         ---
         L1:
         goto_if_exception_mismatch $123, L2
         last_exception -> %i0
         int_return %i0
         ---
         L2:
         reraise
     """)
예제 #37
0
파일: unsimplify.py 프로젝트: charred/pypy
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
예제 #38
0
파일: unsimplify.py 프로젝트: charred/pypy
def call_initial_function(translator, initial_func, annhelper=None):
    """Before the program starts, call 'initial_func()'."""
    from rpython.annotator import model as annmodel
    from rpython.rtyper.lltypesystem import lltype
    from rpython.rtyper.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)
예제 #39
0
파일: unsimplify.py 프로젝트: sbw111/lab4
def call_initial_function(translator, initial_func, annhelper=None):
    """Before the program starts, call 'initial_func()'."""
    from rpython.annotator import model as annmodel
    from rpython.rtyper.lltypesystem import lltype
    from rpython.rtyper.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 = [v.copy() 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)
예제 #40
0
 def transform_jump_to_except_block(self, graph, entrymap, link):
     reraise = self.comes_from_last_exception(entrymap, link)
     result = Variable()
     result.concretetype = lltype.Void
     block = Block([v.copy() for v in graph.exceptblock.inputargs])
     if reraise:
         block.operations = [
             SpaceOperation("direct_call",
                            [self.rpyexc_reraise_ptr] + block.inputargs,
                            result),
             ]
     else:
         block.operations = [
             SpaceOperation("direct_call",
                            [self.rpyexc_raise_ptr] + block.inputargs,
                            result),
             SpaceOperation('debug_record_traceback', [],
                            varoftype(lltype.Void)),
             ]
     link.target = block
     RETTYPE = graph.returnblock.inputargs[0].concretetype
     l = Link([error_constant(RETTYPE)], graph.returnblock)
     block.recloseblock(l)
예제 #41
0
 def builder(translator, func):
     # build a hacked graph that doesn't take a *arg any more, but
     # individual extra arguments
     graph = translator.buildflowgraph(func)
     argnames, vararg, kwarg = graph.signature
     assert vararg, "graph should have a *arg at this point"
     assert not kwarg, "where does this **arg come from??"
     argscopy = [Variable(v) for v in graph.getargs()]
     starargs = [Variable('stararg%d'%i) for i in range(nb_extra_args)]
     newstartblock = Block(argscopy[:-1] + starargs)
     newtup = op.newtuple(*starargs)
     newtup.result = argscopy[-1]
     newstartblock.operations.append(newtup)
     newstartblock.closeblock(Link(argscopy, graph.startblock))
     graph.startblock = newstartblock
     argnames = argnames + ['.star%d' % i for i in range(nb_extra_args)]
     graph.signature = Signature(argnames)
     # note that we can mostly ignore defaults: if nb_extra_args > 0,
     # then defaults aren't applied.  if nb_extra_args == 0, then this
     # just removes the *arg and the defaults keep their meaning.
     if nb_extra_args > 0:
         graph.defaults = None   # shouldn't be used in this case
     checkgraph(graph)
     return graph
예제 #42
0
파일: test_ssa.py 프로젝트: charred/pypy
def test_SSA_to_SSI():
    c = Variable('c')
    x = Variable('x')
    y = Variable('y')
    b1 = Block([c])
    b2 = Block([x])
    b3 = Block([])

    b2.operations.append(SpaceOperation('add', [x, c], y))
    b2.exitswitch = y

    b1.closeblock(Link([Constant(0)], b2))
    b2.closeblock(Link([y], b2), Link([], b3))
    b3.closeblock(Link([y, c], None))

    SSA_to_SSI({b1: True,     # reachable from outside
                b2: False,
                b3: False})

    assert len(b1.inputargs) == 1
    assert len(b2.inputargs) == 2
    assert len(b3.inputargs) == 2

    assert b2.inputargs == b2.operations[0].args
    assert len(b1.exits[0].args) == 2
    assert b1.exits[0].args[1] is c
    assert len(b2.exits[0].args) == 2
    assert b2.exits[0].args == [y, b2.inputargs[1]]
    assert len(b2.exits[1].args) == 2
    assert len(b3.exits[0].args) == 2

    index = b3.inputargs.index(b3.exits[0].args[0])
    assert b2.exits[1].args[index] is b2.operations[0].result

    index = b3.inputargs.index(b3.exits[0].args[1])
    assert b2.exits[1].args[index] is b2.inputargs[1]
예제 #43
0
    def create_proxy_graph(self, op):
        """ creates a graph which calls the original function, checks for
        raised exceptions, fetches and then raises them again. If this graph is
        inlined, the correct exception matching blocks are produced."""
        # XXX slightly annoying: construct a graph by hand
        # but better than the alternative
        result = copyvar(None, op.result)
        opargs = []
        inputargs = []
        callargs = []
        ARGTYPES = []
        for var in op.args:
            if isinstance(var, Variable):
                v = Variable()
                v.concretetype = var.concretetype
                inputargs.append(v)
                opargs.append(v)
                callargs.append(var)
                ARGTYPES.append(var.concretetype)
            else:
                opargs.append(var)
        newop = SpaceOperation(op.opname, opargs, result)
        startblock = Block(inputargs)
        startblock.operations.append(newop)
        newgraph = FunctionGraph("dummy_exc1", startblock)
        startblock.closeblock(Link([result], newgraph.returnblock))
        newgraph.returnblock.inputargs[0].concretetype = op.result.concretetype
        self.gen_exc_check(startblock, newgraph.returnblock)
        excblock = Block([])

        llops = rtyper.LowLevelOpList(None)
        var_value = self.gen_getfield('exc_value', llops)
        var_type  = self.gen_getfield('exc_type' , llops)
        #
        c_check1 = self.c_assertion_error_ll_exc_type
        c_check2 = self.c_n_i_error_ll_exc_type
        llops.genop('debug_catch_exception', [var_type, c_check1, c_check2])
        #
        self.gen_setfield('exc_value', self.c_null_evalue, llops)
        self.gen_setfield('exc_type',  self.c_null_etype,  llops)
        excblock.operations[:] = llops
        newgraph.exceptblock.inputargs[0].concretetype = self.lltype_of_exception_type
        newgraph.exceptblock.inputargs[1].concretetype = self.lltype_of_exception_value
        excblock.closeblock(Link([var_type, var_value], newgraph.exceptblock))
        startblock.exits[True].target = excblock
        startblock.exits[True].args = []
        fptr = self.constant_func("dummy_exc1", ARGTYPES, op.result.concretetype, newgraph)
        return newgraph, SpaceOperation("direct_call", [fptr] + callargs, op.result)
예제 #44
0
파일: inline.py 프로젝트: Mu-L/pypy
 def copy_block(self, block):
     if block in self._copied_blocks:
         return self._copied_blocks[block]
     args = ([self.get_new_name(var) for var in block.inputargs] +
             self.passon_vars(block))
     newblock = Block(args)
     self._copied_blocks[block] = newblock
     newblock.operations = [self.copy_operation(op) for op in block.operations]
     newblock.closeblock(*[self.copy_link(link, block) for link in block.exits])
     newblock.exitswitch = self.get_new_name(block.exitswitch)
     self.search_for_calls(newblock)
     return newblock
예제 #45
0
def test_promote_2():
    v1 = varoftype(lltype.Signed)
    v2 = varoftype(lltype.Signed)
    op = SpaceOperation("hint", [v1, Constant({"promote": True}, lltype.Void)], v2)
    returnblock = Block([varoftype(lltype.Signed)])
    returnblock.operations = ()
    block = Block([v1])
    block.operations = [op]
    block.closeblock(Link([v2], returnblock))
    Transformer().optimize_block(block)
    assert len(block.operations) == 2
    assert block.operations[0].opname == "-live-"
    assert block.operations[0].args == []
    assert block.operations[1].opname == "int_guard_value"
    assert block.operations[1].args == [v1]
    assert block.operations[1].result is None
    assert block.exits[0].args == [v1]
예제 #46
0
def test_SSA_to_SSI_2():
    x = Variable('x')
    y = Variable('y')
    z = Variable('z')
    b1 = Block([x])
    b2 = Block([y])
    b3 = Block([])

    b3.operations.append(SpaceOperation('hello', [y], z))
    b1.closeblock(Link([x], b2), Link([], b3))
    graph = FunctionGraph('x', b1)
    SSA_to_SSI(graph)

    assert b1.inputargs == [x]
    assert b2.inputargs == [y]
    assert b3.inputargs == [b3.operations[0].args[0]]
    assert b1.exits[0].args == [x]
    assert b1.exits[1].args == [x]
예제 #47
0
 def transform_jump_to_except_block(self, graph, entrymap, link):
     reraise = self.comes_from_last_exception(entrymap, link)
     result = Variable()
     result.concretetype = lltype.Void
     block = Block([v.copy() for v in graph.exceptblock.inputargs])
     if reraise:
         block.operations = [
             SpaceOperation("direct_call",
                            [self.rpyexc_reraise_ptr] + block.inputargs,
                            result),
         ]
     else:
         block.operations = [
             SpaceOperation("direct_call",
                            [self.rpyexc_raise_ptr] + block.inputargs,
                            result),
             SpaceOperation('debug_record_traceback', [],
                            varoftype(lltype.Void)),
         ]
     link.target = block
     l = Link([error_constant(graph)], graph.returnblock)
     block.recloseblock(l)
예제 #48
0
파일: unsimplify.py 프로젝트: sbw111/lab4
def insert_empty_block(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] = v.copy()
    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
예제 #49
0
파일: generator.py 프로젝트: sota/pypy-old
def tweak_generator_body_graph(Entry, graph):
    # First, always run simplify_graph in order to reduce the number of
    # variables passed around
    simplify_graph(graph)
    insert_empty_startblock(graph)
    _insert_reads(graph.startblock, Entry.varnames)
    Entry.block = graph.startblock
    #
    mappings = [Entry]
    #
    stopblock = Block([])
    op0 = op.simple_call(const(StopIteration))
    op1 = op.type(op0.result)
    stopblock.operations = [op0, op1]
    stopblock.closeblock(Link([op1.result, op0.result], graph.exceptblock))
    #
    for block in list(graph.iterblocks()):
        for exit in block.exits:
            if exit.target is graph.returnblock:
                exit.args = []
                exit.target = stopblock
        assert block is not stopblock
        for index in range(len(block.operations) - 1, -1, -1):
            hlop = block.operations[index]
            if hlop.opname == 'yield_':
                [v_yielded_value] = hlop.args
                del block.operations[index]
                newlink = split_block(block, index)
                newblock = newlink.target

                #
                class Resume(AbstractPosition):
                    _immutable_ = True
                    block = newblock

                Resume.__name__ = 'Resume%d' % len(mappings)
                mappings.append(Resume)
                varnames = get_variable_names(newlink.args)
                #
                _insert_reads(newblock, varnames)
                #
                op_resume = op.simple_call(const(Resume))
                block.operations.append(op_resume)
                v_resume = op_resume.result
                for i, name in enumerate(varnames):
                    block.operations.append(
                        op.setattr(v_resume, const(name), newlink.args[i]))
                op_pair = op.newtuple(v_resume, v_yielded_value)
                block.operations.append(op_pair)
                newlink.args = [op_pair.result]
                newlink.target = graph.returnblock
    #
    regular_entry_block = Block([Variable('entry')])
    block = regular_entry_block
    for Resume in mappings:
        op_check = op.isinstance(block.inputargs[0], const(Resume))
        block.operations.append(op_check)
        block.exitswitch = op_check.result
        link1 = Link([block.inputargs[0]], Resume.block)
        link1.exitcase = True
        nextblock = Block([Variable('entry')])
        link2 = Link([block.inputargs[0]], nextblock)
        link2.exitcase = False
        block.closeblock(link1, link2)
        block = nextblock
    block.closeblock(
        Link([
            Constant(AssertionError),
            Constant(AssertionError("bad generator class"))
        ], graph.exceptblock))
    graph.startblock = regular_entry_block
    graph.signature = Signature(['entry'])
    graph.defaults = ()
    checkgraph(graph)
    eliminate_empty_blocks(graph)
예제 #50
0
 def __init__(self, framestate):
     Block.__init__(self, framestate.getvariables())
     self.framestate = framestate
     self.dead = False
예제 #51
0
    def gen_exc_check(self, block, returnblock, normalafterblock=None):
        llops = rtyper.LowLevelOpList(None)

        spaceop = block.operations[-1]
        alloc_shortcut = self.check_for_alloc_shortcut(spaceop)

        if alloc_shortcut:
            var_no_exc = self.gen_nonnull(spaceop.result, llops)
        else:
            v_exc_type = self.gen_getfield('exc_type', llops)
            var_no_exc = self.gen_isnull(v_exc_type, llops)
        #
        # We could add a "var_no_exc is likely true" hint, but it seems
        # not to help, so it was commented out again.
        #var_no_exc = llops.genop('likely', [var_no_exc], lltype.Bool)

        block.operations.extend(llops)

        block.exitswitch = var_no_exc
        #exception occurred case
        b = Block([])
        b.operations = [
            SpaceOperation('debug_record_traceback', [],
                           varoftype(lltype.Void))
        ]
        l = Link([error_constant(returnblock.inputargs[0].concretetype)],
                 returnblock)
        b.closeblock(l)
        l = Link([], b)
        l.exitcase = l.llexitcase = False

        #non-exception case
        l0 = block.exits[0]
        l0.exitcase = l0.llexitcase = True

        block.recloseblock(l0, l)
        insert_zeroing_op = False
        if spaceop.opname in ['malloc', 'malloc_varsize']:
            flavor = spaceop.args[1].value['flavor']
            if flavor == 'gc':
                insert_zeroing_op = True
            true_zero = spaceop.args[1].value.get('zero', False)
        # NB. when inserting more special-cases here, keep in mind that
        # you also need to list the opnames in transform_block()
        # (see "special cases")

        if insert_zeroing_op:
            if normalafterblock is None:
                normalafterblock = insert_empty_block(None, l0)
            v_result = spaceop.result
            if v_result in l0.args:
                result_i = l0.args.index(v_result)
                v_result_after = normalafterblock.inputargs[result_i]
            else:
                v_result_after = v_result.copy()
                l0.args.append(v_result)
                normalafterblock.inputargs.append(v_result_after)
            if true_zero:
                opname = "zero_everything_inside"
            else:
                opname = "zero_gc_pointers_inside"
            normalafterblock.operations.insert(
                0,
                SpaceOperation(opname, [v_result_after],
                               varoftype(lltype.Void)))
예제 #52
0
 def __init__(self, inputargs, prevblock, booloutcome):
     Block.__init__(self, inputargs)
     self.prevblock = prevblock
     self.booloutcome = booloutcome
예제 #53
0
파일: asmgcroot.py 프로젝트: sota/pypy-old
 def _transform_hint_close_stack(self, fnptr):
     # We cannot easily pass variable amount of arguments of the call
     # across the call to the pypy_asm_stackwalk helper.  So we store
     # them away and restore them.  More precisely, we need to
     # replace 'graph' with code that saves the arguments, and make
     # a new graph that starts with restoring the arguments.
     if self._asmgcc_save_restore_arguments is None:
         self._asmgcc_save_restore_arguments = {}
     sradict = self._asmgcc_save_restore_arguments
     sra = []  # list of pointers to raw-malloced containers for args
     seen = {}
     FUNC1 = lltype.typeOf(fnptr).TO
     for TYPE in FUNC1.ARGS:
         if isinstance(TYPE, lltype.Ptr):
             TYPE = llmemory.Address
         num = seen.get(TYPE, 0)
         seen[TYPE] = num + 1
         key = (TYPE, num)
         if key not in sradict:
             CONTAINER = lltype.FixedSizeArray(TYPE, 1)
             p = lltype.malloc(CONTAINER,
                               flavor='raw',
                               zero=True,
                               immortal=True)
             sradict[key] = Constant(p, lltype.Ptr(CONTAINER))
         sra.append(sradict[key])
     #
     # make a copy of the graph that will reload the values
     graph = fnptr._obj.graph
     graph2 = copygraph(graph)
     #
     # edit the original graph to only store the value of the arguments
     block = Block(graph.startblock.inputargs)
     c_item0 = Constant('item0', lltype.Void)
     assert len(block.inputargs) == len(sra)
     for v_arg, c_p in zip(block.inputargs, sra):
         if isinstance(v_arg.concretetype, lltype.Ptr):
             v_adr = varoftype(llmemory.Address)
             block.operations.append(
                 SpaceOperation("cast_ptr_to_adr", [v_arg], v_adr))
             v_arg = v_adr
         v_void = varoftype(lltype.Void)
         block.operations.append(
             SpaceOperation("bare_setfield", [c_p, c_item0, v_arg], v_void))
     #
     # call asm_stackwalk(graph2)
     FUNC2 = lltype.FuncType([], FUNC1.RESULT)
     fnptr2 = lltype.functionptr(FUNC2,
                                 fnptr._obj._name + '_reload',
                                 graph=graph2)
     c_fnptr2 = Constant(fnptr2, lltype.Ptr(FUNC2))
     HELPERFUNC = lltype.FuncType(
         [lltype.Ptr(FUNC2), ASM_FRAMEDATA_HEAD_PTR], FUNC1.RESULT)
     v_asm_stackwalk = varoftype(lltype.Ptr(HELPERFUNC), "asm_stackwalk")
     block.operations.append(
         SpaceOperation("cast_pointer", [c_asm_stackwalk], v_asm_stackwalk))
     v_result = varoftype(FUNC1.RESULT)
     block.operations.append(
         SpaceOperation("indirect_call", [
             v_asm_stackwalk, c_fnptr2, c_gcrootanchor,
             Constant(None, lltype.Void)
         ], v_result))
     block.closeblock(Link([v_result], graph.returnblock))
     graph.startblock = block
     #
     # edit the copy of the graph to reload the values
     block2 = graph2.startblock
     block1 = Block([])
     reloadedvars = []
     for v, c_p in zip(block2.inputargs, sra):
         v = v.copy()
         if isinstance(v.concretetype, lltype.Ptr):
             w = varoftype(llmemory.Address)
         else:
             w = v
         block1.operations.append(
             SpaceOperation('getfield', [c_p, c_item0], w))
         if w is not v:
             block1.operations.append(
                 SpaceOperation('cast_adr_to_ptr', [w], v))
         reloadedvars.append(v)
     block1.closeblock(Link(reloadedvars, block2))
     graph2.startblock = block1
     #
     checkgraph(graph)
     checkgraph(graph2)
예제 #54
0
class BlockSpecializer(object):
    def __init__(self, graphbuilder, v_expand_malloc=None):
        self.graphbuilder = graphbuilder
        self.v_expand_malloc = v_expand_malloc
        self.specblock = Block([])

    def initialize_renamings(self, virtualframe, keep_inputargs=False):
        # we make a copy of the original 'virtualframe' because the
        # specialize_operations() will mutate some of its content.
        virtualframe = virtualframe.copy({})
        self.virtualframe = virtualframe
        self.nodes = virtualframe.get_nodes_in_use()
        self.renamings = {}  # {RuntimeSpecNode(): Variable()}
        if keep_inputargs:
            assert virtualframe.varlist == virtualframe.sourceblock.inputargs
        specinputargs = []
        for i, rtnode in enumerate(virtualframe.find_rt_nodes()):
            if keep_inputargs:
                v = virtualframe.varlist[i]
                assert v.concretetype == rtnode.TYPE
            else:
                v = rtnode.newvar()
            self.renamings[rtnode] = v
            specinputargs.append(v)
        self.specblock.inputargs = specinputargs

    def setnode(self, v, node):
        assert v not in self.nodes
        self.nodes[v] = node

    def getnode(self, v):
        if isinstance(v, Variable):
            return self.nodes[v]
        else:
            return getconstnode(v, self.renamings)

    def rename_nonvirtual(self, v, where=None):
        if not isinstance(v, Variable):
            return v
        node = self.nodes[v]
        if not isinstance(node, RuntimeSpecNode):
            raise CannotVirtualize(where)
        return self.renamings[node]

    def expand_nodes(self, nodelist):
        rtnodes, vtnodes = find_all_nodes(nodelist)
        return [self.renamings[rtnode] for rtnode in rtnodes]

    def specialize_operations(self):
        newoperations = []
        self.ops_produced_by_last_op = 0
        # note that 'self.virtualframe' can be changed during the loop!
        while True:
            operations = self.virtualframe.sourceblock.operations
            try:
                op = operations[self.virtualframe.nextopindex]
                self.virtualframe.nextopindex += 1
            except IndexError:
                break

            meth = getattr(self, 'handle_op_' + op.opname, self.handle_default)
            newops_for_this_op = meth(op)
            newoperations += newops_for_this_op
            self.ops_produced_by_last_op = len(newops_for_this_op)
        for op in newoperations:
            if op.opname == 'direct_call':
                graph = graph_called_by(op)
                if graph in self.virtualframe.calledgraphs:
                    raise CannotVirtualize("recursion in residual call")
        self.specblock.operations = newoperations

    def follow_exits(self):
        block = self.virtualframe.sourceblock
        self.specblock.exitswitch = self.rename_nonvirtual(
            block.exitswitch, 'exitswitch')
        links = block.exits
        catch_exc = self.specblock.exitswitch == c_last_exception

        if not catch_exc and isinstance(self.specblock.exitswitch, Constant):
            # constant-fold the switch
            for link in links:
                if link.exitcase == 'default':
                    break
                if link.llexitcase == self.specblock.exitswitch.value:
                    break
            else:
                raise Exception("exit case not found?")
            links = (link, )
            self.specblock.exitswitch = None

        if catch_exc and self.ops_produced_by_last_op == 0:
            # the last op of the sourceblock did not produce any
            # operation in specblock, so we need to discard the
            # exception-catching.
            catch_exc = False
            links = links[:1]
            assert links[0].exitcase is None  # the non-exception-catching case
            self.specblock.exitswitch = None

        newlinks = []
        for link in links:
            is_catch_link = catch_exc and link.exitcase is not None
            if is_catch_link:
                extravars = []
                for attr in ['last_exception', 'last_exc_value']:
                    v = getattr(link, attr)
                    if isinstance(v, Variable):
                        rtnode = RuntimeSpecNode(v, v.concretetype)
                        self.setnode(v, rtnode)
                        self.renamings[rtnode] = v = rtnode.newvar()
                    extravars.append(v)

            linkargsnodes = [self.getnode(v1) for v1 in link.args]
            #
            newlink = self.graphbuilder.create_outgoing_link(
                self.virtualframe, link.target, linkargsnodes, self.renamings,
                self.v_expand_malloc)
            #
            if self.specblock.exitswitch is not None:
                newlink.exitcase = link.exitcase
                if hasattr(link, 'llexitcase'):
                    newlink.llexitcase = link.llexitcase
                if is_catch_link:
                    newlink.extravars(*extravars)
            newlinks.append(newlink)

        self.specblock.closeblock(*newlinks)

    def make_rt_result(self, v_result):
        newrtnode = RuntimeSpecNode(v_result, v_result.concretetype)
        self.setnode(v_result, newrtnode)
        v_new = newrtnode.newvar()
        self.renamings[newrtnode] = v_new
        return v_new

    def make_const_rt_result(self, v_result, value):
        newrtnode = RuntimeSpecNode(v_result, v_result.concretetype)
        self.setnode(v_result, newrtnode)
        if v_result.concretetype is not lltype.Void:
            assert v_result.concretetype == lltype.typeOf(value)
        c_value = Constant(value)
        c_value.concretetype = v_result.concretetype
        self.renamings[newrtnode] = c_value

    def handle_default(self, op):
        newargs = [self.rename_nonvirtual(v, op) for v in op.args]
        constresult = try_fold_operation(op.opname, newargs,
                                         op.result.concretetype)
        if constresult:
            self.make_const_rt_result(op.result, constresult[0])
            return []
        else:
            newresult = self.make_rt_result(op.result)
            return [SpaceOperation(op.opname, newargs, newresult)]

    def handle_unreachable(self, op):
        from rpython.rtyper.lltypesystem.rstr import string_repr
        msg = 'unreachable: %s' % (op, )
        ll_msg = string_repr.convert_const(msg)
        c_msg = Constant(ll_msg, lltype.typeOf(ll_msg))
        newresult = self.make_rt_result(op.result)
        return [SpaceOperation('debug_fatalerror', [c_msg], newresult)]

    def handle_op_getfield(self, op):
        node = self.getnode(op.args[0])
        if isinstance(node, VirtualSpecNode):
            fieldname = op.args[1].value
            index = node.typedesc.name2index[fieldname]
            self.setnode(op.result, node.fields[index])
            return []
        else:
            return self.handle_default(op)

    def handle_op_setfield(self, op):
        node = self.getnode(op.args[0])
        if isinstance(node, VirtualSpecNode):
            if node.readonly:
                raise ForcedInline(op)
            fieldname = op.args[1].value
            index = node.typedesc.name2index[fieldname]
            node.fields[index] = self.getnode(op.args[2])
            return []
        else:
            return self.handle_default(op)

    def handle_op_same_as(self, op):
        node = self.getnode(op.args[0])
        if isinstance(node, VirtualSpecNode):
            node = self.getnode(op.args[0])
            self.setnode(op.result, node)
            return []
        else:
            return self.handle_default(op)

    def handle_op_cast_pointer(self, op):
        node = self.getnode(op.args[0])
        if isinstance(node, VirtualSpecNode):
            node = self.getnode(op.args[0])
            SOURCEPTR = lltype.Ptr(node.typedesc.MALLOCTYPE)
            TARGETPTR = op.result.concretetype
            try:
                if lltype.castable(TARGETPTR, SOURCEPTR) < 0:
                    raise lltype.InvalidCast
            except lltype.InvalidCast:
                return self.handle_unreachable(op)
            self.setnode(op.result, node)
            return []
        else:
            return self.handle_default(op)

    def handle_op_ptr_nonzero(self, op):
        node = self.getnode(op.args[0])
        if isinstance(node, VirtualSpecNode):
            self.make_const_rt_result(op.result, True)
            return []
        else:
            return self.handle_default(op)

    def handle_op_ptr_iszero(self, op):
        node = self.getnode(op.args[0])
        if isinstance(node, VirtualSpecNode):
            self.make_const_rt_result(op.result, False)
            return []
        else:
            return self.handle_default(op)

    def handle_op_ptr_eq(self, op):
        node0 = self.getnode(op.args[0])
        node1 = self.getnode(op.args[1])
        if (isinstance(node0, VirtualSpecNode)
                or isinstance(node1, VirtualSpecNode)):
            self.make_const_rt_result(op.result, node0 is node1)
            return []
        else:
            return self.handle_default(op)

    def handle_op_ptr_ne(self, op):
        node0 = self.getnode(op.args[0])
        node1 = self.getnode(op.args[1])
        if (isinstance(node0, VirtualSpecNode)
                or isinstance(node1, VirtualSpecNode)):
            self.make_const_rt_result(op.result, node0 is not node1)
            return []
        else:
            return self.handle_default(op)

    def handle_op_malloc(self, op):
        if op.result is self.v_expand_malloc:
            MALLOCTYPE = op.result.concretetype.TO
            typedesc = self.graphbuilder.mallocv.getmalloctypedesc(MALLOCTYPE)
            virtualnode = VirtualSpecNode(typedesc, [])
            self.setnode(op.result, virtualnode)
            for name, FIELDTYPE in typedesc.names_and_types:
                fieldnode = RuntimeSpecNode(name, FIELDTYPE)
                virtualnode.fields.append(fieldnode)
                c = Constant(FIELDTYPE._defl())
                c.concretetype = FIELDTYPE
                self.renamings[fieldnode] = c
            self.v_expand_malloc = None  # done
            return []
        else:
            return self.handle_default(op)

    def handle_op_direct_call(self, op):
        graph = graph_called_by(op)
        if graph is None:
            return self.handle_default(op)
        nb_args = len(op.args) - 1
        assert nb_args == len(graph.getargs())
        newnodes = [self.getnode(v) for v in op.args[1:]]
        myframe = self.get_updated_frame(op)
        mallocv = self.graphbuilder.mallocv

        if op.result is self.v_expand_malloc:
            # move to inlining the callee, and continue looking for the
            # malloc to expand in the callee's graph
            op_to_remove = mallocv.inline_and_remove[graph]
            self.v_expand_malloc = op_to_remove.result
            return self.handle_inlined_call(myframe, graph, newnodes)

        argnodes = copynodes(newnodes, flagreadonly=myframe.find_vt_nodes())
        kind, newgraph = mallocv.get_specialized_graph(graph, argnodes)
        if kind == 'trivial':
            return self.handle_default(op)
        elif kind == 'inline':
            return self.handle_inlined_call(myframe, graph, newnodes)
        elif kind == 'call':
            return self.handle_residual_call(op, newgraph, newnodes)
        elif kind == 'fail':
            raise CannotVirtualize(op)
        else:
            raise ValueError(kind)

    def get_updated_frame(self, op):
        sourceblock = self.virtualframe.sourceblock
        nextopindex = self.virtualframe.nextopindex
        self.nodes[op.result] = FutureReturnValue(op)
        myframe = VirtualFrame(sourceblock, nextopindex, self.nodes,
                               self.virtualframe.callerframe,
                               self.virtualframe.calledgraphs)
        del self.nodes[op.result]
        return myframe

    def handle_residual_call(self, op, newgraph, newnodes):
        fspecptr = getfunctionptr(newgraph)
        newargs = [Constant(fspecptr, concretetype=lltype.typeOf(fspecptr))]
        newargs += self.expand_nodes(newnodes)
        newresult = self.make_rt_result(op.result)
        newop = SpaceOperation('direct_call', newargs, newresult)
        return [newop]

    def handle_inlined_call(self, myframe, graph, newnodes):
        assert len(graph.getargs()) == len(newnodes)
        targetnodes = dict(zip(graph.getargs(), newnodes))
        calledgraphs = myframe.calledgraphs.copy()
        if graph in calledgraphs:
            raise CannotVirtualize("recursion during inlining")
        calledgraphs[graph] = True
        calleeframe = VirtualFrame(graph.startblock, 0, targetnodes, myframe,
                                   calledgraphs)
        self.virtualframe = calleeframe
        self.nodes = calleeframe.get_nodes_in_use()
        return []

    def handle_op_indirect_call(self, op):
        v_func = self.rename_nonvirtual(op.args[0], op)
        if isinstance(v_func, Constant):
            op = SpaceOperation('direct_call', [v_func] + op.args[1:-1],
                                op.result)
            return self.handle_op_direct_call(op)
        else:
            return self.handle_default(op)
예제 #55
0
파일: unsimplify.py 프로젝트: sbw111/lab4
def split_block(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 = set()

    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] = var.copy()
        return varmap[var]

    moved_operations = block.operations[index:]
    new_moved_ops = []
    for op in moved_operations:
        repl = dict((arg, get_new_name(arg)) for arg in op.args)
        newop = op.replace(repl)
        new_moved_ops.append(newop)
        vars_produced_in_new_block.add(op.result)
    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 rpython.rtyper.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
예제 #56
0
def normalize_calltable_row_signature(annotator, shape, row):
    graphs = row.values()
    assert graphs, "no graph??"
    sig0 = graphs[0].signature
    defaults0 = graphs[0].defaults
    for graph in graphs[1:]:
        if graph.signature != sig0:
            break
        if graph.defaults != defaults0:
            break
    else:
        return False  # nothing to do, all signatures already match

    shape_cnt, shape_keys, shape_star = shape
    assert not shape_star, "should have been removed at this stage"

    # for the first 'shape_cnt' arguments we need to generalize to
    # a common type
    call_nbargs = shape_cnt + len(shape_keys)

    did_something = False

    for graph in graphs:
        argnames, varargname, kwargname = graph.signature
        assert not varargname, "XXX not implemented"
        assert not kwargname, "XXX not implemented"  # ?
        inputargs_s = [annotator.binding(v) for v in graph.getargs()]
        argorder = range(shape_cnt)
        for key in shape_keys:
            i = list(argnames).index(key)
            assert i not in argorder
            argorder.append(i)
        need_reordering = (argorder != range(call_nbargs))
        if need_reordering or len(graph.getargs()) != call_nbargs:
            oldblock = graph.startblock
            inlist = []
            defaults = graph.defaults or ()
            num_nondefaults = len(inputargs_s) - len(defaults)
            defaults = [description.NODEFAULT
                        ] * num_nondefaults + list(defaults)
            newdefaults = []
            for j in argorder:
                v = Variable(graph.getargs()[j])
                annotator.setbinding(v, inputargs_s[j])
                inlist.append(v)
                newdefaults.append(defaults[j])
            newblock = Block(inlist)
            # prepare the output args of newblock:
            # 1. collect the positional arguments
            outlist = inlist[:shape_cnt]
            # 2. add defaults and keywords
            for j in range(shape_cnt, len(inputargs_s)):
                try:
                    i = argorder.index(j)
                    v = inlist[i]
                except ValueError:
                    default = defaults[j]
                    if default is description.NODEFAULT:
                        raise TyperError(
                            "call pattern has %d positional arguments, "
                            "but %r takes at least %d arguments" %
                            (shape_cnt, graph.name, num_nondefaults))
                    v = Constant(default)
                outlist.append(v)
            newblock.closeblock(Link(outlist, oldblock))
            graph.startblock = newblock
            for i in range(len(newdefaults) - 1, -1, -1):
                if newdefaults[i] is description.NODEFAULT:
                    newdefaults = newdefaults[i:]
                    break
            graph.defaults = tuple(newdefaults)
            graph.signature = Signature([argnames[j] for j in argorder], None,
                                        None)
            # finished
            checkgraph(graph)
            annotator.annotated[newblock] = annotator.annotated[oldblock]
            did_something = True
    return did_something
예제 #57
0
 def __init__(self, graphbuilder, v_expand_malloc=None):
     self.graphbuilder = graphbuilder
     self.v_expand_malloc = v_expand_malloc
     self.specblock = Block([])
예제 #58
0
파일: unsimplify.py 프로젝트: sbw111/lab4
def insert_empty_startblock(graph):
    vars = [v.copy() for v in graph.startblock.inputargs]
    newblock = Block(vars)
    newblock.closeblock(Link(vars, graph.startblock))
    graph.startblock = newblock