PageRenderTime 62ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/translator/c/funcgen.py

https://bitbucket.org/pypy/pypy/
Python | 904 lines | 895 code | 5 blank | 4 comment | 1 complexity | 6415b07d0691cba0d836c275a413a055 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import sys
  2. from pypy.translator.c.support import USESLOTS # set to False if necessary while refactoring
  3. from pypy.translator.c.support import cdecl
  4. from pypy.translator.c.support import llvalue_from_constant, gen_assignments
  5. from pypy.translator.c.support import c_string_constant, barebonearray
  6. from pypy.objspace.flow.model import Variable, Constant, Block
  7. from pypy.objspace.flow.model import c_last_exception, copygraph
  8. from pypy.rpython.lltypesystem.lltype import Ptr, PyObject, Void, Bool, Signed
  9. from pypy.rpython.lltypesystem.lltype import Unsigned, SignedLongLong, Float
  10. from pypy.rpython.lltypesystem.lltype import UnsignedLongLong, Char, UniChar
  11. from pypy.rpython.lltypesystem.lltype import pyobjectptr, ContainerType
  12. from pypy.rpython.lltypesystem.lltype import Struct, Array, FixedSizeArray
  13. from pypy.rpython.lltypesystem.lltype import ForwardReference, FuncType
  14. from pypy.rpython.lltypesystem.llmemory import Address
  15. from pypy.translator.backendopt.ssa import SSI_to_SSA
  16. from pypy.translator.backendopt.innerloop import find_inner_loops
  17. from pypy.tool.identity_dict import identity_dict
  18. PyObjPtr = Ptr(PyObject)
  19. LOCALVAR = 'l_%s'
  20. KEEP_INLINED_GRAPHS = False
  21. class FunctionCodeGenerator(object):
  22. """
  23. Collects information about a function which we have to generate
  24. from a flow graph.
  25. """
  26. if USESLOTS:
  27. __slots__ = """graph db gcpolicy
  28. exception_policy
  29. more_ll_values
  30. vars all_cached_consts
  31. illtypes
  32. functionname
  33. blocknum
  34. innerloops
  35. oldgraph""".split()
  36. def __init__(self, graph, db, exception_policy=None, functionname=None):
  37. graph._seen_by_the_backend = True
  38. self.graph = graph
  39. self.db = db
  40. self.gcpolicy = db.gcpolicy
  41. self.exception_policy = exception_policy
  42. self.functionname = functionname
  43. # apply the exception transformation
  44. if self.db.exctransformer:
  45. self.db.exctransformer.create_exception_handling(self.graph)
  46. # apply the gc transformation
  47. if self.db.gctransformer:
  48. self.db.gctransformer.transform_graph(self.graph)
  49. #self.graph.show()
  50. self.collect_var_and_types()
  51. for v in self.vars:
  52. T = getattr(v, 'concretetype', PyObjPtr)
  53. # obscure: skip forward references and hope for the best
  54. # (needed for delayed function pointers)
  55. if isinstance(T, Ptr) and T.TO.__class__ == ForwardReference:
  56. continue
  57. db.gettype(T) # force the type to be considered by the database
  58. self.illtypes = None
  59. def collect_var_and_types(self):
  60. #
  61. # collect all variables and constants used in the body,
  62. # and get their types now
  63. #
  64. # NOTE: cannot use dictionaries with Constants as keys, because
  65. # Constants may hash and compare equal but have different lltypes
  66. self.all_cached_consts = None # will be filled after implementation_end
  67. mix = [self.graph.getreturnvar()]
  68. self.more_ll_values = []
  69. for block in self.graph.iterblocks():
  70. mix.extend(block.inputargs)
  71. for op in block.operations:
  72. mix.extend(op.args)
  73. mix.append(op.result)
  74. for link in block.exits:
  75. mix.extend(link.getextravars())
  76. mix.extend(link.args)
  77. if hasattr(link, 'llexitcase'):
  78. self.more_ll_values.append(link.llexitcase)
  79. elif link.exitcase is not None:
  80. mix.append(Constant(link.exitcase))
  81. if self.exception_policy == "CPython":
  82. v, exc_cleanup_ops = self.graph.exc_cleanup
  83. mix.append(v)
  84. for cleanupop in exc_cleanup_ops:
  85. mix.extend(cleanupop.args)
  86. mix.append(cleanupop.result)
  87. uniquemix = []
  88. seen = identity_dict()
  89. for v in mix:
  90. if v not in seen:
  91. uniquemix.append(v)
  92. seen[v] = True
  93. self.vars = uniquemix
  94. def name(self, cname): #virtual
  95. return cname
  96. def patch_graph(self, copy_graph):
  97. graph = self.graph
  98. if self.db.gctransformer and self.db.gctransformer.inline:
  99. if copy_graph:
  100. graph = copygraph(graph, shallow=True)
  101. self.db.gctransformer.inline_helpers(graph)
  102. return graph
  103. def implementation_begin(self):
  104. self.oldgraph = self.graph
  105. self.graph = self.patch_graph(copy_graph=True)
  106. SSI_to_SSA(self.graph)
  107. self.collect_var_and_types()
  108. self.blocknum = {}
  109. for block in self.graph.iterblocks():
  110. self.blocknum[block] = len(self.blocknum)
  111. db = self.db
  112. lltypes = identity_dict()
  113. for v in self.vars:
  114. T = getattr(v, 'concretetype', PyObjPtr)
  115. typename = db.gettype(T)
  116. lltypes[v] = T, typename
  117. self.illtypes = lltypes
  118. self.innerloops = {} # maps the loop's header block to a Loop()
  119. for loop in find_inner_loops(self.graph, Bool):
  120. self.innerloops[loop.headblock] = loop
  121. def graphs_to_patch(self):
  122. yield self.graph
  123. def implementation_end(self):
  124. self.all_cached_consts = list(self.allconstantvalues())
  125. self.illtypes = None
  126. self.vars = None
  127. self.blocknum = None
  128. self.innerloops = None
  129. self.graph = self.oldgraph
  130. del self.oldgraph
  131. def argnames(self):
  132. return [LOCALVAR % v.name for v in self.graph.getargs()]
  133. def allvariables(self):
  134. return [v for v in self.vars if isinstance(v, Variable)]
  135. def allconstants(self):
  136. return [c for c in self.vars if isinstance(c, Constant)]
  137. def allconstantvalues(self):
  138. for c in self.vars:
  139. if isinstance(c, Constant):
  140. yield llvalue_from_constant(c)
  141. for llvalue in self.more_ll_values:
  142. yield llvalue
  143. def lltypemap(self, v):
  144. T, typename = self.illtypes[v]
  145. return T
  146. def lltypename(self, v):
  147. T, typename = self.illtypes[v]
  148. return typename
  149. def expr(self, v, special_case_void=True):
  150. if isinstance(v, Variable):
  151. if self.lltypemap(v) is Void and special_case_void:
  152. return '/* nothing */'
  153. else:
  154. return LOCALVAR % v.name
  155. elif isinstance(v, Constant):
  156. value = llvalue_from_constant(v)
  157. if value is None and not special_case_void:
  158. return 'nothing'
  159. else:
  160. return self.db.get(value)
  161. else:
  162. raise TypeError, "expr(%r)" % (v,)
  163. # ____________________________________________________________
  164. def cfunction_declarations(self):
  165. # declare the local variables, excluding the function arguments
  166. seen = {}
  167. for a in self.graph.getargs():
  168. seen[a.name] = True
  169. result_by_name = []
  170. for v in self.allvariables():
  171. name = v.name
  172. if name not in seen:
  173. seen[name] = True
  174. result = cdecl(self.lltypename(v), LOCALVAR % name) + ';'
  175. if self.lltypemap(v) is Void:
  176. continue #result = '/*%s*/' % result
  177. result_by_name.append((v._name, result))
  178. result_by_name.sort()
  179. return [result for name, result in result_by_name]
  180. # ____________________________________________________________
  181. def cfunction_body(self):
  182. graph = self.graph
  183. yield 'goto block0;' # to avoid a warning "this label is not used"
  184. # generate the body of each block
  185. for block in graph.iterblocks():
  186. myblocknum = self.blocknum[block]
  187. yield ''
  188. yield 'block%d:' % myblocknum
  189. for i, op in enumerate(block.operations):
  190. for line in self.gen_op(op):
  191. yield line
  192. if len(block.exits) == 0:
  193. assert len(block.inputargs) == 1
  194. # regular return block
  195. if self.exception_policy == "CPython":
  196. assert self.lltypemap(self.graph.getreturnvar()) == PyObjPtr
  197. yield 'if (RPyExceptionOccurred()) {'
  198. yield '\tRPyConvertExceptionToCPython();'
  199. yield '\treturn NULL;'
  200. yield '}'
  201. retval = self.expr(block.inputargs[0])
  202. if self.exception_policy != "exc_helper":
  203. yield 'RPY_DEBUG_RETURN();'
  204. yield 'return %s;' % retval
  205. continue
  206. elif block.exitswitch is None:
  207. # single-exit block
  208. assert len(block.exits) == 1
  209. for op in self.gen_link(block.exits[0]):
  210. yield op
  211. elif block in self.innerloops:
  212. for line in self.gen_while_loop_hack(block):
  213. yield line
  214. else:
  215. assert block.exitswitch != c_last_exception
  216. # block ending in a switch on a value
  217. TYPE = self.lltypemap(block.exitswitch)
  218. if TYPE in (Bool, PyObjPtr):
  219. expr = self.expr(block.exitswitch)
  220. for link in block.exits[:0:-1]:
  221. assert link.exitcase in (False, True)
  222. if TYPE == Bool:
  223. if not link.exitcase:
  224. expr = '!' + expr
  225. elif TYPE == PyObjPtr:
  226. yield 'assert(%s == Py_True || %s == Py_False);' % (
  227. expr, expr)
  228. if link.exitcase:
  229. expr = '%s == Py_True' % expr
  230. else:
  231. expr = '%s == Py_False' % expr
  232. yield 'if (%s) {' % expr
  233. for op in self.gen_link(link):
  234. yield '\t' + op
  235. yield '}'
  236. link = block.exits[0]
  237. assert link.exitcase in (False, True)
  238. #yield 'assert(%s == %s);' % (self.expr(block.exitswitch),
  239. # self.genc.nameofvalue(link.exitcase, ct))
  240. for op in self.gen_link(link):
  241. yield op
  242. elif TYPE in (Signed, Unsigned, SignedLongLong,
  243. UnsignedLongLong, Char, UniChar):
  244. defaultlink = None
  245. expr = self.expr(block.exitswitch)
  246. yield 'switch (%s) {' % self.expr(block.exitswitch)
  247. for link in block.exits:
  248. if link.exitcase == 'default':
  249. defaultlink = link
  250. continue
  251. yield 'case %s:' % self.db.get(link.llexitcase)
  252. for op in self.gen_link(link):
  253. yield '\t' + op
  254. # 'break;' not needed, as gen_link ends in a 'goto'
  255. # Emit default case
  256. yield 'default:'
  257. if defaultlink is None:
  258. yield '\tassert(!"bad switch!!");'
  259. else:
  260. for op in self.gen_link(defaultlink):
  261. yield '\t' + op
  262. yield '}'
  263. else:
  264. raise TypeError("exitswitch type not supported"
  265. " Got %r" % (TYPE,))
  266. def gen_link(self, link):
  267. "Generate the code to jump across the given Link."
  268. assignments = []
  269. for a1, a2 in zip(link.args, link.target.inputargs):
  270. a2type, a2typename = self.illtypes[a2]
  271. if a2type is Void:
  272. continue
  273. src = self.expr(a1)
  274. dest = LOCALVAR % a2.name
  275. assignments.append((a2typename, dest, src))
  276. for line in gen_assignments(assignments):
  277. yield line
  278. label = 'block%d' % self.blocknum[link.target]
  279. if link.target in self.innerloops:
  280. loop = self.innerloops[link.target]
  281. if link is loop.links[-1]: # link that ends a loop
  282. label += '_back'
  283. yield 'goto %s;' % label
  284. def gen_op(self, op):
  285. macro = 'OP_%s' % op.opname.upper()
  286. line = None
  287. if op.opname.startswith('gc_'):
  288. meth = getattr(self.gcpolicy, macro, None)
  289. if meth:
  290. line = meth(self, op)
  291. else:
  292. meth = getattr(self, macro, None)
  293. if meth:
  294. line = meth(op)
  295. if line is None:
  296. lst = [self.expr(v) for v in op.args]
  297. lst.append(self.expr(op.result))
  298. line = '%s(%s);' % (macro, ', '.join(lst))
  299. if "\n" not in line:
  300. yield line
  301. else:
  302. for line in line.splitlines():
  303. yield line
  304. def gen_while_loop_hack(self, headblock):
  305. # a GCC optimization hack: generate 'while' statement in the
  306. # source to convince the C compiler that it is really dealing
  307. # with loops. For the head of a loop (i.e. the block where the
  308. # decision is) we produce code like this:
  309. #
  310. # headblock:
  311. # ...headblock operations...
  312. # while (cond) {
  313. # goto firstbodyblock;
  314. # headblock_back:
  315. # ...headblock operations...
  316. # }
  317. #
  318. # The real body of the loop is not syntactically within the
  319. # scope of { }, but apparently this doesn't matter to GCC as
  320. # long as it is within the { } via the chain of goto's starting
  321. # at firstbodyblock: and ending at headblock_back:. We need to
  322. # duplicate the operations of headblock, though, because the
  323. # chain of gotos entering the loop must arrive outside the
  324. # while() at the headblock: label and the chain of goto's that
  325. # close the loop must arrive inside the while() at the
  326. # headblock_back: label.
  327. looplinks = self.innerloops[headblock].links
  328. enterlink = looplinks[0]
  329. assert len(headblock.exits) == 2
  330. assert isinstance(headblock.exits[0].exitcase, bool)
  331. assert isinstance(headblock.exits[1].exitcase, bool)
  332. i = list(headblock.exits).index(enterlink)
  333. exitlink = headblock.exits[1 - i]
  334. expr = self.expr(headblock.exitswitch)
  335. if enterlink.exitcase == False:
  336. expr = '!' + expr
  337. yield 'while (%s) {' % expr
  338. for op in self.gen_link(enterlink):
  339. yield '\t' + op
  340. # the semicolon after the colon is needed in case no operation
  341. # produces any code after the label
  342. yield '\t block%d_back: ;' % self.blocknum[headblock]
  343. if headblock.operations:
  344. for i, op in enumerate(headblock.operations):
  345. for line in self.gen_op(op):
  346. yield '\t' + line
  347. yield '}'
  348. for op in self.gen_link(exitlink):
  349. yield op
  350. # ____________________________________________________________
  351. # the C preprocessor cannot handle operations taking a variable number
  352. # of arguments, so here are Python methods that do it
  353. def OP_NEWLIST(self, op):
  354. args = [self.expr(v) for v in op.args]
  355. r = self.expr(op.result)
  356. if len(args) == 0:
  357. return 'OP_NEWLIST0(%s);' % (r, )
  358. else:
  359. args.insert(0, '%d' % len(args))
  360. return 'OP_NEWLIST((%s), %s);' % (', '.join(args), r)
  361. def OP_NEWDICT(self, op):
  362. args = [self.expr(v) for v in op.args]
  363. r = self.expr(op.result)
  364. if len(args) == 0:
  365. return 'OP_NEWDICT0(%s);' % (r, )
  366. else:
  367. assert len(args) % 2 == 0
  368. args.insert(0, '%d' % (len(args)//2))
  369. return 'OP_NEWDICT((%s), %s);' % (', '.join(args), r)
  370. def OP_NEWTUPLE(self, op):
  371. args = [self.expr(v) for v in op.args]
  372. r = self.expr(op.result)
  373. args.insert(0, '%d' % len(args))
  374. return 'OP_NEWTUPLE((%s), %s);' % (', '.join(args), r)
  375. def OP_SIMPLE_CALL(self, op):
  376. args = [self.expr(v) for v in op.args]
  377. r = self.expr(op.result)
  378. args.append('NULL')
  379. return 'OP_SIMPLE_CALL((%s), %s);' % (', '.join(args), r)
  380. def OP_CALL_ARGS(self, op):
  381. args = [self.expr(v) for v in op.args]
  382. r = self.expr(op.result)
  383. return 'OP_CALL_ARGS((%s), %s);' % (', '.join(args), r)
  384. def generic_call(self, FUNC, fnexpr, args_v, v_result, targets=None):
  385. args = []
  386. assert len(args_v) == len(FUNC.TO.ARGS)
  387. for v, ARGTYPE in zip(args_v, FUNC.TO.ARGS):
  388. if ARGTYPE is Void:
  389. continue # skip 'void' argument
  390. args.append(self.expr(v))
  391. # special case for rctypes: by-value container args:
  392. # XXX is this still needed now that rctypes is gone
  393. if isinstance(ARGTYPE, ContainerType):
  394. args[-1] = '*%s' % (args[-1],)
  395. line = '%s(%s);' % (fnexpr, ', '.join(args))
  396. if self.lltypemap(v_result) is not Void:
  397. # skip assignment of 'void' return value
  398. r = self.expr(v_result)
  399. line = '%s = %s' % (r, line)
  400. if targets:
  401. for graph in targets:
  402. if getattr(graph, 'inhibit_tail_call', False):
  403. line += '\nPYPY_INHIBIT_TAIL_CALL();'
  404. break
  405. return line
  406. def OP_DIRECT_CALL(self, op):
  407. fn = op.args[0]
  408. try:
  409. targets = [fn.value._obj.graph]
  410. except AttributeError:
  411. targets = None
  412. return self.generic_call(fn.concretetype, self.expr(fn),
  413. op.args[1:], op.result, targets)
  414. def OP_INDIRECT_CALL(self, op):
  415. fn = op.args[0]
  416. return self.generic_call(fn.concretetype, self.expr(fn),
  417. op.args[1:-1], op.result, op.args[-1].value)
  418. def OP_ADR_CALL(self, op):
  419. ARGTYPES = [v.concretetype for v in op.args[1:]]
  420. RESTYPE = op.result.concretetype
  421. FUNC = Ptr(FuncType(ARGTYPES, RESTYPE))
  422. typename = self.db.gettype(FUNC)
  423. fnaddr = op.args[0]
  424. fnexpr = '((%s)%s)' % (cdecl(typename, ''), self.expr(fnaddr))
  425. return self.generic_call(FUNC, fnexpr, op.args[1:], op.result)
  426. # low-level operations
  427. def generic_get(self, op, sourceexpr):
  428. T = self.lltypemap(op.result)
  429. newvalue = self.expr(op.result, special_case_void=False)
  430. result = '%s = %s;' % (newvalue, sourceexpr)
  431. if T is Void:
  432. result = '/* %s */' % result
  433. return result
  434. def generic_set(self, op, targetexpr):
  435. newvalue = self.expr(op.args[-1], special_case_void=False)
  436. result = '%s = %s;' % (targetexpr, newvalue)
  437. T = self.lltypemap(op.args[-1])
  438. if T is Void:
  439. result = '/* %s */' % result
  440. return result
  441. def OP_GETFIELD(self, op, ampersand=''):
  442. assert isinstance(op.args[1], Constant)
  443. STRUCT = self.lltypemap(op.args[0]).TO
  444. structdef = self.db.gettypedefnode(STRUCT)
  445. baseexpr_is_const = isinstance(op.args[0], Constant)
  446. expr = ampersand + structdef.ptr_access_expr(self.expr(op.args[0]),
  447. op.args[1].value,
  448. baseexpr_is_const)
  449. return self.generic_get(op, expr)
  450. def OP_BARE_SETFIELD(self, op):
  451. assert isinstance(op.args[1], Constant)
  452. STRUCT = self.lltypemap(op.args[0]).TO
  453. structdef = self.db.gettypedefnode(STRUCT)
  454. baseexpr_is_const = isinstance(op.args[0], Constant)
  455. expr = structdef.ptr_access_expr(self.expr(op.args[0]),
  456. op.args[1].value,
  457. baseexpr_is_const)
  458. return self.generic_set(op, expr)
  459. def OP_GETSUBSTRUCT(self, op):
  460. RESULT = self.lltypemap(op.result).TO
  461. if isinstance(RESULT, FixedSizeArray):
  462. return self.OP_GETFIELD(op, ampersand='')
  463. else:
  464. return self.OP_GETFIELD(op, ampersand='&')
  465. def OP_GETARRAYSIZE(self, op):
  466. ARRAY = self.lltypemap(op.args[0]).TO
  467. if isinstance(ARRAY, FixedSizeArray):
  468. return '%s = %d;' % (self.expr(op.result),
  469. ARRAY.length)
  470. else:
  471. return '%s = %s->length;' % (self.expr(op.result),
  472. self.expr(op.args[0]))
  473. def OP_GETARRAYITEM(self, op):
  474. ARRAY = self.lltypemap(op.args[0]).TO
  475. ptr = self.expr(op.args[0])
  476. index = self.expr(op.args[1])
  477. arraydef = self.db.gettypedefnode(ARRAY)
  478. return self.generic_get(op, arraydef.itemindex_access_expr(ptr, index))
  479. def OP_SETARRAYITEM(self, op):
  480. ARRAY = self.lltypemap(op.args[0]).TO
  481. ptr = self.expr(op.args[0])
  482. index = self.expr(op.args[1])
  483. arraydef = self.db.gettypedefnode(ARRAY)
  484. return self.generic_set(op, arraydef.itemindex_access_expr(ptr, index))
  485. OP_BARE_SETARRAYITEM = OP_SETARRAYITEM
  486. def OP_GETARRAYSUBSTRUCT(self, op):
  487. ARRAY = self.lltypemap(op.args[0]).TO
  488. ptr = self.expr(op.args[0])
  489. index = self.expr(op.args[1])
  490. arraydef = self.db.gettypedefnode(ARRAY)
  491. return '%s = &%s;' % (self.expr(op.result),
  492. arraydef.itemindex_access_expr(ptr, index))
  493. def interior_expr(self, args, rettype=False):
  494. TYPE = args[0].concretetype.TO
  495. expr = self.expr(args[0])
  496. for i, arg in enumerate(args[1:]):
  497. defnode = self.db.gettypedefnode(TYPE)
  498. if arg.concretetype is Void:
  499. fieldname = arg.value
  500. if i == 0:
  501. expr = defnode.ptr_access_expr(expr, fieldname)
  502. else:
  503. expr = defnode.access_expr(expr, fieldname)
  504. if isinstance(TYPE, FixedSizeArray):
  505. TYPE = TYPE.OF
  506. else:
  507. TYPE = getattr(TYPE, fieldname)
  508. else:
  509. indexexpr = self.expr(arg)
  510. if i == 0:
  511. expr = defnode.itemindex_access_expr(expr, indexexpr)
  512. else:
  513. expr = defnode.access_expr_varindex(expr, indexexpr)
  514. TYPE = TYPE.OF
  515. if rettype:
  516. return expr, TYPE
  517. else:
  518. return expr
  519. def OP_GETINTERIORFIELD(self, op):
  520. return self.generic_get(op, self.interior_expr(op.args))
  521. def OP_BARE_SETINTERIORFIELD(self, op):
  522. return self.generic_set(op, self.interior_expr(op.args[:-1]))
  523. def OP_GETINTERIORARRAYSIZE(self, op):
  524. expr, ARRAY = self.interior_expr(op.args, True)
  525. if isinstance(ARRAY, FixedSizeArray):
  526. return '%s = %d;'%(self.expr(op.result), ARRAY.length)
  527. else:
  528. assert isinstance(ARRAY, Array)
  529. return '%s = %s.length;'%(self.expr(op.result), expr)
  530. def OP_PTR_NONZERO(self, op):
  531. return '%s = (%s != NULL);' % (self.expr(op.result),
  532. self.expr(op.args[0]))
  533. def OP_PTR_ISZERO(self, op):
  534. return '%s = (%s == NULL);' % (self.expr(op.result),
  535. self.expr(op.args[0]))
  536. def OP_PTR_EQ(self, op):
  537. return '%s = (%s == %s);' % (self.expr(op.result),
  538. self.expr(op.args[0]),
  539. self.expr(op.args[1]))
  540. def OP_PTR_NE(self, op):
  541. return '%s = (%s != %s);' % (self.expr(op.result),
  542. self.expr(op.args[0]),
  543. self.expr(op.args[1]))
  544. def OP_BOEHM_MALLOC(self, op):
  545. return 'OP_BOEHM_ZERO_MALLOC(%s, %s, void*, 0, 0);' % (self.expr(op.args[0]),
  546. self.expr(op.result))
  547. def OP_BOEHM_MALLOC_ATOMIC(self, op):
  548. return 'OP_BOEHM_ZERO_MALLOC(%s, %s, void*, 1, 0);' % (self.expr(op.args[0]),
  549. self.expr(op.result))
  550. def OP_BOEHM_REGISTER_FINALIZER(self, op):
  551. return 'GC_REGISTER_FINALIZER(%s, (GC_finalization_proc)%s, NULL, NULL, NULL);' \
  552. % (self.expr(op.args[0]), self.expr(op.args[1]))
  553. def OP_RAW_MALLOC(self, op):
  554. eresult = self.expr(op.result)
  555. esize = self.expr(op.args[0])
  556. return "OP_RAW_MALLOC(%s, %s, void *);" % (esize, eresult)
  557. def OP_STACK_MALLOC(self, op):
  558. eresult = self.expr(op.result)
  559. esize = self.expr(op.args[0])
  560. return "OP_STACK_MALLOC(%s, %s, void *);" % (esize, eresult)
  561. def OP_DIRECT_FIELDPTR(self, op):
  562. return self.OP_GETFIELD(op, ampersand='&')
  563. def OP_DIRECT_ARRAYITEMS(self, op):
  564. ARRAY = self.lltypemap(op.args[0]).TO
  565. items = self.expr(op.args[0])
  566. if not isinstance(ARRAY, FixedSizeArray) and not barebonearray(ARRAY):
  567. items += '->items'
  568. return '%s = %s;' % (self.expr(op.result), items)
  569. def OP_DIRECT_PTRADD(self, op):
  570. ARRAY = self.lltypemap(op.args[0]).TO
  571. if ARRAY._hints.get("render_as_void"):
  572. return '%s = (char *)%s + %s;' % (
  573. self.expr(op.result),
  574. self.expr(op.args[0]),
  575. self.expr(op.args[1]))
  576. else:
  577. return '%s = %s + %s;' % (
  578. self.expr(op.result),
  579. self.expr(op.args[0]),
  580. self.expr(op.args[1]))
  581. def OP_CAST_POINTER(self, op):
  582. TYPE = self.lltypemap(op.result)
  583. typename = self.db.gettype(TYPE)
  584. result = []
  585. result.append('%s = (%s)%s;' % (self.expr(op.result),
  586. cdecl(typename, ''),
  587. self.expr(op.args[0])))
  588. return '\t'.join(result)
  589. OP_CAST_PTR_TO_ADR = OP_CAST_POINTER
  590. OP_CAST_ADR_TO_PTR = OP_CAST_POINTER
  591. OP_CAST_OPAQUE_PTR = OP_CAST_POINTER
  592. def OP_CAST_INT_TO_PTR(self, op):
  593. TYPE = self.lltypemap(op.result)
  594. typename = self.db.gettype(TYPE)
  595. return "%s = (%s)%s;" % (self.expr(op.result), cdecl(typename, ""),
  596. self.expr(op.args[0]))
  597. def OP_SAME_AS(self, op):
  598. result = []
  599. TYPE = self.lltypemap(op.result)
  600. assert self.lltypemap(op.args[0]) == TYPE
  601. if TYPE is not Void:
  602. result.append('%s = %s;' % (self.expr(op.result),
  603. self.expr(op.args[0])))
  604. return '\t'.join(result)
  605. def OP_HINT(self, op):
  606. hints = op.args[1].value
  607. return '%s\t/* hint: %r */' % (self.OP_SAME_AS(op), hints)
  608. def OP_KEEPALIVE(self, op): # xxx what should be the sematics consequences of this
  609. v = op.args[0]
  610. TYPE = self.lltypemap(v)
  611. if TYPE is Void:
  612. return "/* kept alive: void */"
  613. if isinstance(TYPE, Ptr) and TYPE.TO._gckind == 'gc':
  614. meth = getattr(self.gcpolicy, 'GC_KEEPALIVE', None)
  615. if meth:
  616. return meth(self, v)
  617. return "/* kept alive: %s */" % self.expr(v)
  618. #address operations
  619. def OP_RAW_STORE(self, op):
  620. addr = self.expr(op.args[0])
  621. TYPE = op.args[1].value
  622. offset = self.expr(op.args[2])
  623. value = self.expr(op.args[3])
  624. typename = cdecl(self.db.gettype(TYPE).replace('@', '*@'), '')
  625. return "((%(typename)s) %(addr)s)[%(offset)s] = %(value)s;" % locals()
  626. def OP_RAW_LOAD(self, op):
  627. addr = self.expr(op.args[0])
  628. TYPE = op.args[1].value
  629. offset = self.expr(op.args[2])
  630. result = self.expr(op.result)
  631. typename = cdecl(self.db.gettype(TYPE).replace('@', '*@'), '')
  632. return "%(result)s = ((%(typename)s) %(addr)s)[%(offset)s];" % locals()
  633. def OP_CAST_PRIMITIVE(self, op):
  634. TYPE = self.lltypemap(op.result)
  635. val = self.expr(op.args[0])
  636. ORIG = self.lltypemap(op.args[0])
  637. if ORIG is Char:
  638. val = "(unsigned char)%s" % val
  639. elif ORIG is UniChar:
  640. val = "(unsigned long)%s" % val
  641. result = self.expr(op.result)
  642. typename = cdecl(self.db.gettype(TYPE), '')
  643. return "%(result)s = (%(typename)s)(%(val)s);" % locals()
  644. OP_FORCE_CAST = OP_CAST_PRIMITIVE # xxx the same logic works
  645. def OP_RESUME_POINT(self, op):
  646. return '/* resume point %s */'%(op.args[0],)
  647. def OP_DEBUG_PRINT(self, op):
  648. # XXX
  649. from pypy.rpython.lltypesystem.rstr import STR
  650. format = []
  651. argv = []
  652. free_line = ""
  653. for arg in op.args:
  654. T = arg.concretetype
  655. if T == Ptr(STR):
  656. if isinstance(arg, Constant):
  657. format.append(''.join(arg.value.chars).replace('%', '%%'))
  658. else:
  659. format.append('%s')
  660. argv.append('RPyString_AsCharP(%s)' % self.expr(arg))
  661. free_line = "RPyString_FreeCache();"
  662. continue
  663. elif T == Signed:
  664. format.append('%ld')
  665. elif T == Unsigned:
  666. format.append('%lu')
  667. elif T == Float:
  668. format.append('%f')
  669. elif isinstance(T, Ptr) or T == Address:
  670. format.append('%p')
  671. elif T == Char:
  672. if isinstance(arg, Constant):
  673. format.append(arg.value.replace('%', '%%'))
  674. continue
  675. format.append('%c')
  676. elif T == Bool:
  677. format.append('%s')
  678. argv.append('(%s) ? "True" : "False"' % self.expr(arg))
  679. continue
  680. elif T == SignedLongLong:
  681. if sys.platform == 'win32':
  682. format.append('%I64d')
  683. else:
  684. format.append('%lld')
  685. elif T == UnsignedLongLong:
  686. if sys.platform == 'win32':
  687. format.append('%I64u')
  688. else:
  689. format.append('%llu')
  690. else:
  691. raise Exception("don't know how to debug_print %r" % (T,))
  692. argv.append(self.expr(arg))
  693. argv.insert(0, c_string_constant(' '.join(format) + '\n'))
  694. return (
  695. "if (PYPY_HAVE_DEBUG_PRINTS) { fprintf(PYPY_DEBUG_FILE, %s); %s}"
  696. % (', '.join(argv), free_line))
  697. def _op_debug(self, opname, arg):
  698. if isinstance(arg, Constant):
  699. string_literal = c_string_constant(''.join(arg.value.chars))
  700. return "%s(%s);" % (opname, string_literal)
  701. else:
  702. x = "%s(RPyString_AsCharP(%s));\n" % (opname, self.expr(arg))
  703. x += "RPyString_FreeCache();"
  704. return x
  705. def OP_DEBUG_START(self, op):
  706. return self._op_debug('PYPY_DEBUG_START', op.args[0])
  707. def OP_DEBUG_STOP(self, op):
  708. return self._op_debug('PYPY_DEBUG_STOP', op.args[0])
  709. def OP_DEBUG_ASSERT(self, op):
  710. return 'RPyAssert(%s, %s);' % (self.expr(op.args[0]),
  711. c_string_constant(op.args[1].value))
  712. def OP_DEBUG_FATALERROR(self, op):
  713. # XXX
  714. from pypy.rpython.lltypesystem.rstr import STR
  715. msg = op.args[0]
  716. assert msg.concretetype == Ptr(STR)
  717. if isinstance(msg, Constant):
  718. msg = c_string_constant(''.join(msg.value.chars))
  719. else:
  720. msg = 'RPyString_AsCharP(%s)' % self.expr(msg)
  721. return 'fprintf(stderr, "%%s\\n", %s); abort();' % msg
  722. def OP_DEBUG_LLINTERPCALL(self, op):
  723. result = 'abort(); /* debug_llinterpcall should be unreachable */'
  724. TYPE = self.lltypemap(op.result)
  725. if TYPE is not Void:
  726. typename = self.db.gettype(TYPE)
  727. result += '\n%s = (%s)0;' % (self.expr(op.result),
  728. cdecl(typename, ''))
  729. return result
  730. def OP_DEBUG_NONNULL_POINTER(self, op):
  731. expr = self.expr(op.args[0])
  732. return 'if ((-8192 <= (long)%s) && (((long)%s) < 8192)) abort();' % (
  733. expr, expr)
  734. def OP_INSTRUMENT_COUNT(self, op):
  735. counter_label = op.args[1].value
  736. self.db.instrument_ncounter = max(self.db.instrument_ncounter,
  737. counter_label+1)
  738. counter_label = self.expr(op.args[1])
  739. return 'INSTRUMENT_COUNT(%s);' % counter_label
  740. def OP_IS_EARLY_CONSTANT(self, op):
  741. return '%s = 0; /* IS_EARLY_CONSTANT */' % (self.expr(op.result),)
  742. def OP_JIT_MARKER(self, op):
  743. return '/* JIT_MARKER %s */' % op
  744. def OP_JIT_FORCE_VIRTUALIZABLE(self, op):
  745. return '/* JIT_FORCE_VIRTUALIZABLE %s */' % op
  746. def OP_JIT_FORCE_VIRTUAL(self, op):
  747. return '%s = %s; /* JIT_FORCE_VIRTUAL */' % (self.expr(op.result),
  748. self.expr(op.args[0]))
  749. def OP_JIT_IS_VIRTUAL(self, op):
  750. return '%s = 0; /* JIT_IS_VIRTUAL */' % (self.expr(op.result),)
  751. def OP_JIT_FORCE_QUASI_IMMUTABLE(self, op):
  752. return '/* JIT_FORCE_QUASI_IMMUTABLE %s */' % op
  753. def OP_GET_GROUP_MEMBER(self, op):
  754. typename = self.db.gettype(op.result.concretetype)
  755. return '%s = (%s)_OP_GET_GROUP_MEMBER(%s, %s);' % (
  756. self.expr(op.result),
  757. cdecl(typename, ''),
  758. self.expr(op.args[0]),
  759. self.expr(op.args[1]))
  760. def OP_GET_NEXT_GROUP_MEMBER(self, op):
  761. typename = self.db.gettype(op.result.concretetype)
  762. return '%s = (%s)_OP_GET_NEXT_GROUP_MEMBER(%s, %s, %s);' % (
  763. self.expr(op.result),
  764. cdecl(typename, ''),
  765. self.expr(op.args[0]),
  766. self.expr(op.args[1]),
  767. self.expr(op.args[2]))
  768. def getdebugfunctionname(self):
  769. name = self.functionname
  770. if not name:
  771. return "?"
  772. if name.startswith('pypy_g_'):
  773. name = name[7:]
  774. return name
  775. def OP_DEBUG_RECORD_TRACEBACK(self, op):
  776. #if self.functionname is None, we print "?" as the argument */
  777. return 'PYPY_DEBUG_RECORD_TRACEBACK("%s");' % (
  778. self.getdebugfunctionname(),)
  779. def OP_DEBUG_CATCH_EXCEPTION(self, op):
  780. gottype = self.expr(op.args[0])
  781. exprs = []
  782. for c_limited_type in op.args[1:]:
  783. exprs.append('%s == %s' % (gottype, self.expr(c_limited_type)))
  784. return 'PYPY_DEBUG_CATCH_EXCEPTION("%s", %s, %s);' % (
  785. self.getdebugfunctionname(), gottype, ' || '.join(exprs))
  786. def OP_INT_BETWEEN(self, op):
  787. if (isinstance(op.args[0], Constant) and
  788. isinstance(op.args[2], Constant) and
  789. op.args[2].value - op.args[0].value == 1):
  790. # (a <= b < a+1) ----> (b == a)
  791. return '%s = (%s == %s); /* was INT_BETWEEN */' % (
  792. self.expr(op.result),
  793. self.expr(op.args[1]),
  794. self.expr(op.args[0]))
  795. else:
  796. return None # use the default
  797. assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator)