コード例 #1
0
    def rtype(self, fn, argtypes, resulttype, checkfunction=None):
        t = TranslationContext()
        a = t.buildannotator()
        a.build_types(prefn, [int])
        typer = t.buildrtyper()
        typer.specialize()
        #t.view()

        s_result = a.typeannotation(resulttype)

        from rpython.rtyper import annlowlevel
        # annotate, normalize and rtype fn after the fact
        annhelper = annlowlevel.MixLevelHelperAnnotator(typer)
        graph = annhelper.getgraph(
            fn, [a.typeannotation(argtype) for argtype in argtypes], s_result)
        annhelper.finish()
        t.checkgraphs()

        if checkfunction is not None:
            checkfunction(t)

        # sanity check prefn
        llinterp = LLInterpreter(typer)
        res = llinterp.eval_graph(graphof(t, prefn), [1])
        assert res == 100
        res = llinterp.eval_graph(graphof(t, prefn), [2])
        assert res == 201

        return t
コード例 #2
0
ファイル: test_removenoops.py プロジェクト: zielmicha/pypy
def test_remove_same_as_nonconst():
    from rpython.rlib.nonconst import NonConstant
    from rpython.rtyper.lltypesystem.lloperation import llop
    from rpython.rtyper.lltypesystem import lltype

    def f():
        if NonConstant(False):
            x = llop.same_as(lltype.Signed, 666)
        return 42

    t = TranslationContext()
    t.buildannotator().build_types(f, [])
    t.buildrtyper().specialize()
    f_graph = graphof(t, f)
    #simple_inline_function(t, nothing, f_graph)
    # here, the graph looks like  v21=same_as(True);  exitswitch: v21
    remove_same_as(f_graph)
    t.checkgraphs()
    # only one path should be left
    for block in f_graph.iterblocks():
        assert len(block.exits) <= 1

    for block in t.annotator.annotated:
        assert None not in block.operations

    interp = LLInterpreter(t.rtyper)
    result = interp.eval_graph(f_graph, [])
    assert result == 42
コード例 #3
0
ファイル: test_removenoops.py プロジェクト: cimarieta/usp
def test_remove_same_as():
    def nothing(x):
        return x

    def f():
        nothing(False)
        if nothing(True):
            return 42
        else:
            return 666

    t = TranslationContext()
    t.buildannotator().build_types(f, [])
    t.buildrtyper().specialize()
    # now we make the 'if True' appear
    f_graph = graphof(t, f)
    simple_inline_function(t, nothing, f_graph)
    # here, the graph looks like  v21=same_as(True);  exitswitch: v21
    remove_same_as(f_graph)
    t.checkgraphs()
    # only one path should be left
    for block in f_graph.iterblocks():
        assert len(block.exits) <= 1

    interp = LLInterpreter(t.rtyper)
    result = interp.eval_graph(f_graph, [])
    assert result == 42
コード例 #4
0
 def translates(self, func=None, argtypes=None, seeobj_w=[], **kwds):
     config = make_config(None, **kwds)
     if func is not None:
         if argtypes is None:
             nb_args = func.func_code.co_argcount
             argtypes = [W_Root] * nb_args
     #
     t = TranslationContext(config=config)
     self.t = t     # for debugging
     ann = t.buildannotator()
     def _do_startup():
         self.threadlocals.enter_thread(self)
         W_SliceObject(w_some_obj(), w_some_obj(), w_some_obj())
     ann.build_types(_do_startup, [], complete_now=False)
     if func is not None:
         ann.build_types(func, argtypes, complete_now=False)
     if seeobj_w:
         def seeme(n):
             return seeobj_w[n]
         ann.build_types(seeme, [int], complete_now=False)
     #
     # annotate all _seen_extras, knowing that annotating some may
     # grow the list
     done = 0
     while done < len(self._seen_extras):
         #print self._seen_extras
         ann.build_types(self._seen_extras[done], [],
                         complete_now=False)
         ann.complete_pending_blocks()
         done += 1
     ann.complete()
     assert done == len(self._seen_extras)
     #t.viewcg()
     t.buildrtyper().specialize()
     t.checkgraphs()
