~ubuntu-branches/ubuntu/karmic/pypy/karmic

« back to all changes in this revision

Viewing changes to pypy/translator/llvm/genllvm.py

  • Committer: Bazaar Package Importer
  • Author(s): Alexandre Fayolle
  • Date: 2007-04-13 09:33:09 UTC
  • Revision ID: james.westby@ubuntu.com-20070413093309-yoojh4jcoocu2krz
Tags: upstream-1.0.0
ImportĀ upstreamĀ versionĀ 1.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
import time
 
2
 
 
3
from pypy.tool.isolate import Isolate 
 
4
 
 
5
from pypy.translator.llvm import buildllvm
 
6
from pypy.translator.llvm.database import Database 
 
7
from pypy.rpython.rmodel import inputconst
 
8
from pypy.rpython.typesystem import getfunctionptr
 
9
from pypy.rpython.lltypesystem import lltype
 
10
from pypy.tool.udir import udir
 
11
from pypy.translator.llvm.codewriter import CodeWriter
 
12
from pypy.translator.llvm import extfuncnode
 
13
from pypy.translator.llvm.module.support import \
 
14
     extdeclarations, extfunctions, extfunctions_standalone, write_raise_exc
 
15
from pypy.translator.llvm.node import LLVMNode
 
16
from pypy.translator.llvm.externs2ll import setup_externs, generate_llfile
 
17
from pypy.translator.llvm.gc import GcPolicy
 
18
from pypy.translator.llvm.log import log
 
19
from pypy.translator.llvm.buildllvm import llvm_is_on_path, postfix
 
20
 
 
21
class GenLLVM(object):
 
22
    # see create_codewriter() below
 
23
    function_count = {}
 
24
 
 
25
    def __init__(self, translator, standalone):
 
26
    
 
27
        # reset counters
 
28
        LLVMNode.nodename_count = {}    
 
29
 
 
30
        self.standalone = standalone
 
31
        self.translator = translator
 
32
        
 
33
        self.config = translator.config
 
34
 
 
35
    def gen_source(self, func):
 
36
        self._checkpoint()
 
37
 
 
38
        codewriter = self.setup(func)
 
39
 
 
40
        # write top part of llvm file
 
41
        self.write_headers(codewriter)
 
42
 
 
43
        codewriter.startimpl()
 
44
 
 
45
        # write bottom part of llvm file
 
46
        self.write_implementations(codewriter)
 
47
 
 
48
        self._checkpoint('done')
 
49
        codewriter.close()
 
50
 
 
51
        return self.filename
 
52
 
 
53
    def setup(self, func):
 
54
        """ setup all nodes
 
55
            create c file for externs
 
56
            create ll file for c file
 
57
            create codewriter """
 
58
 
 
59
        # XXX please dont ask!
 
60
        from pypy.translator.c.genc import CStandaloneBuilder
 
61
        cbuild = CStandaloneBuilder(self.translator, func, config=self.config)
 
62
        #cbuild.stackless = self.stackless
 
63
        c_db = cbuild.generate_graphs_for_llinterp()
 
64
 
 
65
        self.db = Database(self, self.translator)
 
66
 
 
67
        # XXX hardcoded for now
 
68
        self.db.gcpolicy = GcPolicy.new(self.db, 'boehm')
 
69
 
 
70
        # get entry point
 
71
        entry_point = self.get_entry_point(func)
 
72
        self._checkpoint('get_entry_point')
 
73
        
 
74
        # set up all nodes
 
75
        self.db.setup_all()
 
76
        
 
77
        self.entrynode = self.db.set_entrynode(entry_point)
 
78
        self._checkpoint('setup_all all nodes')
 
79
 
 
80
        # set up externs nodes
 
81
        self.extern_decls = setup_externs(c_db, self.db)
 
82
        self.translator.rtyper.specialize_more_blocks()
 
83
        self.db.setup_all()
 
84
        self._checkpoint('setup_all externs')
 
85
 
 
86
        for node in self.db.getnodes():
 
87
            node.post_setup_transform()
 
88
        
 
89
        self._print_node_stats()
 
90
 
 
91
        # create ll file from c code
 
92
        self.generate_ll_externs()
 
93
        self._checkpoint('setup_externs')
 
94
 
 
95
        # open file & create codewriter
 
96
        codewriter, self.filename = self.create_codewriter()
 
97
        self._checkpoint('open file and create codewriter')        
 
98
        return codewriter
 
99
 
 
100
    def _set_wordsize(self, s):
 
101
        s = s.replace('UWORD', self.db.get_machine_uword())
 
102
        s = s.replace( 'WORD', self.db.get_machine_word())
 
103
        s = s.replace('POSTFIX', postfix())
 
104
        return s
 
105
 
 
106
    def write_headers(self, codewriter):
 
107
        # write external function headers
 
108
        codewriter.header_comment('External Function Headers')
 
109
        codewriter.write_lines(self.llexterns_header)
 
110
 
 
111
        codewriter.header_comment("Type Declarations")
 
112
 
 
113
        # write extern type declarations
 
114
        self.write_extern_decls(codewriter)
 
115
        self._checkpoint('write externs type declarations')
 
116
 
 
117
        # write node type declarations
 
118
        for typ_decl in self.db.getnodes():
 
119
            typ_decl.writedatatypedecl(codewriter)
 
120
        self._checkpoint('write data type declarations')
 
121
 
 
122
        codewriter.header_comment("Global Data")
 
123
 
 
124
        # write pbcs
 
125
        for typ_decl in self.db.getnodes():
 
126
            typ_decl.writeglobalconstants(codewriter)
 
127
        self._checkpoint('write global constants')
 
128
 
 
129
        codewriter.header_comment("Function Prototypes")
 
130
 
 
131
        # write external protos
 
132
        codewriter.write_lines(self._set_wordsize(extdeclarations))
 
133
 
 
134
        # write node protos
 
135
        for typ_decl in self.db.getnodes():
 
136
            typ_decl.writedecl(codewriter)
 
137
 
 
138
        self._checkpoint('write function prototypes')
 
139
 
 
140
    def write_implementations(self, codewriter):
 
141
        codewriter.header_comment("Function Implementation")
 
142
 
 
143
        # write external function implementations
 
144
        codewriter.header_comment('External Function Implementation')
 
145
        codewriter.write_lines(self.llexterns_functions)
 
146
        codewriter.write_lines(self._set_wordsize(extfunctions))
 
147
        if self.standalone:
 
148
            codewriter.write_lines(self._set_wordsize(extfunctions_standalone))
 
149
        self.write_extern_impls(codewriter)
 
150
        self.write_setup_impl(codewriter)
 
151
        
 
152
        self._checkpoint('write support implentations')
 
153
 
 
154
        # write exception implementaions
 
155
        from pypy.translator.llvm.exception import llvm_implcode
 
156
        codewriter.write_lines(llvm_implcode(self.entrynode))
 
157
 
 
158
        # write all node implementations
 
159
        for typ_decl in self.db.getnodes():
 
160
            typ_decl.writeimpl(codewriter)
 
161
        self._checkpoint('write node implementations')
 
162
 
 
163
        # write entry point if there is one
 
164
        codewriter.comment("End of file")
 
165
    
 
166
    def get_entry_point(self, func):
 
167
        assert func is not None
 
168
        self.entrypoint = func
 
169
 
 
170
        bk = self.translator.annotator.bookkeeper
 
171
        ptr = getfunctionptr(bk.getdesc(func).getuniquegraph())
 
172
        c = inputconst(lltype.typeOf(ptr), ptr)
 
173
        self.db.prepare_arg_value(c)
 
174
        self.entry_func_name = func.func_name
 
175
        return c.value._obj 
 
176
 
 
177
    def generate_ll_externs(self):
 
178
        self.llexterns_header, self.llexterns_functions = \
 
179
                               generate_llfile(self.db,
 
180
                                               self.extern_decls,
 
181
                                               self.entrynode,
 
182
                                               self.standalone)
 
183
 
 
184
    def create_codewriter(self):
 
185
        # prevent running the same function twice in a test
 
186
        if self.entry_func_name in self.function_count:
 
187
            postfix = '_%d' % self.function_count[self.entry_func_name]
 
188
            self.function_count[self.entry_func_name] += 1
 
189
        else:
 
190
            postfix = ''
 
191
            self.function_count[self.entry_func_name] = 1
 
192
        filename = udir.join(self.entry_func_name + postfix).new(ext='.ll')
 
193
        f = open(str(filename), 'w')
 
194
        return CodeWriter(f, self.db), filename
 
195
 
 
196
    def write_extern_decls(self, codewriter):        
 
197
        for c_name, obj in self.extern_decls:
 
198
            if isinstance(obj, lltype.LowLevelType):
 
199
                if isinstance(obj, lltype.Ptr):
 
200
                    obj = obj.TO
 
201
 
 
202
                l = "%%%s = type %s" % (c_name, self.db.repr_type(obj))
 
203
                codewriter.write_lines(l)
 
204
                
 
205
    def write_extern_impls(self, codewriter):
 
206
        for c_name, obj in self.extern_decls:
 
207
            if c_name.startswith("RPyExc_"):
 
208
                c_name = c_name[1:]
 
209
                exc_repr = self.db.repr_constant(obj)[1]
 
210
                write_raise_exc(c_name, exc_repr, codewriter)
 
211
 
 
212
    def write_setup_impl(self, codewriter):
 
213
        open_decl =  "sbyte* %LLVM_RPython_StartupCode()"
 
214
        codewriter.openfunc(open_decl)
 
215
        for node in self.db.getnodes():
 
216
            node.writesetupcode(codewriter)
 
217
 
 
218
        codewriter.ret("sbyte*", "null")
 
219
        codewriter.closefunc()
 
220
 
 
221
    def compile_module(self):
 
222
        assert not self.standalone
 
223
        
 
224
        modname, dirpath = buildllvm.Builder(self).make_module()
 
225
        mod, wrap_fun = self.get_module(modname, dirpath)
 
226
        return mod, wrap_fun
 
227
 
 
228
    def get_module(self, modname, dirpath):
 
229
        if self.config.translation.llvm.isolate:
 
230
            mod = Isolate((dirpath, modname))
 
231
        else:
 
232
            from pypy.translator.tool.cbuild import import_module_from_directory
 
233
            mod = import_module_from_directory(dirpath, modname)
 
234
 
 
235
        wrap_fun = getattr(mod, 'pypy_' + self.entry_func_name + "_wrapper")
 
236
        return mod, wrap_fun
 
237
 
 
238
    def compile_standalone(self, exe_name):
 
239
        assert self.standalone
 
240
        return buildllvm.Builder(self).make_standalone(exe_name)
 
241
 
 
242
    def _checkpoint(self, msg=None):
 
243
        if not self.config.translation.llvm.logging:
 
244
            return
 
245
        if msg:
 
246
            t = (time.time() - self.starttime)
 
247
            log('\t%s took %02dm%02ds' % (msg, t/60, t%60))
 
248
        else:
 
249
            log('GenLLVM:')
 
250
        self.starttime = time.time()
 
251
 
 
252
    def _print_node_stats(self):
 
253
        # disable node stats output
 
254
        if not self.config.translation.llvm.logging: 
 
255
            return 
 
256
 
 
257
        nodecount = {}
 
258
        for node in self.db.getnodes():
 
259
            typ = type(node)
 
260
            try:
 
261
                nodecount[typ] += 1
 
262
            except:
 
263
                nodecount[typ] = 1
 
264
        stats = [(count, str(typ)) for typ, count in nodecount.iteritems()]
 
265
        stats.sort()
 
266
        for s in stats:
 
267
            log('STATS %s' % str(s))
 
268