PageRenderTime 69ms CodeModel.GetById 14ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/jit/codewriter/jtransform.py

http://github.com/pypy/pypy
Python | 1758 lines | 1651 code | 57 blank | 50 comment | 78 complexity | 3d02cf1626a2333d8a8d6170508e5161 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

  1. import py
  2. from pypy.jit.codewriter import support, heaptracker, longlong
  3. from pypy.jit.codewriter.effectinfo import EffectInfo
  4. from pypy.jit.codewriter.flatten import ListOfKind, IndirectCallTargets
  5. from pypy.jit.codewriter.policy import log
  6. from pypy.jit.metainterp import quasiimmut
  7. from pypy.jit.metainterp.history import getkind
  8. from pypy.jit.metainterp.typesystem import deref, arrayItem
  9. from pypy.jit.metainterp.blackhole import BlackholeInterpreter
  10. from pypy.objspace.flow.model import SpaceOperation, Variable, Constant, c_last_exception
  11. from pypy.rlib import objectmodel
  12. from pypy.rlib.jit import _we_are_jitted
  13. from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rclass, rffi
  14. from pypy.rpython.rclass import IR_QUASIIMMUTABLE, IR_QUASIIMMUTABLE_ARRAY
  15. from pypy.translator.simplify import get_funcobj
  16. from pypy.translator.unsimplify import varoftype
  17. class UnsupportedMallocFlags(Exception):
  18. pass
  19. def transform_graph(graph, cpu=None, callcontrol=None, portal_jd=None):
  20. """Transform a control flow graph to make it suitable for
  21. being flattened in a JitCode.
  22. """
  23. t = Transformer(cpu, callcontrol, portal_jd)
  24. t.transform(graph)
  25. def integer_bounds(size, unsigned):
  26. if unsigned:
  27. return 0, 1 << (8 * size)
  28. else:
  29. return -(1 << (8 * size - 1)), 1 << (8 * size - 1)
  30. class Transformer(object):
  31. vable_array_vars = None
  32. def __init__(self, cpu=None, callcontrol=None, portal_jd=None):
  33. self.cpu = cpu
  34. self.callcontrol = callcontrol
  35. self.portal_jd = portal_jd # non-None only for the portal graph(s)
  36. def transform(self, graph):
  37. self.graph = graph
  38. for block in list(graph.iterblocks()):
  39. self.optimize_block(block)
  40. def optimize_block(self, block):
  41. if block.operations == ():
  42. return
  43. self.vable_array_vars = {}
  44. self.vable_flags = {}
  45. renamings = {}
  46. renamings_constants = {} # subset of 'renamings', {Var:Const} only
  47. newoperations = []
  48. #
  49. def do_rename(var, var_or_const):
  50. if var.concretetype is lltype.Void:
  51. renamings[var] = Constant(None, lltype.Void)
  52. return
  53. renamings[var] = var_or_const
  54. if isinstance(var_or_const, Constant):
  55. value = var_or_const.value
  56. value = lltype._cast_whatever(var.concretetype, value)
  57. renamings_constants[var] = Constant(value, var.concretetype)
  58. #
  59. for op in block.operations:
  60. if renamings_constants:
  61. op = self._do_renaming(renamings_constants, op)
  62. oplist = self.rewrite_operation(op)
  63. #
  64. count_before_last_operation = len(newoperations)
  65. if not isinstance(oplist, list):
  66. oplist = [oplist]
  67. for op1 in oplist:
  68. if isinstance(op1, SpaceOperation):
  69. newoperations.append(self._do_renaming(renamings, op1))
  70. elif op1 is None:
  71. # rewrite_operation() returns None to mean "has no real
  72. # effect, the result should just be renamed to args[0]"
  73. if op.result is not None:
  74. do_rename(op.result, renamings.get(op.args[0],
  75. op.args[0]))
  76. elif isinstance(op1, Constant):
  77. do_rename(op.result, op1)
  78. else:
  79. raise TypeError(repr(op1))
  80. #
  81. if block.exitswitch == c_last_exception:
  82. if len(newoperations) == count_before_last_operation:
  83. self._killed_exception_raising_operation(block)
  84. block.operations = newoperations
  85. block.exitswitch = renamings.get(block.exitswitch, block.exitswitch)
  86. self.follow_constant_exit(block)
  87. self.optimize_goto_if_not(block)
  88. for link in block.exits:
  89. self._check_no_vable_array(link.args)
  90. self._do_renaming_on_link(renamings, link)
  91. def _do_renaming(self, rename, op):
  92. op = SpaceOperation(op.opname, op.args[:], op.result)
  93. for i, v in enumerate(op.args):
  94. if isinstance(v, Variable):
  95. if v in rename:
  96. op.args[i] = rename[v]
  97. elif isinstance(v, ListOfKind):
  98. newlst = []
  99. for x in v:
  100. if x in rename:
  101. x = rename[x]
  102. newlst.append(x)
  103. op.args[i] = ListOfKind(v.kind, newlst)
  104. return op
  105. def _check_no_vable_array(self, list):
  106. if not self.vable_array_vars:
  107. return
  108. for v in list:
  109. if v in self.vable_array_vars:
  110. raise AssertionError(
  111. "A virtualizable array is passed around; it should\n"
  112. "only be used immediately after being read. Note\n"
  113. "that a possible cause is indexing with an index not\n"
  114. "known non-negative, or catching IndexError, or\n"
  115. "not inlining at all (for tests: use listops=True).\n"
  116. "Occurred in: %r" % self.graph)
  117. # extra explanation: with the way things are organized in
  118. # rpython/rlist.py, the ll_getitem becomes a function call
  119. # that is typically meant to be inlined by the JIT, but
  120. # this does not work with vable arrays because
  121. # jtransform.py expects the getfield and the getarrayitem
  122. # to be in the same basic block. It works a bit as a hack
  123. # for simple cases where we performed the backendopt
  124. # inlining before (even with a very low threshold, because
  125. # there is _always_inline_ on the relevant functions).
  126. def _do_renaming_on_link(self, rename, link):
  127. for i, v in enumerate(link.args):
  128. if isinstance(v, Variable):
  129. if v in rename:
  130. link.args[i] = rename[v]
  131. def _killed_exception_raising_operation(self, block):
  132. assert block.exits[0].exitcase is None
  133. block.exits = block.exits[:1]
  134. block.exitswitch = None
  135. # ----------
  136. def follow_constant_exit(self, block):
  137. v = block.exitswitch
  138. if isinstance(v, Constant) and v != c_last_exception:
  139. llvalue = v.value
  140. for link in block.exits:
  141. if link.llexitcase == llvalue:
  142. break
  143. else:
  144. assert link.exitcase == 'default'
  145. block.exitswitch = None
  146. link.exitcase = link.llexitcase = None
  147. block.recloseblock(link)
  148. def optimize_goto_if_not(self, block):
  149. """Replace code like 'v = int_gt(x,y); exitswitch = v'
  150. with just 'exitswitch = ('int_gt',x,y)'."""
  151. if len(block.exits) != 2:
  152. return False
  153. v = block.exitswitch
  154. if (v == c_last_exception or isinstance(v, tuple)
  155. or v.concretetype != lltype.Bool):
  156. return False
  157. for op in block.operations[::-1]:
  158. if v in op.args:
  159. return False # variable is also used in cur block
  160. if v is op.result:
  161. if op.opname not in ('int_lt', 'int_le', 'int_eq', 'int_ne',
  162. 'int_gt', 'int_ge',
  163. 'int_is_zero', 'int_is_true',
  164. 'ptr_eq', 'ptr_ne',
  165. 'ptr_iszero', 'ptr_nonzero'):
  166. return False # not a supported operation
  167. # ok! optimize this case
  168. block.operations.remove(op)
  169. block.exitswitch = (op.opname,) + tuple(op.args)
  170. if op.opname in ('ptr_iszero', 'ptr_nonzero'):
  171. block.exitswitch += ('-live-before',)
  172. # if the variable escape to the next block along a link,
  173. # replace it with a constant, because we know its value
  174. for link in block.exits:
  175. while v in link.args:
  176. index = link.args.index(v)
  177. link.args[index] = Constant(link.llexitcase,
  178. lltype.Bool)
  179. return True
  180. return False
  181. # ----------
  182. def rewrite_operation(self, op):
  183. try:
  184. rewrite = _rewrite_ops[op.opname]
  185. except KeyError:
  186. raise Exception("the JIT doesn't support the operation %r"
  187. " in %r" % (op, getattr(self, 'graph', '?')))
  188. return rewrite(self, op)
  189. def rewrite_op_same_as(self, op):
  190. if op.args[0] in self.vable_array_vars:
  191. self.vable_array_vars[op.result]= self.vable_array_vars[op.args[0]]
  192. def rewrite_op_cast_pointer(self, op):
  193. newop = self.rewrite_op_same_as(op)
  194. assert newop is None
  195. return
  196. # disabled for now
  197. if (self._is_rclass_instance(op.args[0]) and
  198. self._is_rclass_instance(op.result)):
  199. FROM = op.args[0].concretetype.TO
  200. TO = op.result.concretetype.TO
  201. if lltype._castdepth(TO, FROM) > 0:
  202. vtable = heaptracker.get_vtable_for_gcstruct(self.cpu, TO)
  203. const_vtable = Constant(vtable, lltype.typeOf(vtable))
  204. return [None, # hack, do the right renaming from op.args[0] to op.result
  205. SpaceOperation("record_known_class", [op.args[0], const_vtable], None)]
  206. def rewrite_op_jit_record_known_class(self, op):
  207. return SpaceOperation("record_known_class", [op.args[0], op.args[1]], None)
  208. def rewrite_op_cast_bool_to_int(self, op): pass
  209. def rewrite_op_cast_bool_to_uint(self, op): pass
  210. def rewrite_op_cast_char_to_int(self, op): pass
  211. def rewrite_op_cast_unichar_to_int(self, op): pass
  212. def rewrite_op_cast_int_to_char(self, op): pass
  213. def rewrite_op_cast_int_to_unichar(self, op): pass
  214. def rewrite_op_cast_int_to_uint(self, op): pass
  215. def rewrite_op_cast_uint_to_int(self, op): pass
  216. def _rewrite_symmetric(self, op):
  217. """Rewrite 'c1+v2' into 'v2+c1' in an attempt to avoid generating
  218. too many variants of the bytecode."""
  219. if (isinstance(op.args[0], Constant) and
  220. isinstance(op.args[1], Variable)):
  221. reversename = {'int_lt': 'int_gt',
  222. 'int_le': 'int_ge',
  223. 'int_gt': 'int_lt',
  224. 'int_ge': 'int_le',
  225. 'uint_lt': 'uint_gt',
  226. 'uint_le': 'uint_ge',
  227. 'uint_gt': 'uint_lt',
  228. 'uint_ge': 'uint_le',
  229. 'float_lt': 'float_gt',
  230. 'float_le': 'float_ge',
  231. 'float_gt': 'float_lt',
  232. 'float_ge': 'float_le',
  233. }.get(op.opname, op.opname)
  234. return SpaceOperation(reversename,
  235. [op.args[1], op.args[0]] + op.args[2:],
  236. op.result)
  237. else:
  238. return op
  239. rewrite_op_int_add = _rewrite_symmetric
  240. rewrite_op_int_mul = _rewrite_symmetric
  241. rewrite_op_int_and = _rewrite_symmetric
  242. rewrite_op_int_or = _rewrite_symmetric
  243. rewrite_op_int_xor = _rewrite_symmetric
  244. rewrite_op_int_lt = _rewrite_symmetric
  245. rewrite_op_int_le = _rewrite_symmetric
  246. rewrite_op_int_gt = _rewrite_symmetric
  247. rewrite_op_int_ge = _rewrite_symmetric
  248. rewrite_op_uint_lt = _rewrite_symmetric
  249. rewrite_op_uint_le = _rewrite_symmetric
  250. rewrite_op_uint_gt = _rewrite_symmetric
  251. rewrite_op_uint_ge = _rewrite_symmetric
  252. rewrite_op_float_add = _rewrite_symmetric
  253. rewrite_op_float_mul = _rewrite_symmetric
  254. rewrite_op_float_lt = _rewrite_symmetric
  255. rewrite_op_float_le = _rewrite_symmetric
  256. rewrite_op_float_gt = _rewrite_symmetric
  257. rewrite_op_float_ge = _rewrite_symmetric
  258. def rewrite_op_int_add_ovf(self, op):
  259. op0 = self._rewrite_symmetric(op)
  260. op1 = SpaceOperation('-live-', [], None)
  261. return [op0, op1]
  262. rewrite_op_int_mul_ovf = rewrite_op_int_add_ovf
  263. def rewrite_op_int_sub_ovf(self, op):
  264. op1 = SpaceOperation('-live-', [], None)
  265. return [op, op1]
  266. def _noop_rewrite(self, op):
  267. return op
  268. rewrite_op_convert_float_bytes_to_longlong = _noop_rewrite
  269. rewrite_op_convert_longlong_bytes_to_float = _noop_rewrite
  270. # ----------
  271. # Various kinds of calls
  272. def rewrite_op_direct_call(self, op):
  273. kind = self.callcontrol.guess_call_kind(op)
  274. return getattr(self, 'handle_%s_call' % kind)(op)
  275. def rewrite_op_indirect_call(self, op):
  276. kind = self.callcontrol.guess_call_kind(op)
  277. return getattr(self, 'handle_%s_indirect_call' % kind)(op)
  278. def rewrite_call(self, op, namebase, initialargs, args=None):
  279. """Turn 'i0 = direct_call(fn, i1, i2, ref1, ref2)'
  280. into 'i0 = xxx_call_ir_i(fn, descr, [i1,i2], [ref1,ref2])'.
  281. The name is one of '{residual,direct}_call_{r,ir,irf}_{i,r,f,v}'."""
  282. if args is None:
  283. args = op.args[1:]
  284. self._check_no_vable_array(args)
  285. lst_i, lst_r, lst_f = self.make_three_lists(args)
  286. reskind = getkind(op.result.concretetype)[0]
  287. if lst_f or reskind == 'f': kinds = 'irf'
  288. elif lst_i: kinds = 'ir'
  289. else: kinds = 'r'
  290. sublists = []
  291. if 'i' in kinds: sublists.append(lst_i)
  292. if 'r' in kinds: sublists.append(lst_r)
  293. if 'f' in kinds: sublists.append(lst_f)
  294. return SpaceOperation('%s_%s_%s' % (namebase, kinds, reskind),
  295. initialargs + sublists, op.result)
  296. def make_three_lists(self, vars):
  297. args_i = []
  298. args_r = []
  299. args_f = []
  300. for v in vars:
  301. self.add_in_correct_list(v, args_i, args_r, args_f)
  302. return [ListOfKind('int', args_i),
  303. ListOfKind('ref', args_r),
  304. ListOfKind('float', args_f)]
  305. def add_in_correct_list(self, v, lst_i, lst_r, lst_f):
  306. kind = getkind(v.concretetype)
  307. if kind == 'void': return
  308. elif kind == 'int': lst = lst_i
  309. elif kind == 'ref': lst = lst_r
  310. elif kind == 'float': lst = lst_f
  311. else: raise AssertionError(kind)
  312. lst.append(v)
  313. def handle_residual_call(self, op, extraargs=[], may_call_jitcodes=False):
  314. """A direct_call turns into the operation 'residual_call_xxx' if it
  315. is calling a function that we don't want to JIT. The initial args
  316. of 'residual_call_xxx' are the function to call, and its calldescr."""
  317. calldescr = self.callcontrol.getcalldescr(op)
  318. op1 = self.rewrite_call(op, 'residual_call',
  319. [op.args[0], calldescr] + extraargs)
  320. if may_call_jitcodes or self.callcontrol.calldescr_canraise(calldescr):
  321. op1 = [op1, SpaceOperation('-live-', [], None)]
  322. return op1
  323. def handle_regular_call(self, op):
  324. """A direct_call turns into the operation 'inline_call_xxx' if it
  325. is calling a function that we want to JIT. The initial arg of
  326. 'inline_call_xxx' is the JitCode of the called function."""
  327. [targetgraph] = self.callcontrol.graphs_from(op)
  328. jitcode = self.callcontrol.get_jitcode(targetgraph,
  329. called_from=self.graph)
  330. op0 = self.rewrite_call(op, 'inline_call', [jitcode])
  331. op1 = SpaceOperation('-live-', [], None)
  332. return [op0, op1]
  333. def handle_builtin_call(self, op):
  334. oopspec_name, args = support.decode_builtin_call(op)
  335. # dispatch to various implementations depending on the oopspec_name
  336. if oopspec_name.startswith('list.') or oopspec_name.startswith('newlist'):
  337. prepare = self._handle_list_call
  338. elif oopspec_name.startswith('stroruni.'):
  339. prepare = self._handle_stroruni_call
  340. elif oopspec_name == 'str.str2unicode':
  341. prepare = self._handle_str2unicode_call
  342. elif oopspec_name.startswith('virtual_ref'):
  343. prepare = self._handle_virtual_ref_call
  344. elif oopspec_name.startswith('jit.'):
  345. prepare = self._handle_jit_call
  346. elif oopspec_name.startswith('libffi_'):
  347. prepare = self._handle_libffi_call
  348. elif oopspec_name.startswith('math.sqrt'):
  349. prepare = self._handle_math_sqrt_call
  350. else:
  351. prepare = self.prepare_builtin_call
  352. try:
  353. op1 = prepare(op, oopspec_name, args)
  354. except NotSupported:
  355. op1 = op
  356. # If the resulting op1 is still a direct_call, turn it into a
  357. # residual_call.
  358. if isinstance(op1, SpaceOperation) and op1.opname == 'direct_call':
  359. op1 = self.handle_residual_call(op1)
  360. return op1
  361. def handle_recursive_call(self, op):
  362. jitdriver_sd = self.callcontrol.jitdriver_sd_from_portal_runner_ptr(
  363. op.args[0].value)
  364. assert jitdriver_sd is not None
  365. ops = self.promote_greens(op.args[1:], jitdriver_sd.jitdriver)
  366. num_green_args = len(jitdriver_sd.jitdriver.greens)
  367. args = ([Constant(jitdriver_sd.index, lltype.Signed)] +
  368. self.make_three_lists(op.args[1:1+num_green_args]) +
  369. self.make_three_lists(op.args[1+num_green_args:]))
  370. kind = getkind(op.result.concretetype)[0]
  371. op0 = SpaceOperation('recursive_call_%s' % kind, args, op.result)
  372. op1 = SpaceOperation('-live-', [], None)
  373. return ops + [op0, op1]
  374. handle_residual_indirect_call = handle_residual_call
  375. def handle_regular_indirect_call(self, op):
  376. """An indirect call where at least one target has a JitCode."""
  377. lst = []
  378. for targetgraph in self.callcontrol.graphs_from(op):
  379. jitcode = self.callcontrol.get_jitcode(targetgraph,
  380. called_from=self.graph)
  381. lst.append(jitcode)
  382. op0 = SpaceOperation('-live-', [], None)
  383. op1 = SpaceOperation('int_guard_value', [op.args[0]], None)
  384. op2 = self.handle_residual_call(op, [IndirectCallTargets(lst)], True)
  385. result = [op0, op1]
  386. if isinstance(op2, list):
  387. result += op2
  388. else:
  389. result.append(op2)
  390. return result
  391. def prepare_builtin_call(self, op, oopspec_name, args,
  392. extra=None, extrakey=None):
  393. argtypes = [v.concretetype for v in args]
  394. resulttype = op.result.concretetype
  395. c_func, TP = support.builtin_func_for_spec(self.cpu.rtyper,
  396. oopspec_name, argtypes,
  397. resulttype, extra, extrakey)
  398. return SpaceOperation('direct_call', [c_func] + args, op.result)
  399. def _do_builtin_call(self, op, oopspec_name=None, args=None,
  400. extra=None, extrakey=None):
  401. if oopspec_name is None: oopspec_name = op.opname
  402. if args is None: args = op.args
  403. op1 = self.prepare_builtin_call(op, oopspec_name, args,
  404. extra, extrakey)
  405. return self.rewrite_op_direct_call(op1)
  406. # XXX some of the following functions should not become residual calls
  407. # but be really compiled
  408. rewrite_op_int_floordiv_ovf_zer = _do_builtin_call
  409. rewrite_op_int_floordiv_ovf = _do_builtin_call
  410. rewrite_op_int_floordiv_zer = _do_builtin_call
  411. rewrite_op_int_mod_ovf_zer = _do_builtin_call
  412. rewrite_op_int_mod_ovf = _do_builtin_call
  413. rewrite_op_int_mod_zer = _do_builtin_call
  414. rewrite_op_int_lshift_ovf = _do_builtin_call
  415. rewrite_op_int_abs = _do_builtin_call
  416. rewrite_op_llong_abs = _do_builtin_call
  417. rewrite_op_llong_floordiv = _do_builtin_call
  418. rewrite_op_llong_floordiv_zer = _do_builtin_call
  419. rewrite_op_llong_mod = _do_builtin_call
  420. rewrite_op_llong_mod_zer = _do_builtin_call
  421. rewrite_op_ullong_floordiv = _do_builtin_call
  422. rewrite_op_ullong_floordiv_zer = _do_builtin_call
  423. rewrite_op_ullong_mod = _do_builtin_call
  424. rewrite_op_ullong_mod_zer = _do_builtin_call
  425. rewrite_op_gc_identityhash = _do_builtin_call
  426. rewrite_op_gc_id = _do_builtin_call
  427. rewrite_op_uint_mod = _do_builtin_call
  428. rewrite_op_cast_float_to_uint = _do_builtin_call
  429. rewrite_op_cast_uint_to_float = _do_builtin_call
  430. # ----------
  431. # getfield/setfield/mallocs etc.
  432. def rewrite_op_hint(self, op):
  433. hints = op.args[1].value
  434. if hints.get('promote') and op.args[0].concretetype is not lltype.Void:
  435. assert op.args[0].concretetype != lltype.Ptr(rstr.STR)
  436. kind = getkind(op.args[0].concretetype)
  437. op0 = SpaceOperation('-live-', [], None)
  438. op1 = SpaceOperation('%s_guard_value' % kind, [op.args[0]], None)
  439. # the special return value None forces op.result to be considered
  440. # equal to op.args[0]
  441. return [op0, op1, None]
  442. if (hints.get('promote_string') and
  443. op.args[0].concretetype is not lltype.Void):
  444. S = lltype.Ptr(rstr.STR)
  445. assert op.args[0].concretetype == S
  446. self._register_extra_helper(EffectInfo.OS_STREQ_NONNULL,
  447. "str.eq_nonnull",
  448. [S, S],
  449. lltype.Signed,
  450. EffectInfo.EF_ELIDABLE_CANNOT_RAISE)
  451. descr, p = self.callcontrol.callinfocollection.callinfo_for_oopspec(
  452. EffectInfo.OS_STREQ_NONNULL)
  453. # XXX this is fairly ugly way of creating a constant,
  454. # however, callinfocollection has no better interface
  455. c = Constant(p.adr.ptr, lltype.typeOf(p.adr.ptr))
  456. op1 = SpaceOperation('str_guard_value', [op.args[0], c, descr],
  457. op.result)
  458. return [SpaceOperation('-live-', [], None), op1, None]
  459. else:
  460. log.WARNING('ignoring hint %r at %r' % (hints, self.graph))
  461. def _rewrite_raw_malloc(self, op, name, args):
  462. d = op.args[1].value.copy()
  463. d.pop('flavor')
  464. add_memory_pressure = d.pop('add_memory_pressure', False)
  465. zero = d.pop('zero', False)
  466. track_allocation = d.pop('track_allocation', True)
  467. if d:
  468. raise UnsupportedMallocFlags(d)
  469. TYPE = op.args[0].value
  470. if zero:
  471. name += '_zero'
  472. if add_memory_pressure:
  473. name += '_add_memory_pressure'
  474. if not track_allocation:
  475. name += '_no_track_allocation'
  476. return self._do_builtin_call(op, name, args,
  477. extra = (TYPE,),
  478. extrakey = TYPE)
  479. def rewrite_op_malloc_varsize(self, op):
  480. if op.args[1].value['flavor'] == 'raw':
  481. return self._rewrite_raw_malloc(op, 'raw_malloc_varsize',
  482. [op.args[2]])
  483. if op.args[0].value == rstr.STR:
  484. return SpaceOperation('newstr', [op.args[2]], op.result)
  485. elif op.args[0].value == rstr.UNICODE:
  486. return SpaceOperation('newunicode', [op.args[2]], op.result)
  487. else:
  488. # XXX only strings or simple arrays for now
  489. ARRAY = op.args[0].value
  490. arraydescr = self.cpu.arraydescrof(ARRAY)
  491. return SpaceOperation('new_array', [arraydescr, op.args[2]],
  492. op.result)
  493. def rewrite_op_free(self, op):
  494. d = op.args[1].value.copy()
  495. assert d['flavor'] == 'raw'
  496. d.pop('flavor')
  497. track_allocation = d.pop('track_allocation', True)
  498. if d:
  499. raise UnsupportedMallocFlags(d)
  500. STRUCT = op.args[0].concretetype.TO
  501. name = 'raw_free'
  502. if not track_allocation:
  503. name += '_no_track_allocation'
  504. return self._do_builtin_call(op, name, [op.args[0]],
  505. extra = (STRUCT,), extrakey = STRUCT)
  506. def rewrite_op_getarrayitem(self, op):
  507. ARRAY = op.args[0].concretetype.TO
  508. if self._array_of_voids(ARRAY):
  509. return []
  510. if op.args[0] in self.vable_array_vars: # for virtualizables
  511. vars = self.vable_array_vars[op.args[0]]
  512. (v_base, arrayfielddescr, arraydescr) = vars
  513. kind = getkind(op.result.concretetype)
  514. return [SpaceOperation('-live-', [], None),
  515. SpaceOperation('getarrayitem_vable_%s' % kind[0],
  516. [v_base, arrayfielddescr, arraydescr,
  517. op.args[1]], op.result)]
  518. # normal case follows
  519. arraydescr = self.cpu.arraydescrof(ARRAY)
  520. kind = getkind(op.result.concretetype)
  521. return SpaceOperation('getarrayitem_%s_%s' % (ARRAY._gckind, kind[0]),
  522. [op.args[0], arraydescr, op.args[1]],
  523. op.result)
  524. def rewrite_op_setarrayitem(self, op):
  525. ARRAY = op.args[0].concretetype.TO
  526. if self._array_of_voids(ARRAY):
  527. return []
  528. if op.args[0] in self.vable_array_vars: # for virtualizables
  529. vars = self.vable_array_vars[op.args[0]]
  530. (v_base, arrayfielddescr, arraydescr) = vars
  531. kind = getkind(op.args[2].concretetype)
  532. return [SpaceOperation('-live-', [], None),
  533. SpaceOperation('setarrayitem_vable_%s' % kind[0],
  534. [v_base, arrayfielddescr, arraydescr,
  535. op.args[1], op.args[2]], None)]
  536. arraydescr = self.cpu.arraydescrof(ARRAY)
  537. kind = getkind(op.args[2].concretetype)
  538. return SpaceOperation('setarrayitem_%s_%s' % (ARRAY._gckind, kind[0]),
  539. [op.args[0], arraydescr, op.args[1], op.args[2]],
  540. None)
  541. def rewrite_op_getarraysize(self, op):
  542. ARRAY = op.args[0].concretetype.TO
  543. assert ARRAY._gckind == 'gc'
  544. if op.args[0] in self.vable_array_vars: # for virtualizables
  545. vars = self.vable_array_vars[op.args[0]]
  546. (v_base, arrayfielddescr, arraydescr) = vars
  547. return [SpaceOperation('-live-', [], None),
  548. SpaceOperation('arraylen_vable',
  549. [v_base, arrayfielddescr, arraydescr],
  550. op.result)]
  551. # normal case follows
  552. arraydescr = self.cpu.arraydescrof(ARRAY)
  553. return SpaceOperation('arraylen_gc', [op.args[0], arraydescr],
  554. op.result)
  555. def _array_of_voids(self, ARRAY):
  556. #if isinstance(ARRAY, ootype.Array):
  557. # return ARRAY.ITEM == ootype.Void
  558. #else:
  559. return ARRAY.OF == lltype.Void
  560. def rewrite_op_getfield(self, op):
  561. if self.is_typeptr_getset(op):
  562. return self.handle_getfield_typeptr(op)
  563. # turn the flow graph 'getfield' operation into our own version
  564. [v_inst, c_fieldname] = op.args
  565. RESULT = op.result.concretetype
  566. if RESULT is lltype.Void:
  567. return
  568. # check for virtualizable
  569. try:
  570. if self.is_virtualizable_getset(op):
  571. descr = self.get_virtualizable_field_descr(op)
  572. kind = getkind(RESULT)[0]
  573. return [SpaceOperation('-live-', [], None),
  574. SpaceOperation('getfield_vable_%s' % kind,
  575. [v_inst, descr], op.result)]
  576. except VirtualizableArrayField, e:
  577. # xxx hack hack hack
  578. vinfo = e.args[1]
  579. arrayindex = vinfo.array_field_counter[op.args[1].value]
  580. arrayfielddescr = vinfo.array_field_descrs[arrayindex]
  581. arraydescr = vinfo.array_descrs[arrayindex]
  582. self.vable_array_vars[op.result] = (op.args[0],
  583. arrayfielddescr,
  584. arraydescr)
  585. return []
  586. # check for _immutable_fields_ hints
  587. immut = v_inst.concretetype.TO._immutable_field(c_fieldname.value)
  588. if immut:
  589. if (self.callcontrol is not None and
  590. self.callcontrol.could_be_green_field(v_inst.concretetype.TO,
  591. c_fieldname.value)):
  592. pure = '_greenfield'
  593. else:
  594. pure = '_pure'
  595. else:
  596. pure = ''
  597. self.check_field_access(v_inst.concretetype.TO)
  598. argname = getattr(v_inst.concretetype.TO, '_gckind', 'gc')
  599. descr = self.cpu.fielddescrof(v_inst.concretetype.TO,
  600. c_fieldname.value)
  601. kind = getkind(RESULT)[0]
  602. op1 = SpaceOperation('getfield_%s_%s%s' % (argname, kind, pure),
  603. [v_inst, descr], op.result)
  604. #
  605. if immut in (IR_QUASIIMMUTABLE, IR_QUASIIMMUTABLE_ARRAY):
  606. descr1 = self.cpu.fielddescrof(
  607. v_inst.concretetype.TO,
  608. quasiimmut.get_mutate_field_name(c_fieldname.value))
  609. op1 = [SpaceOperation('-live-', [], None),
  610. SpaceOperation('record_quasiimmut_field',
  611. [v_inst, descr, descr1], None),
  612. op1]
  613. return op1
  614. def rewrite_op_setfield(self, op):
  615. if self.is_typeptr_getset(op):
  616. # ignore the operation completely -- instead, it's done by 'new'
  617. return
  618. # turn the flow graph 'setfield' operation into our own version
  619. [v_inst, c_fieldname, v_value] = op.args
  620. RESULT = v_value.concretetype
  621. if RESULT is lltype.Void:
  622. return
  623. # check for virtualizable
  624. if self.is_virtualizable_getset(op):
  625. descr = self.get_virtualizable_field_descr(op)
  626. kind = getkind(RESULT)[0]
  627. return [SpaceOperation('-live-', [], None),
  628. SpaceOperation('setfield_vable_%s' % kind,
  629. [v_inst, descr, v_value], None)]
  630. self.check_field_access(v_inst.concretetype.TO)
  631. argname = getattr(v_inst.concretetype.TO, '_gckind', 'gc')
  632. descr = self.cpu.fielddescrof(v_inst.concretetype.TO,
  633. c_fieldname.value)
  634. kind = getkind(RESULT)[0]
  635. return SpaceOperation('setfield_%s_%s' % (argname, kind),
  636. [v_inst, descr, v_value],
  637. None)
  638. def is_typeptr_getset(self, op):
  639. return (op.args[1].value == 'typeptr' and
  640. op.args[0].concretetype.TO._hints.get('typeptr'))
  641. def check_field_access(self, STRUCT):
  642. # check against a GcStruct with a nested GcStruct as a first argument
  643. # but which is not an object at all; see metainterp/test/test_loop,
  644. # test_regular_pointers_in_short_preamble.
  645. if not isinstance(STRUCT, lltype.GcStruct):
  646. return
  647. if STRUCT._first_struct() == (None, None):
  648. return
  649. PARENT = STRUCT
  650. while not PARENT._hints.get('typeptr'):
  651. _, PARENT = PARENT._first_struct()
  652. if PARENT is None:
  653. raise NotImplementedError("%r is a GcStruct using nesting but "
  654. "not inheriting from object" %
  655. (STRUCT,))
  656. def get_vinfo(self, v_virtualizable):
  657. if self.callcontrol is None: # for tests
  658. return None
  659. return self.callcontrol.get_vinfo(v_virtualizable.concretetype)
  660. def is_virtualizable_getset(self, op):
  661. # every access of an object of exactly the type VTYPEPTR is
  662. # likely to be a virtualizable access, but we still have to
  663. # check it in pyjitpl.py.
  664. vinfo = self.get_vinfo(op.args[0])
  665. if vinfo is None:
  666. return False
  667. res = False
  668. if op.args[1].value in vinfo.static_field_to_extra_box:
  669. res = True
  670. if op.args[1].value in vinfo.array_fields:
  671. res = VirtualizableArrayField(self.graph, vinfo)
  672. if res:
  673. flags = self.vable_flags[op.args[0]]
  674. if 'fresh_virtualizable' in flags:
  675. return False
  676. if isinstance(res, Exception):
  677. raise res
  678. return res
  679. def get_virtualizable_field_descr(self, op):
  680. fieldname = op.args[1].value
  681. vinfo = self.get_vinfo(op.args[0])
  682. index = vinfo.static_field_to_extra_box[fieldname]
  683. return vinfo.static_field_descrs[index]
  684. def handle_getfield_typeptr(self, op):
  685. if isinstance(op.args[0], Constant):
  686. cls = op.args[0].value.typeptr
  687. return Constant(cls, concretetype=rclass.CLASSTYPE)
  688. op0 = SpaceOperation('-live-', [], None)
  689. op1 = SpaceOperation('guard_class', [op.args[0]], op.result)
  690. return [op0, op1]
  691. def rewrite_op_malloc(self, op):
  692. if op.args[1].value['flavor'] == 'raw':
  693. return self._rewrite_raw_malloc(op, 'raw_malloc_fixedsize', [])
  694. #
  695. assert op.args[1].value == {'flavor': 'gc'}
  696. STRUCT = op.args[0].value
  697. vtable = heaptracker.get_vtable_for_gcstruct(self.cpu, STRUCT)
  698. if vtable:
  699. # do we have a __del__?
  700. try:
  701. rtti = lltype.getRuntimeTypeInfo(STRUCT)
  702. except ValueError:
  703. pass
  704. else:
  705. if hasattr(rtti._obj, 'destructor_funcptr'):
  706. RESULT = lltype.Ptr(STRUCT)
  707. assert RESULT == op.result.concretetype
  708. return self._do_builtin_call(op, 'alloc_with_del', [],
  709. extra = (RESULT, vtable),
  710. extrakey = STRUCT)
  711. heaptracker.register_known_gctype(self.cpu, vtable, STRUCT)
  712. opname = 'new_with_vtable'
  713. else:
  714. opname = 'new'
  715. sizedescr = self.cpu.sizeof(STRUCT)
  716. return SpaceOperation(opname, [sizedescr], op.result)
  717. def rewrite_op_getinteriorarraysize(self, op):
  718. # only supports strings and unicodes
  719. assert len(op.args) == 2
  720. assert op.args[1].value == 'chars'
  721. optype = op.args[0].concretetype
  722. if optype == lltype.Ptr(rstr.STR):
  723. opname = "strlen"
  724. else:
  725. assert optype == lltype.Ptr(rstr.UNICODE)
  726. opname = "unicodelen"
  727. return SpaceOperation(opname, [op.args[0]], op.result)
  728. def rewrite_op_getinteriorfield(self, op):
  729. assert len(op.args) == 3
  730. optype = op.args[0].concretetype
  731. if optype == lltype.Ptr(rstr.STR):
  732. opname = "strgetitem"
  733. return SpaceOperation(opname, [op.args[0], op.args[2]], op.result)
  734. elif optype == lltype.Ptr(rstr.UNICODE):
  735. opname = "unicodegetitem"
  736. return SpaceOperation(opname, [op.args[0], op.args[2]], op.result)
  737. else:
  738. v_inst, v_index, c_field = op.args
  739. if op.result.concretetype is lltype.Void:
  740. return
  741. # only GcArray of Struct supported
  742. assert isinstance(v_inst.concretetype.TO, lltype.GcArray)
  743. STRUCT = v_inst.concretetype.TO.OF
  744. assert isinstance(STRUCT, lltype.Struct)
  745. descr = self.cpu.interiorfielddescrof(v_inst.concretetype.TO,
  746. c_field.value)
  747. args = [v_inst, v_index, descr]
  748. kind = getkind(op.result.concretetype)[0]
  749. return SpaceOperation('getinteriorfield_gc_%s' % kind, args,
  750. op.result)
  751. def rewrite_op_setinteriorfield(self, op):
  752. assert len(op.args) == 4
  753. optype = op.args[0].concretetype
  754. if optype == lltype.Ptr(rstr.STR):
  755. opname = "strsetitem"
  756. return SpaceOperation(opname, [op.args[0], op.args[2], op.args[3]],
  757. op.result)
  758. elif optype == lltype.Ptr(rstr.UNICODE):
  759. opname = "unicodesetitem"
  760. return SpaceOperation(opname, [op.args[0], op.args[2], op.args[3]],
  761. op.result)
  762. else:
  763. v_inst, v_index, c_field, v_value = op.args
  764. if v_value.concretetype is lltype.Void:
  765. return
  766. # only GcArray of Struct supported
  767. assert isinstance(v_inst.concretetype.TO, lltype.GcArray)
  768. STRUCT = v_inst.concretetype.TO.OF
  769. assert isinstance(STRUCT, lltype.Struct)
  770. descr = self.cpu.interiorfielddescrof(v_inst.concretetype.TO,
  771. c_field.value)
  772. kind = getkind(v_value.concretetype)[0]
  773. args = [v_inst, v_index, v_value, descr]
  774. return SpaceOperation('setinteriorfield_gc_%s' % kind, args,
  775. op.result)
  776. def _rewrite_equality(self, op, opname):
  777. arg0, arg1 = op.args
  778. if isinstance(arg0, Constant) and not arg0.value:
  779. return SpaceOperation(opname, [arg1], op.result)
  780. elif isinstance(arg1, Constant) and not arg1.value:
  781. return SpaceOperation(opname, [arg0], op.result)
  782. else:
  783. return self._rewrite_symmetric(op)
  784. def _is_gc(self, v):
  785. return getattr(getattr(v.concretetype, "TO", None), "_gckind", "?") == 'gc'
  786. def _is_rclass_instance(self, v):
  787. return lltype._castdepth(v.concretetype.TO, rclass.OBJECT) >= 0
  788. def _rewrite_cmp_ptrs(self, op):
  789. if self._is_gc(op.args[0]):
  790. return op
  791. else:
  792. opname = {'ptr_eq': 'int_eq',
  793. 'ptr_ne': 'int_ne',
  794. 'ptr_iszero': 'int_is_zero',
  795. 'ptr_nonzero': 'int_is_true'}[op.opname]
  796. return SpaceOperation(opname, op.args, op.result)
  797. def rewrite_op_int_eq(self, op):
  798. return self._rewrite_equality(op, 'int_is_zero')
  799. def rewrite_op_int_ne(self, op):
  800. return self._rewrite_equality(op, 'int_is_true')
  801. def rewrite_op_ptr_eq(self, op):
  802. prefix = ''
  803. if self._is_rclass_instance(op.args[0]):
  804. assert self._is_rclass_instance(op.args[1])
  805. op = SpaceOperation('instance_ptr_eq', op.args, op.result)
  806. prefix = 'instance_'
  807. op1 = self._rewrite_equality(op, prefix + 'ptr_iszero')
  808. return self._rewrite_cmp_ptrs(op1)
  809. def rewrite_op_ptr_ne(self, op):
  810. prefix = ''
  811. if self._is_rclass_instance(op.args[0]):
  812. assert self._is_rclass_instance(op.args[1])
  813. op = SpaceOperation('instance_ptr_ne', op.args, op.result)
  814. prefix = 'instance_'
  815. op1 = self._rewrite_equality(op, prefix + 'ptr_nonzero')
  816. return self._rewrite_cmp_ptrs(op1)
  817. rewrite_op_ptr_iszero = _rewrite_cmp_ptrs
  818. rewrite_op_ptr_nonzero = _rewrite_cmp_ptrs
  819. def rewrite_op_cast_ptr_to_int(self, op):
  820. if self._is_gc(op.args[0]):
  821. return op
  822. def rewrite_op_cast_opaque_ptr(self, op):
  823. # None causes the result of this op to get aliased to op.args[0]
  824. return [SpaceOperation('mark_opaque_ptr', op.args, None), None]
  825. def rewrite_op_force_cast(self, op):
  826. v_arg = op.args[0]
  827. v_result = op.result
  828. assert not self._is_gc(v_arg)
  829. if v_arg.concretetype == v_result.concretetype:
  830. return
  831. float_arg = v_arg.concretetype in [lltype.Float, lltype.SingleFloat]
  832. float_res = v_result.concretetype in [lltype.Float, lltype.SingleFloat]
  833. if not float_arg and not float_res:
  834. # some int -> some int cast
  835. return self._int_to_int_cast(v_arg, v_result)
  836. elif float_arg and float_res:
  837. # some float -> some float cast
  838. return self._float_to_float_cast(v_arg, v_result)
  839. elif not float_arg and float_res:
  840. # some int -> some float
  841. ops = []
  842. v2 = varoftype(lltype.Float)
  843. sizesign = rffi.size_and_sign(v_arg.concretetype)
  844. if sizesign <= rffi.size_and_sign(lltype.Signed):
  845. # cast from a type that fits in an int: either the size is
  846. # smaller, or it is equal and it is not unsigned
  847. v1 = varoftype(lltype.Signed)
  848. oplist = self.rewrite_operation(
  849. SpaceOperation('force_cast', [v_arg], v1)
  850. )
  851. if oplist:
  852. ops.extend(oplist)
  853. else:
  854. v1 = v_arg
  855. op = self.rewrite_operation(
  856. SpaceOperation('cast_int_to_float', [v1], v2)
  857. )
  858. ops.append(op)
  859. else:
  860. if sizesign == rffi.size_and_sign(lltype.Unsigned):
  861. opname = 'cast_uint_to_float'
  862. elif sizesign == rffi.size_and_sign(lltype.SignedLongLong):
  863. opname = 'cast_longlong_to_float'
  864. elif sizesign == rffi.size_and_sign(lltype.UnsignedLongLong):
  865. opname = 'cast_ulonglong_to_float'
  866. else:
  867. raise AssertionError('cast_x_to_float: %r' % (sizesign,))
  868. ops1 = self.rewrite_operation(
  869. SpaceOperation(opname, [v_arg], v2)
  870. )
  871. if not isinstance(ops1, list): ops1 = [ops1]
  872. ops.extend(ops1)
  873. op2 = self.rewrite_operation(
  874. SpaceOperation('force_cast', [v2], v_result)
  875. )
  876. if op2:
  877. ops.append(op2)
  878. else:
  879. ops[-1].result = v_result
  880. return ops
  881. elif float_arg and not float_res:
  882. # some float -> some int
  883. ops = []
  884. v1 = varoftype(lltype.Float)
  885. op1 = self.rewrite_operation(
  886. SpaceOperation('force_cast', [v_arg], v1)
  887. )
  888. if op1:
  889. ops.append(op1)
  890. else:
  891. v1 = v_arg
  892. sizesign = rffi.size_and_sign(v_result.concretetype)
  893. if sizesign <= rffi.size_and_sign(lltype.Signed):
  894. # cast to a type that fits in an int: either the size is
  895. # smaller, or it is equal and it is not unsigned
  896. v2 = varoftype(lltype.Signed)
  897. op = self.rewrite_operation(
  898. SpaceOperation('cast_float_to_int', [v1], v2)
  899. )
  900. ops.append(op)
  901. oplist = self.rewrite_operation(
  902. SpaceOperation('force_cast', [v2], v_result)
  903. )
  904. if oplist:
  905. ops.extend(oplist)
  906. else:
  907. op.result = v_result
  908. else:
  909. if sizesign == rffi.size_and_sign(lltype.Unsigned):
  910. opname = 'cast_float_to_uint'
  911. elif sizesign == rffi.size_and_sign(lltype.SignedLongLong):
  912. opname = 'cast_float_to_longlong'
  913. elif sizesign == rffi.size_and_sign(lltype.UnsignedLongLong):
  914. opname = 'cast_float_to_ulonglong'
  915. else:
  916. raise AssertionError('cast_float_to_x: %r' % (sizesign,))
  917. ops1 = self.rewrite_operation(
  918. SpaceOperation(opname, [v1], v_result)
  919. )
  920. if not isinstance(ops1, list): ops1 = [ops1]
  921. ops.extend(ops1)
  922. return ops
  923. else:
  924. assert False
  925. def _int_to_int_cast(self, v_arg, v_result):
  926. longlong_arg = longlong.is_longlong(v_arg.concretetype)
  927. longlong_res = longlong.is_longlong(v_result.concretetype)
  928. size1, unsigned1 = rffi.size_and_sign(v_arg.concretetype)
  929. size2, unsigned2 = rffi.size_and_sign(v_result.concretetype)
  930. if longlong_arg and longlong_res:
  931. return
  932. elif longlong_arg:
  933. v = varoftype(lltype.Signed)
  934. op1 = self.rewrite_operation(
  935. SpaceOperation('truncate_longlong_to_int', [v_arg], v)
  936. )
  937. op2 = SpaceOperation('force_cast', [v], v_result)
  938. oplist = self.rewrite_operation(op2)
  939. if not oplist:
  940. op1.result = v_result
  941. oplist = []
  942. return [op1] + oplist
  943. elif longlong_res:
  944. if unsigned1:
  945. INTERMEDIATE = lltype.Unsigned
  946. else:
  947. INTERMEDIATE = lltype.Signed
  948. v = varoftype(INTERMEDIATE)
  949. op1 = SpaceOperation('force_cast', [v_arg], v)
  950. oplist = self.rewrite_operation(op1)
  951. if not oplist:
  952. v = v_arg
  953. oplist = []
  954. if unsigned1:
  955. if unsigned2:
  956. opname = 'cast_uint_to_ulonglong'
  957. else:
  958. opname = 'cast_uint_to_longlong'
  959. else:
  960. if unsigned2:
  961. opname = 'cast_int_to_ulonglong'
  962. else:
  963. opname = 'cast_int_to_longlong'
  964. op2 = self.rewrite_operation(
  965. SpaceOperation(opname, [v], v_result)
  966. )
  967. return oplist + [op2]
  968. # We've now, ostensibly, dealt with the longlongs, everything should be
  969. # a Signed or smaller
  970. assert size1 <= rffi.sizeof(lltype.Signed)
  971. assert size2 <= rffi.sizeof(lltype.Signed)
  972. # the target type is LONG or ULONG
  973. if size2 == rffi.sizeof(lltype.Signed):
  974. return
  975. min1, max1 = integer_bounds(size1, unsigned1)
  976. min2, max2 = integer_bounds(size2, unsigned2)
  977. # the target type includes the source range
  978. if min2 <= min1 <= max1 <= max2:
  979. return
  980. result = []
  981. if min2:
  982. c_min2 = Constant(min2, lltype.Signed)
  983. v2 = varoftype(lltype.Signed)
  984. result.append(SpaceOperation('int_sub', [v_arg, c_min2], v2))
  985. else:
  986. v2 = v_arg
  987. c_mask = Constant(int((1 << (8 * size2)) - 1), lltype.Signed)
  988. if min2:
  989. v3 = varoftype(lltype.Signed)
  990. else:
  991. v3 = v_result
  992. result.append(SpaceOperation('int_and', [v2, c_mask], v3))
  993. if min2:
  994. result.append(SpaceOperation('int_add', [v3, c_min2], v_result))
  995. return result
  996. def _float_to_float_cast(self, v_arg, v_result):
  997. if v_arg.concretetype == lltype.SingleFloat:
  998. assert v_result.concretetype == lltype.Float, "cast %s -> %s" % (
  999. v_arg.concretetype, v_result.concretetype)
  1000. return SpaceOperation('cast_singlefloat_to_float', [v_arg],
  1001. v_result)
  1002. if v_result.concretetype == lltype.SingleFloat:
  1003. assert v_arg.concretetype == lltype.Float, "cast %s -> %s" % (
  1004. v_arg.concretetype, v_result.concretetype)
  1005. return SpaceOperation('cast_float_to_singlefloat', [v_arg],
  1006. v_result)
  1007. def rewrite_op_direct_ptradd(self, op):
  1008. # xxx otherwise, not implemented:
  1009. assert op.args[0].concretetype == rffi.CCHARP
  1010. #
  1011. return SpaceOperation('int_add', [op.args[0], op.args[1]], op.result)
  1012. # ----------
  1013. # Long longs, for 32-bit only. Supported operations are left unmodified,
  1014. # and unsupported ones are turned into a call to a function from
  1015. # jit.codewriter.support.
  1016. for _op, _oopspec in [('llong_invert', 'INVERT'),
  1017. ('llong_lt', 'LT'),
  1018. ('llong_le', 'LE'),
  1019. ('llong_eq', 'EQ'),
  1020. ('llong_ne', 'NE'),
  1021. ('llong_gt', 'GT'),
  1022. ('llong_ge', 'GE'),
  1023. ('llong_add', 'ADD'),
  1024. ('llong_sub', 'SUB'),
  1025. ('llong_mul', 'MUL'),
  1026. ('llong_and', 'AND'),
  1027. ('llong_or', 'OR'),
  1028. ('llong_xor', 'XOR'),
  1029. ('llong_lshift', 'LSHIFT'),
  1030. ('llong_rshift', 'RSHIFT'),
  1031. ('cast_int_to_longlong', 'FROM_INT'),
  1032. ('truncate_longlong_to_int', 'TO_INT'),
  1033. ('cast_float_to_longlong', 'FROM_FLOAT'),
  1034. ('cast_longlong_to_float', 'TO_FLOAT'),
  1035. ('cast_uint_to_longlong', 'FROM_UINT'),
  1036. ]:
  1037. exec py.code.Source('''
  1038. def rewrite_op_%s(self, op):
  1039. args = op.args
  1040. op1 = self.prepare_builtin_call(op, "llong_%s", args)
  1041. op2 = self._handle_oopspec_call(op1, args,
  1042. EffectInfo.OS_LLONG_%s,
  1043. EffectInfo.EF_ELIDABLE_CANNOT_RAISE)
  1044. if %r == "TO_INT":
  1045. assert op2.result.concretetype == lltype.Signed
  1046. return op2
  1047. ''' % (_op, _oopspec.lower(), _oopspec, _oopspec)).compile()
  1048. for _op, _oopspec in [('cast_int_to_ulonglong', 'FROM_INT'),
  1049. ('cast_uint_to_ulonglong', 'FROM_UINT'),
  1050. ('cast_float_to_ulonglong', 'FROM_FLOAT'),
  1051. ('cast_ulonglong_to_float', 'U_TO_FLOAT'),

Large files files are truncated, but you can click here to view the full file