コード例 #5
0
ファイル: test_removenoops.py プロジェクト: cimarieta/usp
def test_remove_same_as_nonconst():
    from rpython.rlib.nonconst import NonConstant
    from rpython.rtyper.lltypesystem.lloperation import llop
    from rpython.rtyper.lltypesystem import lltype

    def f():
        if NonConstant(False):
            x = llop.same_as(lltype.Signed, 666)
        return 42

    t = TranslationContext()
    t.buildannotator().build_types(f, [])
    t.buildrtyper().specialize()
    f_graph = graphof(t, f)
    # simple_inline_function(t, nothing, f_graph)
    # here, the graph looks like  v21=same_as(True);  exitswitch: v21
    remove_same_as(f_graph)
    t.checkgraphs()
    # only one path should be left
    for block in f_graph.iterblocks():
        assert len(block.exits) <= 1

    for block in t.annotator.annotated:
        assert None not in block.operations

    interp = LLInterpreter(t.rtyper)
    result = interp.eval_graph(f_graph, [])
    assert result == 42
コード例 #6
0
def gengraph(func,
             argtypes=[],
             viewbefore='auto',
             policy=None,
             backendopt=False,
             config=None,
             **extraconfigopts):
    t = TranslationContext(config=config)
    t.config.set(**extraconfigopts)
    a = t.buildannotator(policy=policy)
    a.build_types(func, argtypes, main_entry_point=True)
    a.validate()
    if viewbefore == 'auto':
        viewbefore = getattr(option, 'view', False)
    if viewbefore:
        a.simplify()
        t.view()
    global typer  # we need it for find_exception
    typer = t.buildrtyper()
    typer.backend = llinterp_backend
    typer.specialize()
    #t.view()
    t.checkgraphs()
    if backendopt:
        from rpython.translator.backendopt.all import backend_optimizations
        backend_optimizations(t)
        t.checkgraphs()
        if viewbefore:
            t.view()
    desc = t.annotator.bookkeeper.getdesc(func)
    graph = desc.specialize(argtypes)
    return t, typer, graph
コード例 #7
0
ファイル: test_llinterp.py プロジェクト: abhinavthomas/pypy
def gengraph(func, argtypes=[], viewbefore='auto', policy=None,
             backendopt=False, config=None, **extraconfigopts):
    t = TranslationContext(config=config)
    t.config.set(**extraconfigopts)
    a = t.buildannotator(policy=policy)
    a.build_types(func, argtypes, main_entry_point=True)
    a.validate()
    if viewbefore == 'auto':
        viewbefore = getattr(option, 'view', False)
    if viewbefore:
        a.simplify()
        t.view()
    global typer # we need it for find_exception
    typer = t.buildrtyper()
    typer.backend = llinterp_backend
    typer.specialize()
    #t.view()
    t.checkgraphs()
    if backendopt:
        from rpython.translator.backendopt.all import backend_optimizations
        backend_optimizations(t)
        t.checkgraphs()
        if viewbefore:
            t.view()
    desc = t.annotator.bookkeeper.getdesc(func)
    graph = desc.specialize(argtypes)
    return t, typer, graph
コード例 #8
0
ファイル: test_normalizecalls.py プロジェクト: yuyichao/pypy
    def rtype(self, fn, argtypes, resulttype, checkfunction=None):
        t = TranslationContext()
        a = t.buildannotator()
        a.build_types(prefn, [int])
        typer = t.buildrtyper()
        typer.specialize()
        #t.view()

        s_result = a.typeannotation(resulttype)

        from rpython.rtyper import annlowlevel
        # annotate, normalize and rtype fn after the fact
        annhelper = annlowlevel.MixLevelHelperAnnotator(typer)
        graph = annhelper.getgraph(fn, [a.typeannotation(argtype) for argtype in argtypes],
                                   s_result)
        annhelper.finish()
        t.checkgraphs()

        if checkfunction is not None:
            checkfunction(t)

        # sanity check prefn
        llinterp = LLInterpreter(typer)
        res = llinterp.eval_graph(graphof(t, prefn), [1])
        assert res == 100
        res = llinterp.eval_graph(graphof(t, prefn), [2])
        assert res == 201

        return t
