Ejemplo n.º 1
0
    def setup(self, func):
        """ setup all nodes
            create c file for externs
            create ll file for c file
            create codewriter """

        if self.standalone:
            func = augment_entrypoint(self.translator, func)

        # XXX please dont ask!
        from pypy.translator.c.genc import CStandaloneBuilder
        cbuild = CStandaloneBuilder(self.translator, func, config=self.config)
        c_db = cbuild.generate_graphs_for_llinterp()

        self.db = Database(self, self.translator)
        self.db.gcpolicy = GcPolicy.new(self.db, self.config)
        self.db.gctransformer = c_db.gctransformer

        # get entry point
        entry_point = self.get_entry_point(func)
        self._checkpoint('get_entry_point')

        # set up all nodes
        self.db.setup_all()

        self.entrynode = self.db.set_entrynode(entry_point)
        self._checkpoint('setup_all all nodes')

        # set up externs nodes
        self.setup_externs(c_db, self.db)

        self.db.setup_all()
        self._checkpoint('setup_all externs')

        self._print_node_stats()

        # open file & create codewriter
        codewriter, self.filename = self.create_codewriter()
        self._checkpoint('open file and create codewriter')

        # create ll file from c code
        self.generate_ll_externs(codewriter)

        return codewriter
Ejemplo n.º 2
0
    def setup(self, func):
        """ setup all nodes
            create c file for externs
            create ll file for c file
            create codewriter """

        # XXX please dont ask!
        from pypy.translator.c.genc import CStandaloneBuilder
        cbuild = CStandaloneBuilder(self.translator, func, config=self.config)
        #cbuild.stackless = self.stackless
        c_db = cbuild.generate_graphs_for_llinterp()

        self.db = Database(self, self.translator)

        # XXX hardcoded for now
        self.db.gcpolicy = GcPolicy.new(self.db, 'boehm')

        # get entry point
        entry_point = self.get_entry_point(func)
        self._checkpoint('get_entry_point')
        
        # set up all nodes
        self.db.setup_all()
        
        self.entrynode = self.db.set_entrynode(entry_point)
        self._checkpoint('setup_all all nodes')

        # set up externs nodes
        self.extern_decls = setup_externs(c_db, self.db)
        self.translator.rtyper.specialize_more_blocks()
        self.db.setup_all()
        self._checkpoint('setup_all externs')

        for node in self.db.getnodes():
            node.post_setup_transform()
        
        self._print_node_stats()

        # create ll file from c code
        self.generate_ll_externs()
        self._checkpoint('setup_externs')

        # open file & create codewriter
        codewriter, self.filename = self.create_codewriter()
        self._checkpoint('open file and create codewriter')        
        return codewriter
