3
from pypy.tool.isolate import Isolate
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
21
class GenLLVM(object):
22
# see create_codewriter() below
25
def __init__(self, translator, standalone):
28
LLVMNode.nodename_count = {}
30
self.standalone = standalone
31
self.translator = translator
33
self.config = translator.config
35
def gen_source(self, func):
38
codewriter = self.setup(func)
40
# write top part of llvm file
41
self.write_headers(codewriter)
43
codewriter.startimpl()
45
# write bottom part of llvm file
46
self.write_implementations(codewriter)
48
self._checkpoint('done')
53
def setup(self, func):
55
create c file for externs
56
create ll file for c file
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()
65
self.db = Database(self, self.translator)
67
# XXX hardcoded for now
68
self.db.gcpolicy = GcPolicy.new(self.db, 'boehm')
71
entry_point = self.get_entry_point(func)
72
self._checkpoint('get_entry_point')
77
self.entrynode = self.db.set_entrynode(entry_point)
78
self._checkpoint('setup_all all nodes')
80
# set up externs nodes
81
self.extern_decls = setup_externs(c_db, self.db)
82
self.translator.rtyper.specialize_more_blocks()
84
self._checkpoint('setup_all externs')
86
for node in self.db.getnodes():
87
node.post_setup_transform()
89
self._print_node_stats()
91
# create ll file from c code
92
self.generate_ll_externs()
93
self._checkpoint('setup_externs')
95
# open file & create codewriter
96
codewriter, self.filename = self.create_codewriter()
97
self._checkpoint('open file and create codewriter')
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())
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)
111
codewriter.header_comment("Type Declarations")
113
# write extern type declarations
114
self.write_extern_decls(codewriter)
115
self._checkpoint('write externs type declarations')
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')
122
codewriter.header_comment("Global Data")
125
for typ_decl in self.db.getnodes():
126
typ_decl.writeglobalconstants(codewriter)
127
self._checkpoint('write global constants')
129
codewriter.header_comment("Function Prototypes")
131
# write external protos
132
codewriter.write_lines(self._set_wordsize(extdeclarations))
135
for typ_decl in self.db.getnodes():
136
typ_decl.writedecl(codewriter)
138
self._checkpoint('write function prototypes')
140
def write_implementations(self, codewriter):
141
codewriter.header_comment("Function Implementation")
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))
148
codewriter.write_lines(self._set_wordsize(extfunctions_standalone))
149
self.write_extern_impls(codewriter)
150
self.write_setup_impl(codewriter)
152
self._checkpoint('write support implentations')
154
# write exception implementaions
155
from pypy.translator.llvm.exception import llvm_implcode
156
codewriter.write_lines(llvm_implcode(self.entrynode))
158
# write all node implementations
159
for typ_decl in self.db.getnodes():
160
typ_decl.writeimpl(codewriter)
161
self._checkpoint('write node implementations')
163
# write entry point if there is one
164
codewriter.comment("End of file")
166
def get_entry_point(self, func):
167
assert func is not None
168
self.entrypoint = func
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
177
def generate_ll_externs(self):
178
self.llexterns_header, self.llexterns_functions = \
179
generate_llfile(self.db,
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
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
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):
202
l = "%%%s = type %s" % (c_name, self.db.repr_type(obj))
203
codewriter.write_lines(l)
205
def write_extern_impls(self, codewriter):
206
for c_name, obj in self.extern_decls:
207
if c_name.startswith("RPyExc_"):
209
exc_repr = self.db.repr_constant(obj)[1]
210
write_raise_exc(c_name, exc_repr, codewriter)
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)
218
codewriter.ret("sbyte*", "null")
219
codewriter.closefunc()
221
def compile_module(self):
222
assert not self.standalone
224
modname, dirpath = buildllvm.Builder(self).make_module()
225
mod, wrap_fun = self.get_module(modname, dirpath)
228
def get_module(self, modname, dirpath):
229
if self.config.translation.llvm.isolate:
230
mod = Isolate((dirpath, modname))
232
from pypy.translator.tool.cbuild import import_module_from_directory
233
mod = import_module_from_directory(dirpath, modname)
235
wrap_fun = getattr(mod, 'pypy_' + self.entry_func_name + "_wrapper")
238
def compile_standalone(self, exe_name):
239
assert self.standalone
240
return buildllvm.Builder(self).make_standalone(exe_name)
242
def _checkpoint(self, msg=None):
243
if not self.config.translation.llvm.logging:
246
t = (time.time() - self.starttime)
247
log('\t%s took %02dm%02ds' % (msg, t/60, t%60))
250
self.starttime = time.time()
252
def _print_node_stats(self):
253
# disable node stats output
254
if not self.config.translation.llvm.logging:
258
for node in self.db.getnodes():
264
stats = [(count, str(typ)) for typ, count in nodecount.iteritems()]
267
log('STATS %s' % str(s))