コード例 #9
0
ファイル: test_mallocv.py プロジェクト: cimarieta/usp
 def check(self, fn, signature, args, expected_result, expected_mallocs=0, expected_calls=0):
     t = TranslationContext()
     self.translator = t
     t.buildannotator().build_types(fn, signature)
     t.buildrtyper().specialize()
     graph = graphof(t, fn)
     if option.view:
         t.view()
     self.original_graph_count = len(t.graphs)
     # to detect broken intermediate graphs,
     # we do the loop ourselves instead of calling remove_simple_mallocs()
     maxiter = 100
     mallocv = MallocVirtualizer(t.graphs, t.rtyper, verbose=True)
     while True:
         progress = mallocv.remove_mallocs_once()
         if progress and option.view:
             t.view()
         t.checkgraphs()
         if expected_result is not DONT_CHECK_RESULT:
             interp = LLInterpreter(t.rtyper)
             if not isinstance(expected_result, CHECK_RAISES):
                 res = interp.eval_graph(graph, args)
                 assert res == expected_result
             else:
                 excinfo = py.test.raises(LLException, interp.eval_graph, graph, args)
                 assert expected_result.excname in str(excinfo.value)
         if not progress:
             break
         maxiter -= 1
         assert maxiter > 0, "infinite loop?"
     self.check_malloc_removed(graph, expected_mallocs, expected_calls)
     return graph
コード例 #10
0
ファイル: test_removenoops.py プロジェクト: zielmicha/pypy
def test_remove_same_as():
    def nothing(x):
        return x

    def f():
        nothing(False)
        if nothing(True):
            return 42
        else:
            return 666

    t = TranslationContext()
    t.buildannotator().build_types(f, [])
    t.buildrtyper().specialize()
    # now we make the 'if True' appear
    f_graph = graphof(t, f)
    simple_inline_function(t, nothing, f_graph)
    # here, the graph looks like  v21=same_as(True);  exitswitch: v21
    remove_same_as(f_graph)
    t.checkgraphs()
    # only one path should be left
    for block in f_graph.iterblocks():
        assert len(block.exits) <= 1

    interp = LLInterpreter(t.rtyper)
    result = interp.eval_graph(f_graph, [])
    assert result == 42
コード例 #11
0
ファイル: objspace.py プロジェクト: mozillazg/pypy
 def translates(self, func=None, argtypes=None, seeobj_w=[], **kwds):
     config = make_config(None, **kwds)
     if func is not None:
         if argtypes is None:
             nb_args = func.func_code.co_argcount
             argtypes = [W_Root] * nb_args
     #
     t = TranslationContext(config=config)
     self.t = t     # for debugging
     ann = t.buildannotator()
     def _do_startup():
         self.threadlocals.enter_thread(self)
     ann.build_types(_do_startup, [], complete_now=False)
     if func is not None:
         ann.build_types(func, argtypes, complete_now=False)
     if seeobj_w:
         def seeme(n):
             return seeobj_w[n]
         ann.build_types(seeme, [int], complete_now=False)
     #
     # annotate all _seen_extras, knowing that annotating some may
     # grow the list
     done = 0
     while done < len(self._seen_extras):
         #print self._seen_extras
         ann.build_types(self._seen_extras[done], [],
                         complete_now=False)
         ann.complete_pending_blocks()
         done += 1
     ann.complete()
     assert done == len(self._seen_extras)
     #t.viewcg()
     t.buildrtyper().specialize()
     t.checkgraphs()