Ejemplo n.º 3
0
class GenLLVM(object):
    # see create_codewriter() below
    function_count = {}

    def __init__(self, translator, standalone):
    
        # reset counters
        LLVMNode.nodename_count = {}    

        self.standalone = standalone
        self.translator = translator
        
        self.config = translator.config

    def gen_source(self, func):
        self._checkpoint()

        codewriter = self.setup(func)

        # write top part of llvm file
        self.write_headers(codewriter)

        codewriter.startimpl()

        # write bottom part of llvm file
        self.write_implementations(codewriter)

        self._checkpoint('done')
        codewriter.close()

        return self.filename

    def setup(self, func):
        """ setup all nodes
            create c file for externs
            create ll file for c file
            create codewriter """

        # XXX please dont ask!
        from pypy.translator.c.genc import CStandaloneBuilder
        cbuild = CStandaloneBuilder(self.translator, func, config=self.config)
        #cbuild.stackless = self.stackless
        c_db = cbuild.generate_graphs_for_llinterp()

        self.db = Database(self, self.translator)

        # XXX hardcoded for now
        self.db.gcpolicy = GcPolicy.new(self.db, 'boehm')

        # get entry point
        entry_point = self.get_entry_point(func)
        self._checkpoint('get_entry_point')
        
        # set up all nodes
        self.db.setup_all()
        
        self.entrynode = self.db.set_entrynode(entry_point)
        self._checkpoint('setup_all all nodes')

        # set up externs nodes
        self.extern_decls = setup_externs(c_db, self.db)
        self.translator.rtyper.specialize_more_blocks()
        self.db.setup_all()
        self._checkpoint('setup_all externs')

        for node in self.db.getnodes():
            node.post_setup_transform()
        
        self._print_node_stats()

        # create ll file from c code
        self.generate_ll_externs()
        self._checkpoint('setup_externs')

        # open file & create codewriter
        codewriter, self.filename = self.create_codewriter()
        self._checkpoint('open file and create codewriter')        
        return codewriter

    def _set_wordsize(self, s):
        s = s.replace('UWORD', self.db.get_machine_uword())
        s = s.replace( 'WORD', self.db.get_machine_word())
        s = s.replace('POSTFIX', postfix())
        return s

    def write_headers(self, codewriter):
        # write external function headers
        codewriter.header_comment('External Function Headers')
        codewriter.write_lines(self.llexterns_header)

        codewriter.header_comment("Type Declarations")

        # write extern type declarations
        self.write_extern_decls(codewriter)
        self._checkpoint('write externs type declarations')

        # write node type declarations
        for typ_decl in self.db.getnodes():
            typ_decl.writedatatypedecl(codewriter)
        self._checkpoint('write data type declarations')

        codewriter.header_comment("Global Data")

        # write pbcs
        for typ_decl in self.db.getnodes():
            typ_decl.writeglobalconstants(codewriter)
        self._checkpoint('write global constants')

        codewriter.header_comment("Function Prototypes")

        # write external protos
        codewriter.write_lines(self._set_wordsize(extdeclarations))

        # write node protos
        for typ_decl in self.db.getnodes():
            typ_decl.writedecl(codewriter)

        self._checkpoint('write function prototypes')

    def write_implementations(self, codewriter):
        codewriter.header_comment("Function Implementation")

        # write external function implementations
        codewriter.header_comment('External Function Implementation')
        codewriter.write_lines(self.llexterns_functions)
        codewriter.write_lines(self._set_wordsize(extfunctions))
        if self.standalone:
            codewriter.write_lines(self._set_wordsize(extfunctions_standalone))
        self.write_extern_impls(codewriter)
        self.write_setup_impl(codewriter)
        
        self._checkpoint('write support implentations')

        # write exception implementaions
        from pypy.translator.llvm.exception import llvm_implcode
        codewriter.write_lines(llvm_implcode(self.entrynode))

        # write all node implementations
        for typ_decl in self.db.getnodes():
            typ_decl.writeimpl(codewriter)
        self._checkpoint('write node implementations')

        # write entry point if there is one
        codewriter.comment("End of file")
    
    def get_entry_point(self, func):
        assert func is not None
        self.entrypoint = func

        bk = self.translator.annotator.bookkeeper
        ptr = getfunctionptr(bk.getdesc(func).getuniquegraph())
        c = inputconst(lltype.typeOf(ptr), ptr)
        self.db.prepare_arg_value(c)
        self.entry_func_name = func.func_name
        return c.value._obj 

    def generate_ll_externs(self):
        self.llexterns_header, self.llexterns_functions = \
                               generate_llfile(self.db,
                                               self.extern_decls,
                                               self.entrynode,
                                               self.standalone)

    def create_codewriter(self):
        # prevent running the same function twice in a test
        if self.entry_func_name in self.function_count:
            postfix = '_%d' % self.function_count[self.entry_func_name]
            self.function_count[self.entry_func_name] += 1
        else:
            postfix = ''
            self.function_count[self.entry_func_name] = 1
        filename = udir.join(self.entry_func_name + postfix).new(ext='.ll')
        f = open(str(filename), 'w')
        return CodeWriter(f, self.db), filename

    def write_extern_decls(self, codewriter):        
        for c_name, obj in self.extern_decls:
            if isinstance(obj, lltype.LowLevelType):
                if isinstance(obj, lltype.Ptr):
                    obj = obj.TO

                l = "%%%s = type %s" % (c_name, self.db.repr_type(obj))
                codewriter.write_lines(l)
                
    def write_extern_impls(self, codewriter):
        for c_name, obj in self.extern_decls:
            if c_name.startswith("RPyExc_"):
                c_name = c_name[1:]
                exc_repr = self.db.repr_constant(obj)[1]
                write_raise_exc(c_name, exc_repr, codewriter)

    def write_setup_impl(self, codewriter):
        open_decl =  "sbyte* %LLVM_RPython_StartupCode()"
        codewriter.openfunc(open_decl)
        for node in self.db.getnodes():
            node.writesetupcode(codewriter)

        codewriter.ret("sbyte*", "null")
        codewriter.closefunc()

    def compile_module(self):
        assert not self.standalone
        
        modname, dirpath = buildllvm.Builder(self).make_module()
        mod, wrap_fun = self.get_module(modname, dirpath)
        return mod, wrap_fun

    def get_module(self, modname, dirpath):
        if self.config.translation.llvm.isolate:
            mod = Isolate((dirpath, modname))
        else:
            from pypy.translator.tool.cbuild import import_module_from_directory
            mod = import_module_from_directory(dirpath, modname)

        wrap_fun = getattr(mod, 'pypy_' + self.entry_func_name + "_wrapper")
        return mod, wrap_fun

    def compile_standalone(self, exe_name):
        assert self.standalone
        return buildllvm.Builder(self).make_standalone(exe_name)

    def _checkpoint(self, msg=None):
        if not self.config.translation.llvm.logging:
            return
        if msg:
            t = (time.time() - self.starttime)
            log('\t%s took %02dm%02ds' % (msg, t/60, t%60))
        else:
            log('GenLLVM:')
        self.starttime = time.time()

    def _print_node_stats(self):
        # disable node stats output
        if not self.config.translation.llvm.logging: 
            return 

        nodecount = {}
        for node in self.db.getnodes():
            typ = type(node)
            try:
                nodecount[typ] += 1
            except:
                nodecount[typ] = 1
        stats = [(count, str(typ)) for typ, count in nodecount.iteritems()]
        stats.sort()
        for s in stats:
            log('STATS %s' % str(s))
