PageRenderTime 54ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/pypy/jit/codewriter/test/test_flatten.py

https://bitbucket.org/pypy/pypy/
Python | 992 lines | 970 code | 18 blank | 4 comment | 11 complexity | 3520bd12fd557eb760e0600752d8b445 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import py, sys
  2. from pypy.jit.codewriter import support
  3. from pypy.jit.codewriter.flatten import flatten_graph, reorder_renaming_list
  4. from pypy.jit.codewriter.flatten import GraphFlattener, ListOfKind, Register
  5. from pypy.jit.codewriter.format import assert_format
  6. from pypy.jit.codewriter import longlong
  7. from pypy.jit.metainterp.history import AbstractDescr
  8. from pypy.rpython.lltypesystem import lltype, rclass, rstr, rffi
  9. from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
  10. from pypy.translator.unsimplify import varoftype
  11. from pypy.rlib.rarithmetic import ovfcheck, r_uint, r_longlong, r_ulonglong
  12. from pypy.rlib.jit import dont_look_inside, _we_are_jitted, JitDriver
  13. from pypy.rlib.objectmodel import keepalive_until_here
  14. from pypy.rlib import jit
  15. class FakeRegAlloc:
  16. # a RegAllocator that answers "0, 1, 2, 3, 4..." for the colors
  17. def __init__(self):
  18. self.seen = {}
  19. self.num_colors = 0
  20. def getcolor(self, v):
  21. if v not in self.seen:
  22. self.seen[v] = self.num_colors
  23. self.num_colors += 1
  24. return self.seen[v]
  25. def fake_regallocs():
  26. return {'int': FakeRegAlloc(),
  27. 'ref': FakeRegAlloc(),
  28. 'float': FakeRegAlloc()}
  29. class FakeDescr(AbstractDescr):
  30. _for_tests_only = True
  31. def __init__(self, oopspecindex=None):
  32. self.oopspecindex = oopspecindex
  33. def __repr__(self):
  34. return '<Descr>'
  35. def as_vtable_size_descr(self):
  36. return self
  37. class FakeDict(object):
  38. def __getitem__(self, key):
  39. F = lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed)
  40. f = lltype.functionptr(F, key[0])
  41. c_func = Constant(f, lltype.typeOf(f))
  42. return c_func, lltype.Signed
  43. class FakeCPU:
  44. def __init__(self, rtyper):
  45. rtyper._builtin_func_for_spec_cache = FakeDict()
  46. self.rtyper = rtyper
  47. def calldescrof(self, FUNC, ARGS, RESULT, effectinfo):
  48. return FakeDescr()
  49. def fielddescrof(self, STRUCT, name):
  50. return FakeDescr()
  51. def sizeof(self, STRUCT):
  52. return FakeDescr()
  53. def arraydescrof(self, ARRAY):
  54. return FakeDescr()
  55. class FakeCallInfoCollection:
  56. def add(self, *args):
  57. pass
  58. class FakeCallControl:
  59. _descr_cannot_raise = FakeDescr()
  60. callinfocollection = FakeCallInfoCollection()
  61. def guess_call_kind(self, op):
  62. return 'residual'
  63. def getcalldescr(self, op, oopspecindex=None, extraeffect=None):
  64. try:
  65. name = op.args[0].value._obj._name
  66. if 'cannot_raise' in name or name.startswith('cast_'):
  67. return self._descr_cannot_raise
  68. except AttributeError:
  69. pass
  70. return FakeDescr(oopspecindex)
  71. def calldescr_canraise(self, calldescr):
  72. return calldescr is not self._descr_cannot_raise and calldescr.oopspecindex is None
  73. def get_vinfo(self, VTYPEPTR):
  74. return None
  75. class FakeCallControlWithVRefInfo:
  76. class virtualref_info:
  77. JIT_VIRTUAL_REF = lltype.GcStruct('VREF', ('parent', rclass.OBJECT))
  78. jit_virtual_ref_vtable = lltype.malloc(rclass.OBJECT_VTABLE,
  79. immortal=True)
  80. def guess_call_kind(self, op):
  81. if op.args[0].value._obj._name == 'jit_force_virtual':
  82. return 'residual'
  83. return 'builtin'
  84. def getcalldescr(self, op):
  85. return FakeDescr()
  86. def calldescr_canraise(self, calldescr):
  87. return False
  88. # ____________________________________________________________
  89. def test_reorder_renaming_list():
  90. result = reorder_renaming_list([], [])
  91. assert result == []
  92. result = reorder_renaming_list([1, 2, 3], [4, 5, 6])
  93. assert result == [(1, 4), (2, 5), (3, 6)]
  94. result = reorder_renaming_list([4, 5, 1, 2], [1, 2, 3, 4])
  95. assert result == [(1, 3), (4, 1), (2, 4), (5, 2)]
  96. result = reorder_renaming_list([1, 2], [2, 1])
  97. assert result == [(1, None), (2, 1), (None, 2)]
  98. result = reorder_renaming_list([4, 3, 6, 1, 2, 5, 7],
  99. [1, 2, 5, 3, 4, 6, 8])
  100. assert result == [(7, 8),
  101. (4, None), (2, 4), (3, 2), (1, 3), (None, 1),
  102. (6, None), (5, 6), (None, 5)]
  103. def test_repr():
  104. assert repr(Register('int', 13)) == '%i13'
  105. # ____________________________________________________________
  106. class TestFlatten:
  107. def make_graphs(self, func, values, type_system='lltype'):
  108. self.rtyper = support.annotate(func, values, type_system=type_system)
  109. return self.rtyper.annotator.translator.graphs
  110. def encoding_test(self, func, args, expected,
  111. transform=False, liveness=False, cc=None, jd=None):
  112. graphs = self.make_graphs(func, args)
  113. #graphs[0].show()
  114. if transform:
  115. from pypy.jit.codewriter.jtransform import transform_graph
  116. cc = cc or FakeCallControl()
  117. transform_graph(graphs[0], FakeCPU(self.rtyper), cc, jd)
  118. ssarepr = flatten_graph(graphs[0], fake_regallocs(),
  119. _include_all_exc_links=not transform)
  120. if liveness:
  121. from pypy.jit.codewriter.liveness import compute_liveness
  122. compute_liveness(ssarepr)
  123. assert_format(ssarepr, expected)
  124. def test_simple(self):
  125. def f(n):
  126. return n + 10
  127. self.encoding_test(f, [5], """
  128. int_add %i0, $10 -> %i1
  129. int_return %i1
  130. """)
  131. def test_if(self):
  132. def f(n):
  133. if n > 0:
  134. n -= 3
  135. return n + 1
  136. self.encoding_test(f, [10], """
  137. int_gt %i0, $0 -> %i1
  138. goto_if_not %i1, L1
  139. -live- L1
  140. int_copy %i0 -> %i2
  141. int_sub %i2, $3 -> %i3
  142. int_copy %i3 -> %i4
  143. L2:
  144. int_add %i4, $1 -> %i5
  145. int_return %i5
  146. ---
  147. L1:
  148. int_copy %i0 -> %i4
  149. goto L2
  150. """)
  151. def test_loop(self):
  152. def f(a, b):
  153. while a > 0:
  154. b += a
  155. a -= 1
  156. return b
  157. self.encoding_test(f, [5, 6], """
  158. int_copy %i0 -> %i2
  159. int_copy %i1 -> %i3
  160. L1:
  161. int_gt %i2, $0 -> %i4
  162. goto_if_not %i4, L2
  163. -live- L2
  164. int_copy %i2 -> %i5
  165. int_copy %i3 -> %i6
  166. int_add %i6, %i5 -> %i7
  167. int_sub %i5, $1 -> %i8
  168. int_copy %i8 -> %i2
  169. int_copy %i7 -> %i3
  170. goto L1
  171. ---
  172. L2:
  173. int_return %i3
  174. """)
  175. def test_loop_opt(self):
  176. def f(a, b):
  177. while a > 0:
  178. b += a
  179. a -= 1
  180. return b
  181. self.encoding_test(f, [5, 6], """
  182. int_copy %i0 -> %i2
  183. int_copy %i1 -> %i3
  184. L1:
  185. goto_if_not_int_gt %i2, $0, L2
  186. -live- L2
  187. int_copy %i2 -> %i4
  188. int_copy %i3 -> %i5
  189. int_add %i5, %i4 -> %i6
  190. int_sub %i4, $1 -> %i7
  191. int_copy %i7 -> %i2
  192. int_copy %i6 -> %i3
  193. goto L1
  194. ---
  195. L2:
  196. int_return %i3
  197. """, transform=True)
  198. def test_float(self):
  199. def f(i, f):
  200. return (i*5) + (f*0.25)
  201. self.encoding_test(f, [4, 7.5], """
  202. int_mul %i0, $5 -> %i1
  203. float_mul %f0, $0.25 -> %f1
  204. cast_int_to_float %i1 -> %f2
  205. float_add %f2, %f1 -> %f3
  206. float_return %f3
  207. """)
  208. def test_arg_sublist_1(self):
  209. v1 = varoftype(lltype.Signed)
  210. v2 = varoftype(lltype.Char)
  211. v3 = varoftype(rclass.OBJECTPTR)
  212. v4 = varoftype(lltype.Ptr(rstr.STR))
  213. v5 = varoftype(lltype.Float)
  214. op = SpaceOperation('residual_call_ir_f',
  215. [Constant(12345, lltype.Signed), # function ptr
  216. ListOfKind('int', [v1, v2]), # int args
  217. ListOfKind('ref', [v3, v4])], # ref args
  218. v5) # result
  219. flattener = GraphFlattener(None, fake_regallocs())
  220. flattener.serialize_op(op)
  221. assert_format(flattener.ssarepr, """
  222. residual_call_ir_f $12345, I[%i0, %i1], R[%r0, %r1] -> %f0
  223. """)
  224. def test_same_as_removal(self):
  225. def f(a):
  226. b = chr(a)
  227. return ord(b) + a
  228. self.encoding_test(f, [65], """
  229. int_add %i0, %i0 -> %i1
  230. int_return %i1
  231. """, transform=True)
  232. def test_descr(self):
  233. class FooDescr(AbstractDescr):
  234. def __repr__(self):
  235. return 'hi_there!'
  236. op = SpaceOperation('foobar', [FooDescr()], None)
  237. flattener = GraphFlattener(None, fake_regallocs())
  238. flattener.serialize_op(op)
  239. assert_format(flattener.ssarepr, """
  240. foobar hi_there!
  241. """)
  242. def test_switch(self):
  243. def f(n):
  244. if n == -5: return 12
  245. elif n == 2: return 51
  246. elif n == 7: return 1212
  247. else: return 42
  248. self.encoding_test(f, [65], """
  249. -live-
  250. int_guard_value %i0
  251. goto_if_not_int_eq %i0, $-5, L1
  252. int_return $12
  253. ---
  254. L1:
  255. goto_if_not_int_eq %i0, $2, L2
  256. int_return $51
  257. ---
  258. L2:
  259. goto_if_not_int_eq %i0, $7, L3
  260. int_return $1212
  261. ---
  262. L3:
  263. int_return $42
  264. """)
  265. def test_switch_dict(self):
  266. def f(x):
  267. if x == 1: return 61
  268. elif x == 2: return 511
  269. elif x == 3: return -22
  270. elif x == 4: return 81
  271. elif x == 5: return 17
  272. elif x == 6: return 54
  273. return -1
  274. self.encoding_test(f, [65], """
  275. -live-
  276. switch %i0, <SwitchDictDescr 1:L1, 2:L2, 3:L3, 4:L4, 5:L5, 6:L6>
  277. int_return $-1
  278. ---
  279. L1:
  280. int_return $61
  281. ---
  282. L2:
  283. int_return $511
  284. ---
  285. L3:
  286. int_return $-22
  287. ---
  288. L4:
  289. int_return $81
  290. ---
  291. L5:
  292. int_return $17
  293. ---
  294. L6:
  295. int_return $54
  296. """)
  297. def test_exc_exitswitch(self):
  298. def g(i):
  299. pass
  300. def f(i):
  301. try:
  302. g(i)
  303. except ValueError:
  304. return 1
  305. except KeyError:
  306. return 2
  307. else:
  308. return 3
  309. self.encoding_test(f, [65], """
  310. direct_call $<* fn g>, %i0
  311. catch_exception L1
  312. int_return $3
  313. ---
  314. L1:
  315. goto_if_exception_mismatch $<* struct object_vtable>, L2
  316. int_return $1
  317. ---
  318. L2:
  319. goto_if_exception_mismatch $<* struct object_vtable>, L3
  320. int_return $2
  321. ---
  322. L3:
  323. reraise
  324. """)
  325. def test_exc_exitswitch_2(self):
  326. class FooError(Exception):
  327. pass
  328. @dont_look_inside
  329. def g(i):
  330. FooError().num = 1
  331. FooError().num = 2
  332. def f(i):
  333. try:
  334. g(i)
  335. except FooError, e:
  336. return e.num
  337. except Exception:
  338. return 3
  339. else:
  340. return 4
  341. self.encoding_test(f, [65], """
  342. residual_call_ir_v $<* fn g>, <Descr>, I[%i0], R[]
  343. -live-
  344. catch_exception L1
  345. int_return $4
  346. ---
  347. L1:
  348. goto_if_exception_mismatch $<* struct object_vtable>, L2
  349. last_exc_value -> %r0
  350. getfield_gc_i %r0, <Descr> -> %i1
  351. int_return %i1
  352. ---
  353. L2:
  354. int_return $3
  355. """, transform=True)
  356. def test_exc_raise_1(self):
  357. class FooError(Exception):
  358. pass
  359. fooerror = FooError()
  360. def f(i):
  361. raise fooerror
  362. self.encoding_test(f, [65], """
  363. raise $<* struct object>
  364. """)
  365. def test_exc_raise_2(self):
  366. def g(i):
  367. pass
  368. def f(i):
  369. try:
  370. g(i)
  371. except Exception:
  372. raise KeyError
  373. self.encoding_test(f, [65], """
  374. direct_call $<* fn g>, %i0
  375. catch_exception L1
  376. void_return
  377. ---
  378. L1:
  379. raise $<* struct object>
  380. """)
  381. def test_exc_finally(self):
  382. def get_exception(n):
  383. if n > 5:
  384. raise ValueError
  385. class Foo:
  386. pass
  387. Foo.__module__ = "test"
  388. foo = Foo()
  389. def f(i):
  390. try:
  391. get_exception(i)
  392. finally:
  393. foo.sideeffect = 5
  394. self.encoding_test(f, [65], """
  395. residual_call_ir_v $<* fn get_exception>, <Descr>, I[%i0], R[]
  396. -live-
  397. catch_exception L1
  398. setfield_gc_i $<* struct test.Foo>, <Descr>, $5
  399. void_return
  400. ---
  401. L1:
  402. last_exception -> %i1
  403. last_exc_value -> %r0
  404. setfield_gc_i $<* struct test.Foo>, <Descr>, $5
  405. -live-
  406. raise %r0
  407. """, transform=True)
  408. def test_goto_if_not_int_is_true(self):
  409. def f(i):
  410. return not i
  411. # note that 'goto_if_not_int_is_true' is not the same thing
  412. # as just 'goto_if_not', because the last one expects a boolean
  413. self.encoding_test(f, [7], """
  414. goto_if_not_int_is_true %i0, L1
  415. -live- L1
  416. int_return $False
  417. ---
  418. L1:
  419. int_return $True
  420. """, transform=True)
  421. def test_int_floordiv_ovf_zer(self):
  422. def f(i, j):
  423. assert i >= 0
  424. assert j >= 0
  425. try:
  426. return ovfcheck(i // j)
  427. except OverflowError:
  428. return 42
  429. except ZeroDivisionError:
  430. return -42
  431. self.encoding_test(f, [7, 2], """
  432. residual_call_ir_i $<* fn int_floordiv_ovf_zer>, <Descr>, I[%i0, %i1], R[] -> %i2
  433. -live-
  434. catch_exception L1
  435. int_return %i2
  436. ---
  437. L1:
  438. goto_if_exception_mismatch $<* struct object_vtable>, L2
  439. int_return $42
  440. ---
  441. L2:
  442. goto_if_exception_mismatch $<* struct object_vtable>, L3
  443. int_return $-42
  444. ---
  445. L3:
  446. reraise
  447. """, transform=True)
  448. def test_int_mod_ovf(self):
  449. def f(i, j):
  450. assert i >= 0
  451. assert j >= 0
  452. try:
  453. return ovfcheck(i % j)
  454. except OverflowError:
  455. return 42
  456. # XXX so far, this really produces a int_mod_ovf_zer...
  457. self.encoding_test(f, [7, 2], """
  458. residual_call_ir_i $<* fn int_mod_ovf_zer>, <Descr>, I[%i0, %i1], R[] -> %i2
  459. -live-
  460. catch_exception L1
  461. int_return %i2
  462. ---
  463. L1:
  464. goto_if_exception_mismatch $<* struct object_vtable>, L2
  465. int_return $42
  466. ---
  467. L2:
  468. reraise
  469. """, transform=True)
  470. def test_simple_branch(self):
  471. def f(n, m1, m2):
  472. if n:
  473. return m1
  474. else:
  475. return m2
  476. self.encoding_test(f, [4, 5, 6], """
  477. goto_if_not_int_is_true %i0, L1
  478. -live- %i1, %i2, L1
  479. int_return %i1
  480. ---
  481. L1:
  482. int_return %i2
  483. """, transform=True, liveness=True)
  484. def test_int_add_ovf(self):
  485. def f(i, j):
  486. try:
  487. return ovfcheck(i + j)
  488. except OverflowError:
  489. return 42
  490. self.encoding_test(f, [7, 2], """
  491. int_add_ovf %i0, %i1 -> %i2
  492. -live- %i2
  493. catch_exception L1
  494. int_return %i2
  495. ---
  496. L1:
  497. int_return $42
  498. """, transform=True, liveness=True)
  499. def test_residual_call_raising(self):
  500. @dont_look_inside
  501. def g(i, j):
  502. return ovfcheck(i + j)
  503. def f(i, j):
  504. try:
  505. return g(i, j)
  506. except Exception:
  507. return 42 + j
  508. self.encoding_test(f, [7, 2], """
  509. residual_call_ir_i $<* fn g>, <Descr>, I[%i0, %i1], R[] -> %i2
  510. -live- %i1, %i2
  511. catch_exception L1
  512. int_return %i2
  513. ---
  514. L1:
  515. int_copy %i1 -> %i3
  516. int_add %i3, $42 -> %i4
  517. int_return %i4
  518. """, transform=True, liveness=True)
  519. def test_residual_call_nonraising(self):
  520. @dont_look_inside
  521. def cannot_raise(i, j):
  522. return i + j
  523. def f(i, j):
  524. try:
  525. return cannot_raise(i, j)
  526. except Exception:
  527. return 42 + j
  528. self.encoding_test(f, [7, 2], """
  529. residual_call_ir_i $<* fn cannot_raise>, <Descr>, I[%i0, %i1], R[] -> %i2
  530. int_return %i2
  531. """, transform=True, liveness=True)
  532. def test_we_are_jitted(self):
  533. def f(x):
  534. if _we_are_jitted:
  535. return 2
  536. else:
  537. return 3 + x
  538. self.encoding_test(f, [5], """
  539. int_return $2
  540. """, transform=True)
  541. def test_jitdriver(self):
  542. myjitdriver = JitDriver(greens = ['x'], reds = ['y'])
  543. def f(x, y):
  544. myjitdriver.jit_merge_point(x=x, y=y)
  545. myjitdriver.can_enter_jit(x=y, y=x)
  546. class FakeJitDriverSD:
  547. jitdriver = myjitdriver
  548. index = 27
  549. jd = FakeJitDriverSD()
  550. class MyFakeCallControl(FakeCallControl):
  551. def jitdriver_sd_from_jitdriver(self, jitdriver):
  552. assert jitdriver == myjitdriver
  553. return jd
  554. self.encoding_test(f, [4, 5], """
  555. -live- %i0, %i1
  556. int_guard_value %i0
  557. -live- %i0, %i1
  558. jit_merge_point $27, I[%i0], R[], F[], I[%i1], R[], F[]
  559. -live-
  560. loop_header $27
  561. void_return
  562. """, transform=True, liveness=True, cc=MyFakeCallControl(), jd=jd)
  563. def test_keepalive(self):
  564. S = lltype.GcStruct('S')
  565. def g():
  566. return lltype.malloc(S)
  567. def f(x):
  568. p = g()
  569. q = g()
  570. keepalive_until_here(p)
  571. keepalive_until_here(q)
  572. return x
  573. self.encoding_test(f, [5], """
  574. residual_call_r_r $<* fn g>, <Descr>, R[] -> %r0
  575. -live-
  576. residual_call_r_r $<* fn g>, <Descr>, R[] -> %r1
  577. -live-
  578. -live- %r0
  579. -live- %r1
  580. int_return %i0
  581. """, transform=True)
  582. self.encoding_test(f, [5], """
  583. residual_call_r_r $<* fn g>, <Descr>, R[] -> %r0
  584. -live- %i0, %r0
  585. residual_call_r_r $<* fn g>, <Descr>, R[] -> %r1
  586. -live- %i0, %r0, %r1
  587. -live- %i0, %r0, %r1
  588. -live- %i0, %r1
  589. int_return %i0
  590. """, transform=True, liveness=True)
  591. def test_ptr_nonzero(self):
  592. def f(p):
  593. if p:
  594. return 12
  595. return 34
  596. S = lltype.GcStruct('S')
  597. self.encoding_test(f, [lltype.malloc(S)], """
  598. -live- %r0
  599. goto_if_not_ptr_nonzero %r0, L1
  600. int_return $12
  601. ---
  602. L1:
  603. int_return $34
  604. """, transform=True, liveness=True)
  605. def test_vref_simple(self):
  606. class X:
  607. pass
  608. def f():
  609. return jit.virtual_ref(X())
  610. self.encoding_test(f, [], """
  611. new_with_vtable <Descr> -> %r0
  612. virtual_ref %r0 -> %r1
  613. ref_return %r1
  614. """, transform=True, cc=FakeCallControlWithVRefInfo())
  615. def test_vref_forced(self):
  616. class X:
  617. pass
  618. def f():
  619. vref = jit.virtual_ref(X())
  620. return vref()
  621. # The call vref() is a jit_force_virtual operation in the original
  622. # graph. It becomes in the JitCode a residual call to a helper that
  623. # contains itself a jit_force_virtual.
  624. self.encoding_test(f, [], """
  625. new_with_vtable <Descr> -> %r0
  626. virtual_ref %r0 -> %r1
  627. residual_call_r_r $<* fn jit_force_virtual>, <Descr>, R[%r1] -> %r2
  628. ref_return %r2
  629. """, transform=True, cc=FakeCallControlWithVRefInfo())
  630. def test_array_operations(self):
  631. A = lltype.GcArray(lltype.Signed)
  632. def f():
  633. array = lltype.malloc(A, 5)
  634. array[2] = 5
  635. return array[2] + len(array)
  636. self.encoding_test(f, [], """
  637. new_array <Descr>, $5 -> %r0
  638. setarrayitem_gc_i %r0, <Descr>, $2, $5
  639. getarrayitem_gc_i %r0, <Descr>, $2 -> %i0
  640. arraylen_gc %r0, <Descr> -> %i1
  641. int_add %i0, %i1 -> %i2
  642. int_return %i2
  643. """, transform=True)
  644. def test_void_array_operations(self):
  645. A = lltype.GcArray(lltype.Void)
  646. def f():
  647. array = lltype.malloc(A, 5)
  648. array[2] = None
  649. x = array[2]
  650. return len(array)
  651. self.encoding_test(f, [], """
  652. new_array <Descr>, $5 -> %r0
  653. arraylen_gc %r0, <Descr> -> %i0
  654. int_return %i0
  655. """, transform=True)
  656. def test_string_operations(self):
  657. from pypy.rpython.lltypesystem import rstr
  658. def f(n):
  659. s = lltype.malloc(rstr.STR, 2)
  660. s.chars[1] = chr(n)
  661. return ord(s.chars[1]) + len(s.chars)
  662. self.encoding_test(f, [512], """
  663. newstr $2 -> %r0
  664. strsetitem %r0, $1, %i0
  665. strgetitem %r0, $1 -> %i1
  666. strlen %r0 -> %i2
  667. int_add %i1, %i2 -> %i3
  668. int_return %i3
  669. """, transform=True)
  670. def test_uint_operations(self):
  671. def f(n):
  672. return ((r_uint(n) - 123) >> 1) <= r_uint(456)
  673. self.encoding_test(f, [200], """
  674. int_sub %i0, $123L -> %i1
  675. uint_rshift %i1, $1 -> %i2
  676. uint_le %i2, $456L -> %i3
  677. int_return %i3
  678. """, transform=True)
  679. def test_int_between(self):
  680. from pypy.rpython.lltypesystem.lloperation import llop
  681. def f(n, m, p):
  682. return llop.int_between(lltype.Bool, n, m, p)
  683. self.encoding_test(f, [5, 6, 7], """
  684. int_between %i0, %i1, %i2 -> %i3
  685. int_return %i3
  686. """, transform=True)
  687. def test_force_cast(self):
  688. # NB: we don't need to test for INT here, the logic in jtransform is
  689. # general enough so that if we have the below cases it should
  690. # generalize also to INT
  691. for FROM, TO, expected in [
  692. (rffi.SIGNEDCHAR, rffi.SIGNEDCHAR, ""),
  693. (rffi.SIGNEDCHAR, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
  694. (rffi.SIGNEDCHAR, rffi.SHORT, ""),
  695. (rffi.SIGNEDCHAR, rffi.USHORT, "int_and %i0, $65535 -> %i1"),
  696. (rffi.SIGNEDCHAR, rffi.LONG, ""),
  697. (rffi.SIGNEDCHAR, rffi.ULONG, ""),
  698. (rffi.UCHAR, rffi.SIGNEDCHAR, """int_sub %i0, $-128 -> %i1
  699. int_and %i1, $255 -> %i2
  700. int_add %i2, $-128 -> %i3"""),
  701. (rffi.UCHAR, rffi.UCHAR, ""),
  702. (rffi.UCHAR, rffi.SHORT, ""),
  703. (rffi.UCHAR, rffi.USHORT, ""),
  704. (rffi.UCHAR, rffi.LONG, ""),
  705. (rffi.UCHAR, rffi.ULONG, ""),
  706. (rffi.SHORT, rffi.SIGNEDCHAR, """int_sub %i0, $-128 -> %i1
  707. int_and %i1, $255 -> %i2
  708. int_add %i2, $-128 -> %i3"""),
  709. (rffi.SHORT, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
  710. (rffi.SHORT, rffi.SHORT, ""),
  711. (rffi.SHORT, rffi.USHORT, "int_and %i0, $65535 -> %i1"),
  712. (rffi.SHORT, rffi.LONG, ""),
  713. (rffi.SHORT, rffi.ULONG, ""),
  714. (rffi.USHORT, rffi.SIGNEDCHAR, """int_sub %i0, $-128 -> %i1
  715. int_and %i1, $255 -> %i2
  716. int_add %i2, $-128 -> %i3"""),
  717. (rffi.USHORT, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
  718. (rffi.USHORT, rffi.SHORT, """int_sub %i0, $-32768 -> %i1
  719. int_and %i1, $65535 -> %i2
  720. int_add %i2, $-32768 -> %i3"""),
  721. (rffi.USHORT, rffi.USHORT, ""),
  722. (rffi.USHORT, rffi.LONG, ""),
  723. (rffi.USHORT, rffi.ULONG, ""),
  724. (rffi.LONG, rffi.SIGNEDCHAR, """int_sub %i0, $-128 -> %i1
  725. int_and %i1, $255 -> %i2
  726. int_add %i2, $-128 -> %i3"""),
  727. (rffi.LONG, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
  728. (rffi.LONG, rffi.SHORT, """int_sub %i0, $-32768 -> %i1
  729. int_and %i1, $65535 -> %i2
  730. int_add %i2, $-32768 -> %i3"""),
  731. (rffi.LONG, rffi.USHORT, "int_and %i0, $65535 -> %i1"),
  732. (rffi.LONG, rffi.LONG, ""),
  733. (rffi.LONG, rffi.ULONG, ""),
  734. (rffi.ULONG, rffi.SIGNEDCHAR, """int_sub %i0, $-128 -> %i1
  735. int_and %i1, $255 -> %i2
  736. int_add %i2, $-128 -> %i3"""),
  737. (rffi.ULONG, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
  738. (rffi.ULONG, rffi.SHORT, """int_sub %i0, $-32768 -> %i1
  739. int_and %i1, $65535 -> %i2
  740. int_add %i2, $-32768 -> %i3"""),
  741. (rffi.ULONG, rffi.USHORT, "int_and %i0, $65535 -> %i1"),
  742. (rffi.ULONG, rffi.LONG, ""),
  743. (rffi.ULONG, rffi.ULONG, ""),
  744. ]:
  745. expected = [s.strip() for s in expected.splitlines()]
  746. check_force_cast(FROM, TO, expected, 42)
  747. check_force_cast(FROM, TO, expected, -42)
  748. returnvar = "%i" + str(len(expected))
  749. expected.append('int_return ' + returnvar)
  750. expectedstr = '\n'.join(expected)
  751. #
  752. def f(n):
  753. return rffi.cast(TO, n)
  754. self.encoding_test(f, [rffi.cast(FROM, 42)], expectedstr,
  755. transform=True)
  756. if not longlong.is_64_bit:
  757. if FROM in (rffi.LONG, rffi.ULONG):
  758. if FROM == rffi.LONG:
  759. FROM = rffi.LONGLONG
  760. else:
  761. FROM = rffi.ULONGLONG
  762. expected.insert(0,
  763. "residual_call_irf_i $<* fn llong_to_int>, <Descr>, I[], R[], F[%f0] -> %i0")
  764. expectedstr = '\n'.join(expected)
  765. self.encoding_test(f, [rffi.cast(FROM, 42)], expectedstr,
  766. transform=True)
  767. elif TO in (rffi.LONG, rffi.ULONG):
  768. if rffi.cast(FROM, -1) < 0:
  769. fnname = "llong_from_int"
  770. else:
  771. fnname = "llong_from_uint"
  772. if TO == rffi.LONG:
  773. TO = rffi.LONGLONG
  774. else:
  775. TO = rffi.ULONGLONG
  776. fnname = "u" + fnname
  777. expected.pop() # remove int_return
  778. expected.append(
  779. "residual_call_irf_f $<* fn %s>, <Descr>, I[%s], R[], F[] -> %%f0"
  780. % (fnname, returnvar))
  781. expected.append("float_return %f0")
  782. expectedstr = '\n'.join(expected)
  783. self.encoding_test(f, [rffi.cast(FROM, 42)], expectedstr,
  784. transform=True)
  785. def test_force_cast_pointer(self):
  786. def h(p):
  787. return rffi.cast(rffi.VOIDP, p)
  788. self.encoding_test(h, [lltype.nullptr(rffi.CCHARP.TO)], """
  789. int_return %i0
  790. """, transform=True)
  791. def test_force_cast_floats(self):
  792. # Caststs to lltype.Float
  793. def f(n):
  794. return rffi.cast(lltype.Float, n)
  795. self.encoding_test(f, [12.456], """
  796. float_return %f0
  797. """, transform=True)
  798. self.encoding_test(f, [rffi.cast(rffi.SIGNEDCHAR, 42)], """
  799. cast_int_to_float %i0 -> %f0
  800. float_return %f0
  801. """, transform=True)
  802. # Casts to lltype.SingleFloat
  803. def g(n):
  804. return rffi.cast(lltype.SingleFloat, n)
  805. self.encoding_test(g, [12.456], """
  806. cast_float_to_singlefloat %f0 -> %i0
  807. int_return %i0
  808. """, transform=True)
  809. self.encoding_test(g, [rffi.cast(rffi.SIGNEDCHAR, 42)], """
  810. cast_int_to_float %i0 -> %f0
  811. cast_float_to_singlefloat %f0 -> %i1
  812. int_return %i1
  813. """, transform=True)
  814. # Casts from floats
  815. def f(n):
  816. return rffi.cast(rffi.SIGNEDCHAR, n)
  817. self.encoding_test(f, [12.456], """
  818. cast_float_to_int %f0 -> %i0
  819. int_sub %i0, $-128 -> %i1
  820. int_and %i1, $255 -> %i2
  821. int_add %i2, $-128 -> %i3
  822. int_return %i3
  823. """, transform=True)
  824. self.encoding_test(f, [rffi.cast(lltype.SingleFloat, 12.456)], """
  825. cast_singlefloat_to_float %i0 -> %f0
  826. cast_float_to_int %f0 -> %i1
  827. int_sub %i1, $-128 -> %i2
  828. int_and %i2, $255 -> %i3
  829. int_add %i3, $-128 -> %i4
  830. int_return %i4
  831. """, transform=True)
  832. def f(dbl):
  833. return rffi.cast(rffi.UCHAR, dbl)
  834. self.encoding_test(f, [12.456], """
  835. cast_float_to_int %f0 -> %i0
  836. int_and %i0, $255 -> %i1
  837. int_return %i1
  838. """, transform=True)
  839. def f(dbl):
  840. return rffi.cast(lltype.Unsigned, dbl)
  841. self.encoding_test(f, [12.456], """
  842. residual_call_irf_i $<* fn cast_float_to_uint>, <Descr>, I[], R[], F[%f0] -> %i0
  843. int_return %i0
  844. """, transform=True)
  845. def f(i):
  846. return rffi.cast(lltype.Float, chr(i)) # "char -> float"
  847. self.encoding_test(f, [12], """
  848. cast_int_to_float %i0 -> %f0
  849. float_return %f0
  850. """, transform=True)
  851. def f(i):
  852. return rffi.cast(lltype.Float, r_uint(i)) # "uint -> float"
  853. self.encoding_test(f, [12], """
  854. residual_call_irf_f $<* fn cast_uint_to_float>, <Descr>, I[%i0], R[], F[] -> %f0
  855. float_return %f0
  856. """, transform=True)
  857. if not longlong.is_64_bit:
  858. def f(dbl):
  859. return rffi.cast(lltype.SignedLongLong, dbl)
  860. self.encoding_test(f, [12.3], """
  861. residual_call_irf_f $<* fn llong_from_float>, <Descr>, I[], R[], F[%f0] -> %f1
  862. float_return %f1
  863. """, transform=True)
  864. def f(dbl):
  865. return rffi.cast(lltype.UnsignedLongLong, dbl)
  866. self.encoding_test(f, [12.3], """
  867. residual_call_irf_f $<* fn ullong_from_float>, <Descr>, I[], R[], F[%f0] -> %f1
  868. float_return %f1
  869. """, transform=True)
  870. def f(x):
  871. ll = r_longlong(x)
  872. return rffi.cast(lltype.Float, ll)
  873. self.encoding_test(f, [12], """
  874. residual_call_irf_f $<* fn llong_from_int>, <Descr>, I[%i0], R[], F[] -> %f0
  875. residual_call_irf_f $<* fn llong_to_float>, <Descr>, I[], R[], F[%f0] -> %f1
  876. float_return %f1
  877. """, transform=True)
  878. def f(x):
  879. ll = r_ulonglong(x)
  880. return rffi.cast(lltype.Float, ll)
  881. self.encoding_test(f, [12], """
  882. residual_call_irf_f $<* fn ullong_from_int>, <Descr>, I[%i0], R[], F[] -> %f0
  883. residual_call_irf_f $<* fn ullong_u_to_float>, <Descr>, I[], R[], F[%f0] -> %f1
  884. float_return %f1
  885. """, transform=True)
  886. def test_direct_ptradd(self):
  887. def f(p, n):
  888. return lltype.direct_ptradd(p, n)
  889. self.encoding_test(f, [lltype.nullptr(rffi.CCHARP.TO), 123], """
  890. int_add %i0, %i1 -> %i2
  891. int_return %i2
  892. """, transform=True)
  893. def check_force_cast(FROM, TO, operations, value):
  894. """Check that the test is correctly written..."""
  895. import re
  896. r = re.compile('(\w+) \%i\d, \$(-?\d+)')
  897. #
  898. value = rffi.cast(FROM, value)
  899. value = rffi.cast(lltype.Signed, value)
  900. #
  901. expected_value = rffi.cast(TO, value)
  902. expected_value = rffi.cast(lltype.Signed, expected_value)
  903. #
  904. for op in operations:
  905. match = r.match(op)
  906. assert match, "line %r does not match regexp" % (op,)
  907. opname = match.group(1)
  908. if opname == 'int_add': value += int(match.group(2))
  909. elif opname == 'int_sub': value -= int(match.group(2))
  910. elif opname == 'int_and': value &= int(match.group(2))
  911. else: assert 0, opname
  912. #
  913. assert rffi.cast(lltype.Signed, value) == expected_value