コード例 #12
0
ファイル: test_exception.py プロジェクト: soIu/rpython
def rtype(fn, argtypes=[]):
    t = TranslationContext()
    t.buildannotator().build_types(fn, argtypes)
    typer = t.buildrtyper()
    typer.specialize()
    #t.view()
    t.checkgraphs()
    return t
コード例 #13
0
ファイル: test_exception.py プロジェクト: mozillazg/pypy
def rtype(fn, argtypes=[]):
    t = TranslationContext()
    t.buildannotator().build_types(fn, argtypes)
    typer = t.buildrtyper()
    typer.specialize()
    #t.view()
    t.checkgraphs()
    return t
コード例 #14
0
 def rtype(self, fn, argtypes, resulttype):
     t = TranslationContext()
     a = t.buildannotator()
     s = a.build_types(fn, argtypes)
     assert s == a.typeannotation(resulttype)
     typer = t.buildrtyper()
     typer.specialize()
     #t.view()
     t.checkgraphs()
     return t
コード例 #15
0
ファイル: test_normalizecalls.py プロジェクト: yuyichao/pypy
 def rtype(self, fn, argtypes, resulttype):
     t = TranslationContext()
     a = t.buildannotator()
     s = a.build_types(fn, argtypes)
     assert s == a.typeannotation(resulttype)
     typer = t.buildrtyper()
     typer.specialize()
     #t.view()
     t.checkgraphs()
     return t
コード例 #16
0
ファイル: test_rtyper.py プロジェクト: charred/pypy
def test_retval_None():
    def f(x):
        pass
    t = TranslationContext()
    t.buildannotator().build_types(f, [int])
    t.buildrtyper().specialize()
    #t.view()
    t.checkgraphs()
    graph = graphof(t, f)
    assert graph.getreturnvar().concretetype == Void
    assert graph.startblock.exits[0].args[0].concretetype == Void
コード例 #17
0
ファイル: test_rtyper.py プロジェクト: sota/pypy-old
def test_retval_None():
    def f(x):
        pass

    t = TranslationContext()
    t.buildannotator().build_types(f, [int])
    t.buildrtyper().specialize()
    #t.view()
    t.checkgraphs()
    graph = graphof(t, f)
    assert graph.getreturnvar().concretetype == Void
    assert graph.startblock.exits[0].args[0].concretetype == Void
コード例 #18
0
    def translates(self,
                   func=None,
                   argtypes=None,
                   seeobj_w=[],
                   extra_func=None,
                   c_compile=False,
                   **kwds):
        config = make_config(None, **kwds)
        if func is not None:
            if argtypes is None:
                nb_args = func.func_code.co_argcount
                argtypes = [W_Root] * nb_args
        #
        t = TranslationContext(config=config)
        self.t = t  # for debugging
        ann = t.buildannotator()

        def entry_point(argv):
            self.threadlocals.enter_thread(self)
            W_SliceObject(w_some_obj(), w_some_obj(), w_some_obj())
            if extra_func:
                extra_func(self)
            return 0

        ann.build_types(entry_point, [s_list_of_strings], complete_now=False)
        if func is not None:
            ann.build_types(func, argtypes, complete_now=False)
        if seeobj_w:

            def seeme(n):
                return seeobj_w[n]

            ann.build_types(seeme, [int], complete_now=False)
        #
        # annotate all _seen_extras, knowing that annotating some may
        # grow the list
        done = 0
        while done < len(self._seen_extras):
            #print self._seen_extras
            ann.build_types(self._seen_extras[done], [], complete_now=False)
            ann.complete_pending_blocks()
            done += 1
        ann.complete()
        assert done == len(self._seen_extras)
        #t.viewcg()
        t.buildrtyper().specialize()
        t.checkgraphs()
        if c_compile:
            cbuilder = CStandaloneBuilder(t, entry_point, t.config)
            cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES)
            cbuilder.compile()
            return t, cbuilder