Ejemplo n.º 4
0
class GenLLVM(object):
    # see create_codewriter() below
    function_count = {}

    def __init__(self, translator, standalone):

        # reset counters
        Node.nodename_count = {}
        self.eci = ExternalCompilationInfo()

        self.standalone = standalone
        self.translator = translator

        self.config = translator.config

    def gen_source(self, func):
        self._checkpoint("before gen source")

        codewriter = self.setup(func)

        codewriter.header_comment("Extern code")
        codewriter.write_lines(self.llcode)

        codewriter.header_comment("Type declarations")
        for typ_decl in self.db.gettypedefnodes():
            typ_decl.writetypedef(codewriter)

        codewriter.header_comment("Function prototypes")
        for node in self.db.getnodes():
            if hasattr(node, 'writedecl'):
                node.writedecl(codewriter)

        codewriter.header_comment("Prebuilt constants")
        for node in self.db.getnodes():
            # XXX tmp
            if hasattr(node, "writeglobalconstants"):
                node.writeglobalconstants(codewriter)

        self._checkpoint("before definitions")

        codewriter.header_comment('Suppport definitions')
        codewriter.write_lines(extfunctions, patch=True)

        codewriter.header_comment('Startup definition')
        self.write_startup_impl(codewriter)

        codewriter.header_comment("Function definitions")
        for node in self.db.getnodes():
            if hasattr(node, 'writeimpl'):
                node.writeimpl(codewriter)

        self._debug(codewriter)

        codewriter.comment("End of file")
        codewriter.close()
        self._checkpoint('done')

        return self.filename

    def setup(self, func):
        """ setup all nodes
            create c file for externs
            create ll file for c file
            create codewriter """

        if self.standalone:
            func = augment_entrypoint(self.translator, func)

        # XXX please dont ask!
        from pypy.translator.c.genc import CStandaloneBuilder
        cbuild = CStandaloneBuilder(self.translator, func, config=self.config)
        c_db = cbuild.generate_graphs_for_llinterp()

        self.db = Database(self, self.translator)
        self.db.gcpolicy = GcPolicy.new(self.db, self.config)
        self.db.gctransformer = c_db.gctransformer

        # get entry point
        entry_point = self.get_entry_point(func)
        self._checkpoint('get_entry_point')

        # set up all nodes
        self.db.setup_all()

        self.entrynode = self.db.set_entrynode(entry_point)
        self._checkpoint('setup_all all nodes')

        # set up externs nodes
        self.setup_externs(c_db, self.db)

        self.db.setup_all()
        self._checkpoint('setup_all externs')

        self._print_node_stats()

        # open file & create codewriter
        codewriter, self.filename = self.create_codewriter()
        self._checkpoint('open file and create codewriter')

        # create ll file from c code
        self.generate_ll_externs(codewriter)

        return codewriter

    def setup_externs(self, c_db, db):
        # XXX this should be done via augmenting entrypoint
        exctransformer = c_db.exctransformer
        for obj in [
                exctransformer.rpyexc_occured_ptr.value,
                exctransformer.rpyexc_fetch_type_ptr.value,
                exctransformer.rpyexc_clear_ptr.value
        ]:
            db.prepare_constant(lltype.typeOf(obj), obj)

    def get_entry_point(self, func):
        assert func is not None
        self.entrypoint = func

        bk = self.translator.annotator.bookkeeper
        ptr = getfunctionptr(bk.getdesc(func).getuniquegraph())
        c = inputconst(lltype.typeOf(ptr), ptr)
        self.db.prepare_arg(c)

        # ensure unqiue entry node name for testing
        entry_node = self.db.obj2node[c.value._obj]
        name = entry_node.name
        if name in self.function_count:
            self.function_count[name] += 1
            Node.nodename_count[name] = self.function_count[name] + 1
            name += '_%d' % self.function_count[name]
            entry_node.name = name
        else:
            self.function_count[name] = 1

        self.entry_name = name[6:]
        return c.value._obj

    def generate_ll_externs(self, codewriter):
        all = []
        for node in self.db.getnodes():
            eci = getattr(node, 'compilation_info', None)
            if eci:
                all.append(eci)
        self.eci = self.eci.merge(*all)

        ccode = generate_c(self.db, self.entrynode, self.eci, self.standalone)
        self.llcode = generate_ll(ccode, self.eci)
        self.eci = self.eci.convert_sources_to_files(being_main=True)

    def create_codewriter(self):
        # prevent running the same function twice in a test
        filename = udir.join(self.entry_name).new(ext='.ll')
        f = open(str(filename), 'w')
        if self.standalone:
            return CodeWriter(f, self.db), filename
        else:
            return CodeWriter(f, self.db, linkage=''), filename

    def write_startup_impl(self, codewriter):
        open_decl = "i8* @LLVM_RPython_StartupCode()"
        codewriter.openfunc(open_decl)
        for node in self.db.getnodes():
            node.writesetupcode(codewriter)

        codewriter.ret("i8*", "null")
        codewriter.closefunc()

    def compile_module(self):
        assert not self.standalone

        modname, dirpath = buildllvm.Builder(self).make_module()
        mod, wrap_fun = self.get_module(modname, dirpath)
        return mod, wrap_fun

    def get_module(self, modname, dirpath):
        if self.config.translation.llvm.isolate:
            mod = Isolate((dirpath, modname))
        else:
            from pypy.translator.tool.cbuild import import_module_from_directory
            mod = import_module_from_directory(dirpath, modname)

        wrap_fun = getattr(mod, 'entrypoint')
        return mod, wrap_fun

    def compile_standalone(self, exe_name):
        assert self.standalone
        return buildllvm.Builder(self).make_standalone(exe_name)

    def _checkpoint(self, msg=None):
        if not self.config.translation.llvm.logging:
            return
        if msg:
            t = (time.time() - self.starttime)
            log('\t%s took %02dm%02ds' % (msg, t / 60, t % 60))
        else:
            log('GenLLVM:')
        self.starttime = time.time()

    def _print_node_stats(self):
        # disable node stats output
        if not self.config.translation.llvm.logging:
            return

        nodecount = {}
        for node in self.db.getnodes():
            typ = type(node)
            try:
                nodecount[typ] += 1
            except:
                nodecount[typ] = 1
        stats = [(count, str(typ)) for typ, count in nodecount.iteritems()]
        stats.sort()
        for s in stats:
            log('STATS %s' % str(s))

    def _debug(self, codewriter):
        if self.config.translation.llvm.debug:
            if self.db.debugstringnodes:
                codewriter.header_comment("Debug string")
                for node in self.db.debugstringnodes:
                    node.writeglobalconstants(codewriter)

            print "Start"
            print self.db.dump_pbcs()
            print "End"