コード例 #19
0
ファイル: test_stackcheck.py プロジェクト: cimarieta/usp
def test_simple():
    t = TranslationContext()
    a = t.buildannotator()
    a.build_types(g, [int])
    a.simplify()
    t.buildrtyper().specialize()
    backend_optimizations(t)
    t.checkgraphs()
    n = insert_ll_stackcheck(t)
    t.checkgraphs()
    assert n == 1
    if option.view:
        t.view()
    check(graphof(t, f), "f")
コード例 #20
0
ファイル: test_stackcheck.py プロジェクト: sbw111/lab4
def test_simple():
    t = TranslationContext()
    a = t.buildannotator()
    a.build_types(g, [int])
    a.simplify()
    t.buildrtyper().specialize()
    backend_optimizations(t)
    t.checkgraphs()
    n = insert_ll_stackcheck(t)
    t.checkgraphs()
    assert n == 1
    if option.view:
        t.view()
    check(graphof(t, f), 'f')
コード例 #21
0
ファイル: test_removenoops.py プロジェクト: mozillazg/pypy
def test_remove_unaryops():
    # We really want to use remove_unaryops for more complex operations, but
    # it's easier to test it with operations on ints here.
    def f(x):
        i = llop.int_invert(lltype.Signed, x)
        i = llop.int_add(lltype.Signed, x, 1)
        return llop.int_neg(lltype.Signed, i)
    t = TranslationContext()
    t.buildannotator().build_types(f, [int])
    t.buildrtyper().specialize()
    f_graph = graphof(t, f)
    remove_unaryops(f_graph, ["int_neg", "int_invert"])
    t.checkgraphs()

    interp = LLInterpreter(t.rtyper)
    result = interp.eval_graph(f_graph, [-2])
    assert result == -1
コード例 #22
0
ファイル: test_removenoops.py プロジェクト: zielmicha/pypy
def test_remove_unaryops():
    # We really want to use remove_unaryops for more complex operations, but
    # it's easier to test it with operations on ints here.
    def f(x):
        i = llop.int_invert(lltype.Signed, x)
        i = llop.int_add(lltype.Signed, x, 1)
        return llop.int_neg(lltype.Signed, i)

    t = TranslationContext()
    t.buildannotator().build_types(f, [int])
    t.buildrtyper().specialize()
    f_graph = graphof(t, f)
    remove_unaryops(f_graph, ["int_neg", "int_invert"])
    t.checkgraphs()

    interp = LLInterpreter(t.rtyper)
    result = interp.eval_graph(f_graph, [-2])
    assert result == -1
コード例 #23
0
ファイル: test_stackcheck.py プロジェクト: sbw111/lab4
def test_gctransformed():
    t = TranslationContext()
    a = t.buildannotator()
    a.build_types(g, [int])
    a.simplify()
    t.buildrtyper().specialize()
    backend_optimizations(t)
    t.checkgraphs()
    n = insert_ll_stackcheck(t)
    t.checkgraphs()
    assert n == 1
    exctransf = t.getexceptiontransformer()
    f_graph = graphof(t, f)
    exctransf.create_exception_handling(f_graph)
    if option.view:
        f_graph.show()
    check(f_graph, 'f')

    class GCTransform(shadowstack.ShadowStackFrameworkGCTransformer):
        from rpython.memory.gc.generation import GenerationGC as \
                                                          GCClass
        GC_PARAMS = {}

    gctransf = GCTransform(t)
    gctransf.transform_graph(f_graph)
    if option.view:
        f_graph.show()
    relevant = check(f_graph, 'f')
    for p in relevant:
        in_between = False
        reload = 0
        for spaceop in p:
            if spaceop.opname == 'direct_call':
                target = direct_target(spaceop)
                if target == 'f':
                    in_between = False
                elif target == 'stack_check___':
                    in_between = True
            if in_between and spaceop.opname == 'gc_reload_possibly_moved':
                reload += 1

        assert reload == 0
コード例 #24
0
ファイル: test_stackcheck.py プロジェクト: cimarieta/usp
def test_gctransformed():
    t = TranslationContext()
    a = t.buildannotator()
    a.build_types(g, [int])
    a.simplify()
    t.buildrtyper().specialize()
    backend_optimizations(t)
    t.checkgraphs()
    n = insert_ll_stackcheck(t)
    t.checkgraphs()
    assert n == 1
    exctransf = t.getexceptiontransformer()
    f_graph = graphof(t, f)
    exctransf.create_exception_handling(f_graph)
    if option.view:
        f_graph.show()
    check(f_graph, "f")

    class GCTransform(shadowstack.ShadowStackFrameworkGCTransformer):
        from rpython.memory.gc.generation import GenerationGC as GCClass

        GC_PARAMS = {}

    gctransf = GCTransform(t)
    gctransf.transform_graph(f_graph)
    if option.view:
        f_graph.show()
    relevant = check(f_graph, "f")
    for p in relevant:
        in_between = False
        reload = 0
        for spaceop in p:
            if spaceop.opname == "direct_call":
                target = direct_target(spaceop)
                if target == "f":
                    in_between = False
                elif target == "stack_check___":
                    in_between = True
            if in_between and spaceop.opname == "gc_reload_possibly_moved":
                reload += 1

        assert reload == 0
コード例 #25
0
ファイル: test_mallocv.py プロジェクト: sota/pypy-old
 def check(self,
           fn,
           signature,
           args,
           expected_result,
           expected_mallocs=0,
           expected_calls=0):
     t = TranslationContext()
     self.translator = t
     t.buildannotator().build_types(fn, signature)
     t.buildrtyper().specialize()
     graph = graphof(t, fn)
     if option.view:
         t.view()
     self.original_graph_count = len(t.graphs)
     # to detect broken intermediate graphs,
     # we do the loop ourselves instead of calling remove_simple_mallocs()
     maxiter = 100
     mallocv = MallocVirtualizer(t.graphs, t.rtyper, verbose=True)
     while True:
         progress = mallocv.remove_mallocs_once()
         if progress and option.view:
             t.view()
         t.checkgraphs()
         if expected_result is not DONT_CHECK_RESULT:
             interp = LLInterpreter(t.rtyper)
             if not isinstance(expected_result, CHECK_RAISES):
                 res = interp.eval_graph(graph, args)
                 assert res == expected_result
             else:
                 excinfo = py.test.raises(LLException, interp.eval_graph,
                                          graph, args)
                 assert expected_result.excname in str(excinfo.value)
         if not progress:
             break
         maxiter -= 1
         assert maxiter > 0, "infinite loop?"
     self.check_malloc_removed(graph, expected_mallocs, expected_calls)
     return graph
コード例 #26
0
    def _makefunc_str_int(cls, func):
        def main(argv):
            arg0 = argv[1]
            arg1 = int(argv[2])
            try:
                res = func(arg0, arg1)
            except MemoryError:
                print 'Result: MemoryError'
            else:
                print 'Result: "%s"' % (res,)
            return 0
        config = cls.make_config()
        t = TranslationContext(config=config)
        a = t.buildannotator()
        sec_ep = getattr(cls, 'secondary_entrypoints', [])
        for f, inputtypes in sec_ep:
            a.build_types(f, inputtypes, False)
        a.build_types(main, [s_list_of_strings])
        t.buildrtyper().specialize()
        t.checkgraphs()

        cbuilder = CStandaloneBuilder(t, main, config=config,
                secondary_entrypoints=sec_ep)
        c_source_filename = cbuilder.generate_source(
            defines = cbuilder.DEBUG_DEFINES)
        cls._patch_makefile(cbuilder.targetdir)
        if option.view:
            t.view()
        exe_name = cbuilder.compile()

        def run(arg0, arg1, runner=None):
            if runner is not None:
                py.test.skip("unsupported test: runner=%r" % (runner,))
            lines = []
            print >> sys.stderr, 'RUN: starting', exe_name, arg0, arg1
            if sys.platform == 'win32':
                redirect = ' 2> NUL'
            else:
                redirect = ''
            if config.translation.shared and os.name == 'posix':
                library_path = exe_name.dirpath()
                if sys.platform == 'darwin':
                    env = 'DYLD_LIBRARY_PATH="%s" ' % library_path
                else:
                    env = 'LD_LIBRARY_PATH="%s" ' % library_path
            else:
                env = ''
            cwd = os.getcwd()
            try:
                os.chdir(str(exe_name.dirpath()))
                g = os.popen(
                    '%s"%s" %s %d%s' % (env, exe_name, arg0, arg1, redirect), 'r')
            finally:
                os.chdir(cwd)
            for line in g:
                print >> sys.stderr, 'RUN:', line.rstrip()
                lines.append(line)
            g.close()
            if not lines:
                py.test.fail("no output from subprocess")
            if not lines[-1].startswith('Result:'):
                py.test.fail("unexpected output from subprocess")
            result = lines[-1][len('Result:'):].strip()
            if result == 'MemoryError':
                raise MemoryError("subprocess got an RPython MemoryError")
            if result.startswith('"') and result.endswith('"'):
                return result[1:-1]
            else:
                return int(result)
        return run
コード例 #27
0
ファイル: test_rint.py プロジェクト: sota/pypy-old
 def _test(self, func, types):
     t = TranslationContext()
     t.buildannotator().build_types(func, types)
     t.buildrtyper().specialize()
     t.checkgraphs()
コード例 #28
0
ファイル: test_asmgcroot.py プロジェクト: Darriall/pypy
    def _makefunc_str_int(cls, func):
        def main(argv):
            arg0 = argv[1]
            arg1 = int(argv[2])
            try:
                res = func(arg0, arg1)
            except MemoryError:
                print 'Result: MemoryError'
            else:
                print 'Result: "%s"' % (res,)
            return 0
        config = cls.make_config()
        t = TranslationContext(config=config)
        a = t.buildannotator()
        sec_ep = getattr(cls, 'secondary_entrypoints', [])
        for f, inputtypes in sec_ep:
            a.build_types(f, inputtypes, False)
        a.build_types(main, [s_list_of_strings])
        t.buildrtyper().specialize()
        t.checkgraphs()

        cbuilder = CStandaloneBuilder(t, main, config=config,
                secondary_entrypoints=sec_ep)
        c_source_filename = cbuilder.generate_source(
            defines = cbuilder.DEBUG_DEFINES)
        cls._patch_makefile(cbuilder.targetdir)
        if option.view:
            t.view()
        exe_name = cbuilder.compile()

        def run(arg0, arg1):
            lines = []
            print >> sys.stderr, 'RUN: starting', exe_name, arg0, arg1
            if sys.platform == 'win32':
                redirect = ' 2> NUL'
            else:
                redirect = ''
            if config.translation.shared and os.name == 'posix':
                library_path = exe_name.dirpath()
                if sys.platform == 'darwin':
                    env = 'DYLD_LIBRARY_PATH="%s" ' % library_path
                else:
                    env = 'LD_LIBRARY_PATH="%s" ' % library_path
            else:
                env = ''
            cwd = os.getcwd()
            try:
                os.chdir(str(exe_name.dirpath()))
                g = os.popen(
                    '%s"%s" %s %d%s' % (env, exe_name, arg0, arg1, redirect), 'r')
            finally:
                os.chdir(cwd)
            for line in g:
                print >> sys.stderr, 'RUN:', line.rstrip()
                lines.append(line)
            g.close()
            if not lines:
                py.test.fail("no output from subprocess")
            if not lines[-1].startswith('Result:'):
                py.test.fail("unexpected output from subprocess")
            result = lines[-1][len('Result:'):].strip()
            if result == 'MemoryError':
                raise MemoryError("subprocess got an RPython MemoryError")
            if result.startswith('"') and result.endswith('"'):
                return result[1:-1]
            else:
                return int(result)
        return run