PageRenderTime 63ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/jit/metainterp/resoperation.py

https://bitbucket.org/pypy/pypy/
Python | 1801 lines | 1757 code | 35 blank | 9 comment | 42 complexity | 2a81aee1c57c25e7013fa981d317d241 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import weakref, os
  2. from rpython.rlib.objectmodel import we_are_translated, specialize
  3. from rpython.rtyper.lltypesystem.lloperation import llop
  4. from rpython.rlib.objectmodel import compute_identity_hash
  5. from rpython.rtyper.lltypesystem import lltype, llmemory
  6. from rpython.jit.codewriter import longlong
  7. from rpython.jit.backend.llsupport.symbolic import (WORD as INT_WORD,
  8. SIZEOF_FLOAT as FLOAT_WORD)
  9. class SettingForwardedOnAbstractValue(Exception):
  10. pass
  11. class CountingDict(object):
  12. def __init__(self):
  13. self._d = weakref.WeakKeyDictionary()
  14. self.counter = 0
  15. def __getitem__(self, item):
  16. try:
  17. return self._d[item]
  18. except KeyError:
  19. c = self.counter
  20. self.counter += 1
  21. self._d[item] = c
  22. return c
  23. class AbstractValue(object):
  24. _repr_memo = CountingDict()
  25. is_info_class = False
  26. namespace = None
  27. _attrs_ = ()
  28. def _get_hash_(self):
  29. return compute_identity_hash(self)
  30. def same_box(self, other):
  31. return self is other
  32. def same_shape(self, other):
  33. return True
  34. def repr_short(self, memo):
  35. return self.repr(memo)
  36. def is_constant(self):
  37. return False
  38. def get_forwarded(self):
  39. return None
  40. def set_forwarded(self, forwarded_to):
  41. llop.debug_print(lltype.Void, "setting forwarded on:", self.__class__.__name__)
  42. raise SettingForwardedOnAbstractValue()
  43. @specialize.arg(1)
  44. def get_box_replacement(op, not_const=False):
  45. # Read the chain "op, op._forwarded, op._forwarded._forwarded..."
  46. # until we reach None or an Info instance, and return the last
  47. # item before that.
  48. while isinstance(op, AbstractResOpOrInputArg): # else, _forwarded is None
  49. next_op = op._forwarded
  50. if (next_op is None or next_op.is_info_class or
  51. (not_const and next_op.is_constant())):
  52. return op
  53. op = next_op
  54. return op
  55. def reset_value(self):
  56. pass
  57. def is_inputarg(self):
  58. return False
  59. def returns_vector(self):
  60. return False
  61. def is_vector(self):
  62. return False
  63. def returns_void(self):
  64. return False
  65. def ResOperation(opnum, args, descr=None):
  66. cls = opclasses[opnum]
  67. op = cls()
  68. op.initarglist(args)
  69. if descr is not None:
  70. assert isinstance(op, ResOpWithDescr)
  71. if opnum == rop.FINISH:
  72. assert descr.final_descr
  73. elif OpHelpers.is_guard(opnum):
  74. assert not descr.final_descr
  75. op.setdescr(descr)
  76. return op
  77. def VecOperation(opnum, args, baseop, count, descr=None):
  78. vecinfo = baseop.get_forwarded()
  79. assert isinstance(vecinfo, VectorizationInfo)
  80. datatype = vecinfo.datatype
  81. bytesize = vecinfo.bytesize
  82. signed = vecinfo.signed
  83. if baseop.is_typecast():
  84. ft,tt = baseop.cast_types()
  85. datatype = tt
  86. bytesize = baseop.cast_to_bytesize()
  87. return VecOperationNew(opnum, args, datatype, bytesize, signed, count, descr)
  88. def VecOperationNew(opnum, args, datatype, bytesize, signed, count, descr=None):
  89. op = ResOperation(opnum, args, descr=descr)
  90. vecinfo = VectorizationInfo(None)
  91. vecinfo.setinfo(datatype, bytesize, signed)
  92. vecinfo.count = count
  93. op.set_forwarded(vecinfo)
  94. if isinstance(op,VectorOp):
  95. op.datatype = datatype
  96. op.bytesize = bytesize
  97. op.signed = signed
  98. op.count = count
  99. else:
  100. assert isinstance(op, VectorGuardOp)
  101. op.datatype = datatype
  102. op.bytesize = bytesize
  103. op.signed = signed
  104. op.count = count
  105. assert op.count > 0
  106. if not we_are_translated():
  107. # for the test suite
  108. op._vec_debug_info = vecinfo
  109. return op
  110. def vector_repr(self, num):
  111. if we_are_translated():
  112. # the set_forwarded solution is volatile, we CANNOT acquire
  113. # the information (e.g. count, bytesize) here easily
  114. return 'v' + str(num)
  115. if hasattr(self, '_vec_debug_info'):
  116. vecinfo = self._vec_debug_info
  117. count = vecinfo.count
  118. datatype = vecinfo.datatype
  119. bytesize = vecinfo.bytesize
  120. elif self.vector == -2:
  121. count = self.count
  122. datatype = self.datatype
  123. bytesize = self.bytesize
  124. else:
  125. assert 0, "cannot debug print variable"
  126. if self.opnum in (rop.VEC_UNPACK_I, rop.VEC_UNPACK_F):
  127. return self.type + str(num)
  128. return 'v%d[%dx%s%d]' % (num, count, datatype,
  129. bytesize * 8)
  130. class VectorizationInfo(AbstractValue):
  131. _attrs_ = ('datatype', 'bytesize', 'signed', 'count')
  132. datatype = '\x00'
  133. bytesize = -1 # -1 means the biggest size known to the machine
  134. signed = True
  135. count = -1
  136. def __init__(self, op):
  137. if op is None:
  138. return
  139. from rpython.jit.metainterp.history import Const
  140. if isinstance(op, Const) or isinstance(op, AbstractInputArg):
  141. self.setinfo(op.type, -1, op.type == 'i')
  142. return
  143. if op.is_primitive_array_access():
  144. from rpython.jit.backend.llsupport.descr import ArrayDescr
  145. descr = op.getdescr()
  146. if not we_are_translated():
  147. from rpython.jit.backend.llgraph.runner import _getdescr
  148. descr = _getdescr(op)
  149. type = op.type
  150. bytesize = descr.get_item_size_in_bytes()
  151. signed = descr.is_item_signed()
  152. datatype = type
  153. self.setinfo(datatype, bytesize, signed)
  154. elif op.opnum == rop.INT_SIGNEXT:
  155. from rpython.jit.metainterp import history
  156. arg0 = op.getarg(0)
  157. arg1 = op.getarg(1)
  158. assert isinstance(arg1, history.ConstInt)
  159. self.setinfo('i', arg1.value, True)
  160. elif op.is_typecast():
  161. ft,tt = op.cast_types()
  162. bytesize = op.cast_to_bytesize()
  163. self.setinfo(tt, bytesize, True)
  164. else:
  165. # pass through the type of the first input argument
  166. type = op.type
  167. signed = type == 'i'
  168. bytesize = -1
  169. if op.numargs() > 0:
  170. i = 0
  171. arg = op.getarg(i)
  172. while arg.is_constant() and i+1 < op.numargs():
  173. i += 1
  174. arg = op.getarg(i)
  175. if not arg.is_constant():
  176. vecinfo = arg.get_forwarded()
  177. if vecinfo is not None and isinstance(vecinfo, VectorizationInfo):
  178. if vecinfo.datatype != '\x00' and \
  179. vecinfo.bytesize != -1:
  180. type = vecinfo.datatype
  181. signed = vecinfo.signed
  182. bytesize = vecinfo.bytesize
  183. if rop.returns_bool_result(op.opnum):
  184. type = 'i'
  185. self.setinfo(type, bytesize, signed)
  186. def setinfo(self, datatype, bytesize, signed):
  187. self.datatype = datatype
  188. if bytesize == -1:
  189. if datatype == 'i':
  190. bytesize = INT_WORD
  191. elif datatype == 'f':
  192. bytesize = FLOAT_WORD
  193. elif datatype == 'r':
  194. bytesize = INT_WORD
  195. elif datatype == 'v':
  196. bytesize = 0
  197. elif datatype == 'V': # input arg vector
  198. bytesize = INT_WORD
  199. else:
  200. assert 0, "unknown datasize"
  201. self.bytesize = bytesize
  202. self.signed = signed
  203. class AbstractResOpOrInputArg(AbstractValue):
  204. _attrs_ = ('_forwarded',)
  205. _forwarded = None # either another resop or OptInfo
  206. def get_forwarded(self):
  207. return self._forwarded
  208. def set_forwarded(self, forwarded_to):
  209. assert forwarded_to is not self
  210. self._forwarded = forwarded_to
  211. def getdescr(self):
  212. return None
  213. def forget_value(self):
  214. pass
  215. class AbstractResOp(AbstractResOpOrInputArg):
  216. """The central ResOperation class, representing one operation."""
  217. _attrs_ = ()
  218. # debug
  219. name = ""
  220. pc = 0
  221. opnum = 0
  222. _cls_has_bool_result = False
  223. type = 'v'
  224. boolreflex = -1
  225. boolinverse = -1
  226. vector = -1 # -1 means, no vector equivalent, -2 it is a vector statement
  227. cls_casts = ('\x00', -1, '\x00', -1, -1)
  228. def getopnum(self):
  229. return self.opnum
  230. #def same_box(self, other):
  231. # if self.is_same_as():
  232. # return self is other or self.getarg(0).same_box(other)
  233. # return self is other
  234. # methods implemented by the arity mixins
  235. # ---------------------------------------
  236. def initarglist(self, args):
  237. "This is supposed to be called only just after the ResOp has been created"
  238. raise NotImplementedError
  239. def getarglist(self):
  240. raise NotImplementedError
  241. def getarglist_copy(self):
  242. return self.getarglist()
  243. def getarg(self, i):
  244. raise NotImplementedError
  245. def setarg(self, i, box):
  246. raise NotImplementedError
  247. def numargs(self):
  248. raise NotImplementedError
  249. # methods implemented by GuardResOp
  250. # ---------------------------------
  251. def getfailargs(self):
  252. return None
  253. def setfailargs(self, fail_args):
  254. raise NotImplementedError
  255. # methods implemented by ResOpWithDescr
  256. # -------------------------------------
  257. #def getdescr(self): -- in the base class, AbstractResOpOrInputArg
  258. # return None
  259. def setdescr(self, descr):
  260. raise NotImplementedError
  261. def cleardescr(self):
  262. pass
  263. # common methods
  264. # --------------
  265. def copy(self):
  266. return self.copy_and_change(self.opnum)
  267. def copy_and_change(self, opnum, args=None, descr=None):
  268. "shallow copy: the returned operation is meant to be used in place of self"
  269. # XXX specialize
  270. from rpython.jit.metainterp.history import DONT_CHANGE
  271. if args is None:
  272. args = self.getarglist_copy()
  273. if descr is None:
  274. descr = self.getdescr()
  275. if descr is DONT_CHANGE:
  276. descr = None
  277. return ResOperation(opnum, args, descr)
  278. def repr(self, memo, graytext=False):
  279. # RPython-friendly version
  280. if self.type != 'v':
  281. try:
  282. num = memo[self]
  283. except KeyError:
  284. num = len(memo)
  285. memo[self] = num
  286. if self.is_vector():
  287. sres = vector_repr(self, num) + ' = '
  288. else:
  289. sres = self.type + str(num) + ' = '
  290. #if self.result is not None:
  291. # sres = '%s = ' % (self.result,)
  292. else:
  293. sres = ''
  294. if self.name:
  295. prefix = "%s:%s " % (self.name, self.pc)
  296. if graytext:
  297. prefix = "\f%s\f" % prefix
  298. else:
  299. prefix = ""
  300. args = self.getarglist()
  301. descr = self.getdescr()
  302. if descr is None or we_are_translated():
  303. s = '%s%s%s(%s)' % (prefix, sres, self.getopname(),
  304. ', '.join([a.repr_short(memo) for a in args]))
  305. else:
  306. s = '%s%s%s(%s)' % (prefix, sres, self.getopname(),
  307. ', '.join([a.repr_short(memo) for a in args] +
  308. ['descr=%r' % descr]))
  309. # --- enable to display the failargs too:
  310. #if isinstance(self, GuardResOp):
  311. # s += ' [%s]' % (', '.join([a.repr_short(memo) for a in
  312. # self.getfailargs()]),)
  313. return s
  314. def repr_short(self, memo):
  315. try:
  316. num = memo[self]
  317. except KeyError:
  318. num = len(memo)
  319. memo[self] = num
  320. if self.is_vector():
  321. return vector_repr(self, num)
  322. return self.type + str(num)
  323. def __repr__(self):
  324. r = self.repr(self._repr_memo)
  325. if self.namespace is not None:
  326. return "<" + self.namespace + ">" + r
  327. return r
  328. def getopname(self):
  329. try:
  330. return opname[self.getopnum()].lower()
  331. except KeyError:
  332. return '<%d>' % self.getopnum()
  333. def is_guard(self):
  334. return rop.is_guard(self.getopnum())
  335. def is_ovf(self):
  336. return rop.is_ovf(self.getopnum())
  337. def can_raise(self):
  338. return rop.can_raise(self.getopnum())
  339. def is_foldable_guard(self):
  340. return rop.is_foldable_guard(self.getopnun())
  341. def is_primitive_array_access(self):
  342. """ Indicates that this operations loads/stores a
  343. primitive type (int,float) """
  344. if rop.is_primitive_load(self.opnum) or rop.is_primitive_store(self.opnum):
  345. descr = self.getdescr()
  346. if not we_are_translated():
  347. from rpython.jit.backend.llgraph.runner import _getdescr
  348. descr = _getdescr(self)
  349. if descr and descr.is_array_of_primitives():
  350. return True
  351. return False
  352. def is_vector(self):
  353. return False
  354. def returns_void(self):
  355. return self.type == 'v'
  356. def returns_vector(self):
  357. return self.type != 'v' and self.vector == -2
  358. def is_typecast(self):
  359. return False
  360. def cast_count(self, vec_reg_size):
  361. return self.cls_casts[4]
  362. def cast_types(self):
  363. return self.cls_casts[0], self.cls_casts[2]
  364. def cast_to_bytesize(self):
  365. return self.cls_casts[3]
  366. def cast_from_bytesize(self):
  367. return self.cls_casts[1]
  368. def casts_up(self):
  369. return self.cast_to_bytesize() > self.cast_from_bytesize()
  370. def casts_down(self):
  371. # includes the cast as noop
  372. return self.cast_to_bytesize() <= self.cast_from_bytesize()
  373. # ===================
  374. # Top of the hierachy
  375. # ===================
  376. class PlainResOp(AbstractResOp):
  377. pass
  378. class ResOpWithDescr(AbstractResOp):
  379. _descr = None
  380. def getdescr(self):
  381. return self._descr
  382. def setdescr(self, descr):
  383. # for 'call', 'new', 'getfield_gc'...: the descr is a prebuilt
  384. # instance provided by the backend holding details about the type
  385. # of the operation. It must inherit from AbstractDescr. The
  386. # backend provides it with cpu.fielddescrof(), cpu.arraydescrof(),
  387. # cpu.calldescrof(), and cpu.typedescrof().
  388. self._check_descr(descr)
  389. self._descr = descr
  390. def cleardescr(self):
  391. self._descr = None
  392. def _check_descr(self, descr):
  393. if not we_are_translated() and getattr(descr, 'I_am_a_descr', False):
  394. return # needed for the mock case in oparser_model
  395. from rpython.jit.metainterp.history import check_descr
  396. check_descr(descr)
  397. class GuardResOp(ResOpWithDescr):
  398. _fail_args = None
  399. rd_resume_position = -1
  400. def getfailargs(self):
  401. return self._fail_args
  402. def getfailargs_copy(self):
  403. return self._fail_args[:]
  404. def setfailargs(self, fail_args):
  405. self._fail_args = fail_args
  406. def copy_and_change(self, opnum, args=None, descr=None):
  407. newop = AbstractResOp.copy_and_change(self, opnum, args, descr)
  408. assert isinstance(newop, GuardResOp)
  409. newop.setfailargs(self.getfailargs())
  410. newop.rd_resume_position = self.rd_resume_position
  411. return newop
  412. class VectorGuardOp(GuardResOp):
  413. bytesize = 0
  414. datatype = '\x00'
  415. signed = True
  416. count = 0
  417. def copy_and_change(self, opnum, args=None, descr=None):
  418. newop = GuardResOp.copy_and_change(self, opnum, args, descr)
  419. assert isinstance(newop, VectorGuardOp)
  420. newop.datatype = self.datatype
  421. newop.bytesize = self.bytesize
  422. newop.signed = self.signed
  423. newop.count = self.count
  424. return newop
  425. class VectorOp(ResOpWithDescr):
  426. bytesize = 0
  427. datatype = '\x00'
  428. signed = True
  429. count = 0
  430. def is_vector(self):
  431. if self.getopnum() in (rop.VEC_UNPACK_I, rop.VEC_UNPACK_F):
  432. arg = self.getarg(2)
  433. from rpython.jit.metainterp.history import ConstInt
  434. assert isinstance(arg, ConstInt)
  435. return arg.value > 1
  436. return True
  437. def copy_and_change(self, opnum, args=None, descr=None):
  438. newop = ResOpWithDescr.copy_and_change(self, opnum, args, descr)
  439. assert isinstance(newop, VectorOp)
  440. newop.datatype = self.datatype
  441. newop.bytesize = self.bytesize
  442. newop.signed = self.signed
  443. newop.count = self.count
  444. return newop
  445. def same_shape(self, other):
  446. """ NOT_RPYTHON """
  447. myvecinfo = self.get_forwarded()
  448. othervecinfo = other.get_forwarded()
  449. if other.is_vector() != self.is_vector():
  450. return False
  451. if myvecinfo.datatype != othervecinfo.datatype:
  452. return False
  453. if myvecinfo.bytesize != othervecinfo.bytesize:
  454. return False
  455. if myvecinfo.signed != othervecinfo.signed:
  456. return False
  457. if myvecinfo.count != othervecinfo.count:
  458. return False
  459. return True
  460. # ===========
  461. # type mixins
  462. # ===========
  463. class IntOp(object):
  464. _mixin_ = True
  465. type = 'i'
  466. _resint = 0
  467. def getint(self):
  468. return self._resint
  469. getvalue = getint
  470. def setint(self, intval):
  471. self._resint = intval
  472. def copy_value_from(self, other):
  473. self.setint(other.getint())
  474. def constbox(self):
  475. from rpython.jit.metainterp import history
  476. return history.ConstInt(self.getint())
  477. def nonnull(self):
  478. return self._resint != 0
  479. class FloatOp(object):
  480. _mixin_ = True
  481. type = 'f'
  482. _resfloat = longlong.ZEROF
  483. def getfloatstorage(self):
  484. return self._resfloat
  485. getvalue = getfloatstorage
  486. def getfloat(self):
  487. return longlong.getrealfloat(self.getfloatstorage())
  488. def setfloatstorage(self, floatval):
  489. assert lltype.typeOf(floatval) is longlong.FLOATSTORAGE
  490. self._resfloat = floatval
  491. def copy_value_from(self, other):
  492. self.setfloatstorage(other.getfloatstorage())
  493. def constbox(self):
  494. from rpython.jit.metainterp import history
  495. return history.ConstFloat(self.getfloatstorage())
  496. def nonnull(self):
  497. return bool(longlong.extract_bits(self._resfloat))
  498. class RefOp(object):
  499. _mixin_ = True
  500. type = 'r'
  501. _resref = lltype.nullptr(llmemory.GCREF.TO)
  502. def getref_base(self):
  503. return self._resref
  504. def reset_value(self):
  505. self.setref_base(lltype.nullptr(llmemory.GCREF.TO))
  506. getvalue = getref_base
  507. def forget_value(self):
  508. self._resref = lltype.nullptr(llmemory.GCREF.TO)
  509. def setref_base(self, refval):
  510. self._resref = refval
  511. def getref(self, PTR):
  512. return lltype.cast_opaque_ptr(PTR, self.getref_base())
  513. getref._annspecialcase_ = 'specialize:arg(1)'
  514. def copy_value_from(self, other):
  515. self.setref_base(other.getref_base())
  516. def nonnull(self):
  517. return bool(self._resref)
  518. def constbox(self):
  519. from rpython.jit.metainterp import history
  520. return history.ConstPtr(self.getref_base())
  521. class CastOp(object):
  522. _mixin_ = True
  523. def is_typecast(self):
  524. return True
  525. def cast_to(self):
  526. to_type, size = self.cls_casts[2], self.cls_casts[3]
  527. if self.cls_casts[3] == 0:
  528. if self.getopnum() == rop.INT_SIGNEXT:
  529. from rpython.jit.metainterp.history import ConstInt
  530. arg = self.getarg(1)
  531. assert isinstance(arg, ConstInt)
  532. return (to_type,arg.value)
  533. else:
  534. raise NotImplementedError
  535. return (to_type,size)
  536. def cast_from(self):
  537. type, size, a, b = self.cls_casts
  538. if size == -1:
  539. return self.bytesize
  540. return (type, size)
  541. def cast_input_bytesize(self, vec_reg_size):
  542. count = vec_reg_size // self.cast_to_bytesize()
  543. size = self.cast_from_bytesize() * self.cast_count(vec_reg_size)
  544. return size
  545. class SignExtOp(object):
  546. _mixin_ = True
  547. def is_typecast(self):
  548. return True
  549. def cast_types(self):
  550. return self.cls_casts[0], self.cls_casts[2]
  551. def cast_to_bytesize(self):
  552. from rpython.jit.metainterp.history import ConstInt
  553. arg = self.getarg(1)
  554. assert isinstance(arg, ConstInt)
  555. return arg.value
  556. def cast_from_bytesize(self):
  557. arg = self.getarg(0)
  558. vecinfo = arg.get_forwarded()
  559. if vecinfo is None or not isinstance(vecinfo, VectorizationInfo):
  560. vecinfo = VectorizationInfo(arg)
  561. return vecinfo.bytesize
  562. def cast_input_bytesize(self, vec_reg_size):
  563. return vec_reg_size # self.cast_from_bytesize() * self.cast_count(vec_reg_size)
  564. class AbstractInputArg(AbstractResOpOrInputArg):
  565. _attrs_ = ('_forwarded', 'position')
  566. def repr(self, memo):
  567. try:
  568. num = memo[self]
  569. except KeyError:
  570. num = len(memo)
  571. memo[self] = num
  572. return self.type + str(num)
  573. def get_position(self):
  574. return self.position
  575. def __repr__(self):
  576. return self.repr(self._repr_memo)
  577. def is_inputarg(self):
  578. return True
  579. class InputArgInt(IntOp, AbstractInputArg):
  580. datatype = 'i'
  581. bytesize = INT_WORD
  582. signed = True
  583. def __init__(self, intval=0):
  584. self.setint(intval)
  585. class InputArgFloat(FloatOp, AbstractInputArg):
  586. datatype = 'f'
  587. bytesize = FLOAT_WORD
  588. signed = True
  589. def __init__(self, f=longlong.ZEROF):
  590. self.setfloatstorage(f)
  591. @staticmethod
  592. def fromfloat(x):
  593. return InputArgFloat(longlong.getfloatstorage(x))
  594. class InputArgRef(RefOp, AbstractInputArg):
  595. datatype = 'r'
  596. def __init__(self, r=lltype.nullptr(llmemory.GCREF.TO)):
  597. self.setref_base(r)
  598. self.datatype = 'r'
  599. def reset_value(self):
  600. self.setref_base(lltype.nullptr(llmemory.GCREF.TO))
  601. class InputArgVector(AbstractInputArg):
  602. type = 'V'
  603. def __init__(self):
  604. pass
  605. def returns_vector(self):
  606. return True
  607. # ============
  608. # arity mixins
  609. # ============
  610. class NullaryOp(object):
  611. _mixin_ = True
  612. def initarglist(self, args):
  613. assert len(args) == 0
  614. def getarglist(self):
  615. return []
  616. def numargs(self):
  617. return 0
  618. def getarg(self, i):
  619. raise IndexError
  620. def setarg(self, i, box):
  621. raise IndexError
  622. class UnaryOp(object):
  623. _mixin_ = True
  624. _arg0 = None
  625. def initarglist(self, args):
  626. assert len(args) == 1
  627. self._arg0, = args
  628. def getarglist(self):
  629. return [self._arg0]
  630. def numargs(self):
  631. return 1
  632. def getarg(self, i):
  633. if i == 0:
  634. return self._arg0
  635. else:
  636. raise IndexError
  637. def setarg(self, i, box):
  638. if i == 0:
  639. self._arg0 = box
  640. else:
  641. raise IndexError
  642. class BinaryOp(object):
  643. _mixin_ = True
  644. _arg0 = None
  645. _arg1 = None
  646. def initarglist(self, args):
  647. assert len(args) == 2
  648. self._arg0, self._arg1 = args
  649. def numargs(self):
  650. return 2
  651. def getarg(self, i):
  652. if i == 0:
  653. return self._arg0
  654. elif i == 1:
  655. return self._arg1
  656. else:
  657. raise IndexError
  658. def setarg(self, i, box):
  659. if i == 0:
  660. self._arg0 = box
  661. elif i == 1:
  662. self._arg1 = box
  663. else:
  664. raise IndexError
  665. def getarglist(self):
  666. return [self._arg0, self._arg1]
  667. class TernaryOp(object):
  668. _mixin_ = True
  669. _arg0 = None
  670. _arg1 = None
  671. _arg2 = None
  672. def initarglist(self, args):
  673. assert len(args) == 3
  674. self._arg0, self._arg1, self._arg2 = args
  675. def getarglist(self):
  676. return [self._arg0, self._arg1, self._arg2]
  677. def numargs(self):
  678. return 3
  679. def getarg(self, i):
  680. if i == 0:
  681. return self._arg0
  682. elif i == 1:
  683. return self._arg1
  684. elif i == 2:
  685. return self._arg2
  686. else:
  687. raise IndexError
  688. def setarg(self, i, box):
  689. if i == 0:
  690. self._arg0 = box
  691. elif i == 1:
  692. self._arg1 = box
  693. elif i == 2:
  694. self._arg2 = box
  695. else:
  696. raise IndexError
  697. class N_aryOp(object):
  698. _mixin_ = True
  699. _args = None
  700. def initarglist(self, args):
  701. self._args = args
  702. if not we_are_translated() and \
  703. self.__class__.__name__.startswith('FINISH'): # XXX remove me
  704. assert len(args) <= 1 # FINISH operations take 0 or 1 arg now
  705. def getarglist(self):
  706. return self._args
  707. def getarglist_copy(self):
  708. return self._args[:]
  709. def numargs(self):
  710. return len(self._args)
  711. def getarg(self, i):
  712. return self._args[i]
  713. def setarg(self, i, box):
  714. self._args[i] = box
  715. # ____________________________________________________________
  716. """ All the operations are desribed like this:
  717. NAME/no-of-args-or-*[b][d]/types-of-result
  718. if b is present it means the operation produces a boolean
  719. if d is present it means there is a descr
  720. type of result can be one or more of r i f n
  721. """
  722. _oplist = [
  723. '_FINAL_FIRST',
  724. 'JUMP/*d/n',
  725. 'FINISH/*d/n',
  726. '_FINAL_LAST',
  727. 'LABEL/*d/n',
  728. '_GUARD_FIRST',
  729. '_GUARD_FOLDABLE_FIRST',
  730. 'GUARD_TRUE/1d/n',
  731. 'GUARD_FALSE/1d/n',
  732. 'VEC_GUARD_TRUE/1d/n',
  733. 'VEC_GUARD_FALSE/1d/n',
  734. 'GUARD_VALUE/2d/n',
  735. 'GUARD_CLASS/2d/n',
  736. 'GUARD_NONNULL/1d/n',
  737. 'GUARD_ISNULL/1d/n',
  738. 'GUARD_NONNULL_CLASS/2d/n',
  739. 'GUARD_GC_TYPE/2d/n', # only if supports_guard_gc_type
  740. 'GUARD_IS_OBJECT/1d/n', # only if supports_guard_gc_type
  741. 'GUARD_SUBCLASS/2d/n', # only if supports_guard_gc_type
  742. '_GUARD_FOLDABLE_LAST',
  743. 'GUARD_NO_EXCEPTION/0d/n', # may be called with an exception currently set
  744. 'GUARD_EXCEPTION/1d/r', # XXX kill me, use only SAVE_EXCEPTION
  745. 'GUARD_NO_OVERFLOW/0d/n',
  746. 'GUARD_OVERFLOW/0d/n',
  747. 'GUARD_NOT_FORCED/0d/n', # may be called with an exception currently set
  748. 'GUARD_NOT_FORCED_2/0d/n', # same as GUARD_NOT_FORCED, but for finish()
  749. 'GUARD_NOT_INVALIDATED/0d/n',
  750. 'GUARD_FUTURE_CONDITION/0d/n',
  751. # is removable, may be patched by an optimization
  752. '_GUARD_LAST', # ----- end of guard operations -----
  753. '_NOSIDEEFFECT_FIRST', # ----- start of no_side_effect operations -----
  754. '_ALWAYS_PURE_FIRST', # ----- start of always_pure operations -----
  755. 'INT_ADD/2/i',
  756. 'INT_SUB/2/i',
  757. 'INT_MUL/2/i',
  758. 'UINT_MUL_HIGH/2/i', # a * b as a double-word, keep the high word
  759. 'INT_AND/2/i',
  760. 'INT_OR/2/i',
  761. 'INT_XOR/2/i',
  762. 'INT_RSHIFT/2/i',
  763. 'INT_LSHIFT/2/i',
  764. 'UINT_RSHIFT/2/i',
  765. 'INT_SIGNEXT/2/i',
  766. 'FLOAT_ADD/2/f',
  767. 'FLOAT_SUB/2/f',
  768. 'FLOAT_MUL/2/f',
  769. 'FLOAT_TRUEDIV/2/f',
  770. 'FLOAT_NEG/1/f',
  771. 'FLOAT_ABS/1/f',
  772. 'CAST_FLOAT_TO_INT/1/i', # don't use for unsigned ints; we would
  773. 'CAST_INT_TO_FLOAT/1/f', # need some messy code in the backend
  774. 'CAST_FLOAT_TO_SINGLEFLOAT/1/i',
  775. 'CAST_SINGLEFLOAT_TO_FLOAT/1/f',
  776. 'CONVERT_FLOAT_BYTES_TO_LONGLONG/1/' + ('i' if longlong.is_64_bit else 'f'),
  777. 'CONVERT_LONGLONG_BYTES_TO_FLOAT/1/f',
  778. #
  779. # vector operations
  780. '_VEC_PURE_FIRST',
  781. '_VEC_ARITHMETIC_FIRST',
  782. 'VEC_INT_ADD/2/i',
  783. 'VEC_INT_SUB/2/i',
  784. 'VEC_INT_MUL/2/i',
  785. 'VEC_INT_AND/2/i',
  786. 'VEC_INT_OR/2/i',
  787. 'VEC_INT_XOR/2/i',
  788. 'VEC_FLOAT_ADD/2/f',
  789. 'VEC_FLOAT_SUB/2/f',
  790. 'VEC_FLOAT_MUL/2/f',
  791. 'VEC_FLOAT_TRUEDIV/2/f',
  792. 'VEC_FLOAT_NEG/1/f',
  793. 'VEC_FLOAT_ABS/1/f',
  794. '_VEC_ARITHMETIC_LAST',
  795. 'VEC_FLOAT_EQ/2b/i',
  796. 'VEC_FLOAT_NE/2b/i',
  797. 'VEC_INT_IS_TRUE/1b/i',
  798. 'VEC_INT_NE/2b/i',
  799. 'VEC_INT_EQ/2b/i',
  800. '_VEC_CAST_FIRST',
  801. 'VEC_INT_SIGNEXT/2/i',
  802. # double -> float: v2 = cast(v1, 2) equal to v2 = (v1[0], v1[1], X, X)
  803. 'VEC_CAST_FLOAT_TO_SINGLEFLOAT/1/i',
  804. # v4 = cast(v3, 0, 2), v4 = (v3[0], v3[1])
  805. 'VEC_CAST_SINGLEFLOAT_TO_FLOAT/1/f',
  806. 'VEC_CAST_FLOAT_TO_INT/1/i',
  807. 'VEC_CAST_INT_TO_FLOAT/1/f',
  808. '_VEC_CAST_LAST',
  809. 'VEC/0/if',
  810. 'VEC_UNPACK/3/if', # iX|fX = VEC_INT_UNPACK(vX, index, count)
  811. 'VEC_PACK/4/if', # VEC_INT_PACK(vX, var/const, index, count)
  812. 'VEC_EXPAND/1/if', # vX = VEC_INT_EXPAND(var/const)
  813. '_VEC_PURE_LAST',
  814. #
  815. 'INT_LT/2b/i',
  816. 'INT_LE/2b/i',
  817. 'INT_EQ/2b/i',
  818. 'INT_NE/2b/i',
  819. 'INT_GT/2b/i',
  820. 'INT_GE/2b/i',
  821. 'UINT_LT/2b/i',
  822. 'UINT_LE/2b/i',
  823. 'UINT_GT/2b/i',
  824. 'UINT_GE/2b/i',
  825. 'FLOAT_LT/2b/i',
  826. 'FLOAT_LE/2b/i',
  827. 'FLOAT_EQ/2b/i',
  828. 'FLOAT_NE/2b/i',
  829. 'FLOAT_GT/2b/i',
  830. 'FLOAT_GE/2b/i',
  831. #
  832. 'INT_IS_ZERO/1b/i',
  833. 'INT_IS_TRUE/1b/i',
  834. 'INT_NEG/1/i',
  835. 'INT_INVERT/1/i',
  836. 'INT_FORCE_GE_ZERO/1/i',
  837. #
  838. 'SAME_AS/1/ifr', # gets a Const or a Box, turns it into another Box
  839. 'CAST_PTR_TO_INT/1/i',
  840. 'CAST_INT_TO_PTR/1/r',
  841. #
  842. 'PTR_EQ/2b/i',
  843. 'PTR_NE/2b/i',
  844. 'INSTANCE_PTR_EQ/2b/i',
  845. 'INSTANCE_PTR_NE/2b/i',
  846. 'NURSERY_PTR_INCREMENT/2/r',
  847. #
  848. 'ARRAYLEN_GC/1d/i',
  849. 'STRLEN/1/i',
  850. 'STRGETITEM/2/i',
  851. 'GETARRAYITEM_GC_PURE/2d/rfi',
  852. 'UNICODELEN/1/i',
  853. 'UNICODEGETITEM/2/i',
  854. #
  855. 'LOAD_FROM_GC_TABLE/1/r', # only emitted by rewrite.py
  856. #
  857. '_ALWAYS_PURE_LAST', # ----- end of always_pure operations -----
  858. # parameters GC_LOAD
  859. # 1: pointer to complex object
  860. # 2: integer describing the offset
  861. # 3: constant integer. byte size of datatype to load (negative if it is signed)
  862. 'GC_LOAD/3/rfi',
  863. # parameters GC_LOAD_INDEXED
  864. # 1: pointer to complex object
  865. # 2: integer describing the index
  866. # 3: constant integer scale factor
  867. # 4: constant integer base offset (final offset is 'base + scale * index')
  868. # 5: constant integer. byte size of datatype to load (negative if it is signed)
  869. # (GC_LOAD is equivalent to GC_LOAD_INDEXED with arg3==1, arg4==0)
  870. 'GC_LOAD_INDEXED/5/rfi',
  871. '_RAW_LOAD_FIRST',
  872. 'GETARRAYITEM_GC/2d/rfi',
  873. 'VEC_GETARRAYITEM_GC/2d/fi',
  874. 'GETARRAYITEM_RAW/2d/fi',
  875. 'VEC_GETARRAYITEM_RAW/2d/fi',
  876. 'RAW_LOAD/2d/fi',
  877. 'VEC_RAW_LOAD/2d/fi',
  878. '_RAW_LOAD_LAST',
  879. 'GETINTERIORFIELD_GC/2d/rfi',
  880. 'GETFIELD_GC/1d/rfi',
  881. 'GETFIELD_RAW/1d/rfi',
  882. '_MALLOC_FIRST',
  883. 'NEW/0d/r', #-> GcStruct, gcptrs inside are zeroed (not the rest)
  884. 'NEW_WITH_VTABLE/0d/r',#-> GcStruct with vtable, gcptrs inside are zeroed
  885. 'NEW_ARRAY/1d/r', #-> GcArray, not zeroed. only for arrays of primitives
  886. 'NEW_ARRAY_CLEAR/1d/r',#-> GcArray, fully zeroed
  887. 'NEWSTR/1/r', #-> STR, the hash field is zeroed
  888. 'NEWUNICODE/1/r', #-> UNICODE, the hash field is zeroed
  889. '_MALLOC_LAST',
  890. 'FORCE_TOKEN/0/r', # historical name; nowadays, returns the jitframe
  891. 'VIRTUAL_REF/2/r', # removed before it's passed to the backend
  892. # this one has no *visible* side effect, since the virtualizable
  893. # must be forced, however we need to execute it anyway
  894. '_NOSIDEEFFECT_LAST', # ----- end of no_side_effect operations -----
  895. # same paramters as GC_LOAD, but one additional for the value to store
  896. # note that the itemsize is not signed (always > 0)
  897. # (gcptr, index, value, [scale, base_offset,] itemsize)
  898. # invariants for GC_STORE: index is constant, but can be large
  899. # invariants for GC_STORE_INDEXED: index is a non-constant box;
  900. # scale is a constant;
  901. # base_offset is a small constant
  902. 'GC_STORE/4d/n',
  903. 'GC_STORE_INDEXED/6d/n',
  904. 'INCREMENT_DEBUG_COUNTER/1/n',
  905. '_RAW_STORE_FIRST',
  906. 'SETARRAYITEM_GC/3d/n',
  907. 'VEC_SETARRAYITEM_GC/3d/n',
  908. 'SETARRAYITEM_RAW/3d/n',
  909. 'VEC_SETARRAYITEM_RAW/3d/n',
  910. 'RAW_STORE/3d/n',
  911. 'VEC_RAW_STORE/3d/n',
  912. '_RAW_STORE_LAST',
  913. 'SETINTERIORFIELD_GC/3d/n',
  914. 'SETINTERIORFIELD_RAW/3d/n', # right now, only used by tests
  915. 'SETFIELD_GC/2d/n',
  916. 'ZERO_ARRAY/5d/n', # only emitted by the rewrite, clears (part of) an array
  917. # [arraygcptr, firstindex, length, scale_firstindex,
  918. # scale_length], descr=ArrayDescr
  919. 'SETFIELD_RAW/2d/n',
  920. 'STRSETITEM/3/n',
  921. 'UNICODESETITEM/3/n',
  922. 'COND_CALL_GC_WB/1d/n', # [objptr] (for the write barrier)
  923. 'COND_CALL_GC_WB_ARRAY/2d/n', # [objptr, arrayindex] (write barr. for array)
  924. '_JIT_DEBUG_FIRST',
  925. 'DEBUG_MERGE_POINT/*/n', # debugging only
  926. 'ENTER_PORTAL_FRAME/2/n', # debugging only
  927. 'LEAVE_PORTAL_FRAME/1/n', # debugging only
  928. 'JIT_DEBUG/*/n', # debugging only
  929. '_JIT_DEBUG_LAST',
  930. 'ESCAPE/*/rfin', # tests only
  931. 'FORCE_SPILL/1/n', # tests only
  932. 'VIRTUAL_REF_FINISH/2/n', # removed before it's passed to the backend
  933. 'COPYSTRCONTENT/5/n', # src, dst, srcstart, dststart, length
  934. 'COPYUNICODECONTENT/5/n',
  935. 'QUASIIMMUT_FIELD/1d/n', # [objptr], descr=SlowMutateDescr
  936. 'RECORD_EXACT_CLASS/2/n', # [objptr, clsptr]
  937. 'KEEPALIVE/1/n',
  938. 'SAVE_EXCEPTION/0/r',
  939. 'SAVE_EXC_CLASS/0/i', # XXX kill me
  940. 'RESTORE_EXCEPTION/2/n', # XXX kill me
  941. '_CANRAISE_FIRST', # ----- start of can_raise operations -----
  942. '_CALL_FIRST',
  943. 'CALL/*d/rfin',
  944. 'COND_CALL/*d/n',
  945. # a conditional call, with first argument as a condition
  946. 'CALL_ASSEMBLER/*d/rfin', # call already compiled assembler
  947. 'CALL_MAY_FORCE/*d/rfin',
  948. 'CALL_LOOPINVARIANT/*d/rfin',
  949. 'CALL_RELEASE_GIL/*d/fin',
  950. # release the GIL and "close the stack" for asmgcc
  951. 'CALL_PURE/*d/rfin', # removed before it's passed to the backend
  952. 'CHECK_MEMORY_ERROR/1/n', # after a CALL: NULL => propagate MemoryError
  953. 'CALL_MALLOC_NURSERY/1/r', # nursery malloc, const number of bytes, zeroed
  954. 'CALL_MALLOC_NURSERY_VARSIZE/3d/r',
  955. 'CALL_MALLOC_NURSERY_VARSIZE_FRAME/1/r',
  956. # nursery malloc, non-const number of bytes, zeroed
  957. # note that the number of bytes must be well known to be small enough
  958. # to fulfill allocating in the nursery rules (and no card markings)
  959. '_CALL_LAST',
  960. '_CANRAISE_LAST', # ----- end of can_raise operations -----
  961. '_OVF_FIRST', # ----- start of is_ovf operations -----
  962. 'INT_ADD_OVF/2/i', # note that the orded has to match INT_ADD order
  963. 'INT_SUB_OVF/2/i',
  964. 'INT_MUL_OVF/2/i',
  965. '_OVF_LAST', # ----- end of is_ovf operations -----
  966. '_LAST', # for the backend to add more internal operations
  967. ]
  968. _cast_ops = {
  969. 'CAST_FLOAT_TO_INT': ('f', 8, 'i', 4, 2),
  970. 'VEC_CAST_FLOAT_TO_INT': ('f', 8, 'i', 4, 2),
  971. 'CAST_INT_TO_FLOAT': ('i', 4, 'f', 8, 2),
  972. 'VEC_CAST_INT_TO_FLOAT': ('i', 4, 'f', 8, 2),
  973. 'CAST_FLOAT_TO_SINGLEFLOAT': ('f', 8, 'i', 4, 2),
  974. 'VEC_CAST_FLOAT_TO_SINGLEFLOAT': ('f', 8, 'i', 4, 2),
  975. 'CAST_SINGLEFLOAT_TO_FLOAT': ('i', 4, 'f', 8, 2),
  976. 'VEC_CAST_SINGLEFLOAT_TO_FLOAT': ('i', 4, 'f', 8, 2),
  977. 'INT_SIGNEXT': ('i', 0, 'i', 0, 0),
  978. 'VEC_INT_SIGNEXT': ('i', 0, 'i', 0, 0),
  979. }
  980. # ____________________________________________________________
  981. class rop(object):
  982. @staticmethod
  983. def call_for_descr(descr):
  984. tp = descr.get_normalized_result_type()
  985. if tp == 'i':
  986. return rop.CALL_I
  987. elif tp == 'r':
  988. return rop.CALL_R
  989. elif tp == 'f':
  990. return rop.CALL_F
  991. assert tp == 'v'
  992. return rop.CALL_N
  993. @staticmethod
  994. def call_pure_for_descr(descr):
  995. tp = descr.get_normalized_result_type()
  996. if tp == 'i':
  997. return rop.CALL_PURE_I
  998. elif tp == 'r':
  999. return rop.CALL_PURE_R
  1000. elif tp == 'f':
  1001. return rop.CALL_PURE_F
  1002. assert tp == 'v'
  1003. return rop.CALL_PURE_N
  1004. @staticmethod
  1005. def call_may_force_for_descr(descr):
  1006. tp = descr.get_normalized_result_type()
  1007. if tp == 'i':
  1008. return rop.CALL_MAY_FORCE_I
  1009. elif tp == 'r':
  1010. return rop.CALL_MAY_FORCE_R
  1011. elif tp == 'f':
  1012. return rop.CALL_MAY_FORCE_F
  1013. assert tp == 'v'
  1014. return rop.CALL_MAY_FORCE_N
  1015. @staticmethod
  1016. def call_release_gil_for_descr(descr):
  1017. tp = descr.get_normalized_result_type()
  1018. if tp == 'i':
  1019. return rop.CALL_RELEASE_GIL_I
  1020. # no such thing
  1021. #elif tp == 'r':
  1022. # return rop.CALL_RELEASE_GIL_R
  1023. elif tp == 'f':
  1024. return rop.CALL_RELEASE_GIL_F
  1025. assert tp == 'v'
  1026. return rop.CALL_RELEASE_GIL_N
  1027. @staticmethod
  1028. def call_assembler_for_descr(descr):
  1029. tp = descr.get_normalized_result_type()
  1030. if tp == 'i':
  1031. return rop.CALL_ASSEMBLER_I
  1032. elif tp == 'r':
  1033. return rop.CALL_ASSEMBLER_R
  1034. elif tp == 'f':
  1035. return rop.CALL_ASSEMBLER_F
  1036. assert tp == 'v'
  1037. return rop.CALL_ASSEMBLER_N
  1038. @staticmethod
  1039. def call_loopinvariant_for_descr(descr):
  1040. tp = descr.get_normalized_result_type()
  1041. if tp == 'i':
  1042. return rop.CALL_LOOPINVARIANT_I
  1043. elif tp == 'r':
  1044. return rop.CALL_LOOPINVARIANT_R
  1045. elif tp == 'f':
  1046. return rop.CALL_LOOPINVARIANT_F
  1047. assert tp == 'v'
  1048. return rop.CALL_LOOPINVARIANT_N
  1049. @staticmethod
  1050. def getfield_pure_for_descr(descr):
  1051. if descr.is_pointer_field():
  1052. return rop.GETFIELD_GC_PURE_R
  1053. elif descr.is_float_field():
  1054. return rop.GETFIELD_GC_PURE_F
  1055. return rop.GETFIELD_GC_PURE_I
  1056. @staticmethod
  1057. def getfield_for_descr(descr):
  1058. if descr.is_pointer_field():
  1059. return rop.GETFIELD_GC_R
  1060. elif descr.is_float_field():
  1061. return rop.GETFIELD_GC_F
  1062. return rop.GETFIELD_GC_I
  1063. @staticmethod
  1064. def getarrayitem_pure_for_descr(descr):
  1065. if descr.is_array_of_pointers():
  1066. return rop.GETARRAYITEM_GC_PURE_R
  1067. elif descr.is_array_of_floats():
  1068. return rop.GETARRAYITEM_GC_PURE_F
  1069. return rop.GETARRAYITEM_GC_PURE_I
  1070. @staticmethod
  1071. def getarrayitem_for_descr(descr):
  1072. if descr.is_array_of_pointers():
  1073. return rop.GETARRAYITEM_GC_R
  1074. elif descr.is_array_of_floats():
  1075. return rop.GETARRAYITEM_GC_F
  1076. return rop.GETARRAYITEM_GC_I
  1077. @staticmethod
  1078. def same_as_for_type(tp):
  1079. if tp == 'i':
  1080. return rop.SAME_AS_I
  1081. elif tp == 'r':
  1082. return rop.SAME_AS_R
  1083. else:
  1084. assert tp == 'f'
  1085. return rop.SAME_AS_F
  1086. @staticmethod
  1087. def call_for_type(tp):
  1088. if tp == 'i':
  1089. return rop.CALL_I
  1090. elif tp == 'r':
  1091. return rop.CALL_R
  1092. elif tp == 'f':
  1093. return rop.CALL_F
  1094. return rop.CALL_N
  1095. @staticmethod
  1096. def is_guard(opnum):
  1097. return rop._GUARD_FIRST <= opnum <= rop._GUARD_LAST
  1098. @staticmethod
  1099. def is_comparison(opnum):
  1100. return rop.is_always_pure(opnum) and rop.returns_bool_result(opnum)
  1101. @staticmethod
  1102. def is_foldable_guard(opnum):
  1103. return rop._GUARD_FOLDABLE_FIRST <= opnum <= rop._GUARD_FOLDABLE_LAST
  1104. @staticmethod
  1105. def is_guard_exception(opnum):
  1106. return (opnum == rop.GUARD_EXCEPTION or
  1107. opnum == rop.GUARD_NO_EXCEPTION)
  1108. @staticmethod
  1109. def is_guard_overflow(opnum):
  1110. return (opnum == rop.GUARD_OVERFLOW or
  1111. opnum == rop.GUARD_NO_OVERFLOW)
  1112. @staticmethod
  1113. def is_jit_debug(opnum):
  1114. return rop._JIT_DEBUG_FIRST <= opnum <= rop._JIT_DEBUG_LAST
  1115. @staticmethod
  1116. def is_always_pure(opnum):
  1117. return rop._ALWAYS_PURE_FIRST <= opnum <= rop._ALWAYS_PURE_LAST
  1118. @staticmethod
  1119. def is_pure_with_descr(opnum, descr):
  1120. if rop.is_always_pure(opnum):
  1121. return True
  1122. if (opnum == rop.GETFIELD_RAW_I or
  1123. opnum == rop.GETFIELD_RAW_R or
  1124. opnum == rop.GETFIELD_RAW_F or
  1125. opnum == rop.GETFIELD_GC_I or
  1126. opnum == rop.GETFIELD_GC_R or
  1127. opnum == rop.GETFIELD_GC_F or
  1128. opnum == rop.GETARRAYITEM_RAW_I or
  1129. opnum == rop.GETARRAYITEM_RAW_F):
  1130. return descr.is_always_pure()
  1131. return False
  1132. @staticmethod
  1133. def is_pure_getfield(opnum, descr):
  1134. if (opnum == rop.GETFIELD_GC_I or
  1135. opnum == rop.GETFIELD_GC_F or
  1136. opnum == rop.GETFIELD_GC_R):
  1137. return descr is not None and descr.is_always_pure()
  1138. return False
  1139. @staticmethod
  1140. def has_no_side_effect(opnum):
  1141. return rop._NOSIDEEFFECT_FIRST <= opnum <= rop._NOSIDEEFFECT_LAST
  1142. @staticmethod
  1143. def can_raise(opnum):
  1144. return rop._CANRAISE_FIRST <= opnum <= rop._CANRAISE_LAST
  1145. @staticmethod
  1146. def is_malloc(opnum):
  1147. # a slightly different meaning from can_malloc
  1148. return rop._MALLOC_FIRST <= opnum <= rop._MALLOC_LAST
  1149. @staticmethod
  1150. def can_malloc(opnum):
  1151. return rop.is_call(opnum) or rop.is_malloc(opnum)
  1152. @staticmethod
  1153. def is_same_as(opnum):
  1154. return opnum in (rop.SAME_AS_I, rop.SAME_AS_F, rop.SAME_AS_R)
  1155. @staticmethod
  1156. def is_getfield(opnum):
  1157. return opnum in (rop.GETFIELD_GC_I, rop.GETFIELD_GC_F,
  1158. rop.GETFIELD_GC_R)
  1159. @staticmethod
  1160. def is_getarrayitem(opnum):
  1161. return opnum in (rop.GETARRAYITEM_GC_I, rop.GETARRAYITEM_GC_F,
  1162. rop.GETARRAYITEM_GC_R, rop.GETARRAYITEM_GC_PURE_I,
  1163. rop.GETARRAYITEM_GC_PURE_F,
  1164. rop.GETARRAYITEM_GC_PURE_R)
  1165. @staticmethod
  1166. def is_real_call(opnum):
  1167. return (opnum == rop.CALL_I or
  1168. opnum == rop.CALL_R or
  1169. opnum == rop.CALL_F or
  1170. opnum == rop.CALL_N)
  1171. @staticmethod
  1172. def is_call_assembler(opnum):
  1173. return (opnum == rop.CALL_ASSEMBLER_I or
  1174. opnum == rop.CALL_ASSEMBLER_R or
  1175. opnum == rop.CALL_ASSEMBLER_N or
  1176. opnum == rop.CALL_ASSEMBLER_F)
  1177. @staticmethod
  1178. def is_call_may_force(opnum):
  1179. return (opnum == rop.CALL_MAY_FORCE_I or
  1180. opnum == rop.CALL_MAY_FORCE_R or
  1181. opnum == rop.CALL_MAY_FORCE_N or
  1182. opnum == rop.CALL_MAY_FORCE_F)
  1183. @staticmethod
  1184. def is_call_pure(opnum):
  1185. return (opnum == rop.CALL_PURE_I or
  1186. opnum == rop.CALL_PURE_R or
  1187. opnum == rop.CALL_PURE_N or
  1188. opnum == rop.CALL_PURE_F)
  1189. @staticmethod
  1190. def is_call_release_gil(opnum):
  1191. # no R returning call_release_gil
  1192. return (opnum == rop.CALL_RELEASE_GIL_I or
  1193. opnum == rop.CALL_RELEASE_GIL_F or
  1194. opnum == rop.CALL_RELEASE_GIL_N)
  1195. @staticmethod
  1196. def is_ovf(opnum):
  1197. return rop._OVF_FIRST <= opnum <= rop._OVF_LAST
  1198. @staticmethod
  1199. def is_vector_arithmetic(opnum):
  1200. return rop._VEC_ARITHMETIC_FIRST <= opnum <= rop._VEC_ARITHMETIC_LAST
  1201. @staticmethod
  1202. def is_raw_array_access(opnum):
  1203. return rop.is_raw_load(opnum) or rop.is_raw_store(opnum)
  1204. @staticmethod
  1205. def is_primitive_load(opnum):
  1206. return rop._RAW_LOAD_FIRST < opnum < rop._RAW_LOAD_LAST
  1207. @staticmethod
  1208. def is_primitive_store(opnum):
  1209. return rop._RAW_STORE_FIRST < opnum < rop._RAW_STORE_LAST
  1210. @staticmethod
  1211. def is_final(opnum):
  1212. return rop._FINAL_FIRST <= opnum <= rop._FINAL_LAST
  1213. @staticmethod
  1214. def returns_bool_result(opnum):
  1215. return opclasses[opnum]._cls_has_bool_result
  1216. @staticmethod
  1217. def is_label(opnum):
  1218. return opnum == rop.LABEL
  1219. @staticmethod
  1220. def is_call(opnum):
  1221. return rop._CALL_FIRST <= opnum <= rop._CALL_LAST
  1222. @staticmethod
  1223. def is_plain_call(opnum):
  1224. return (opnum == rop.CALL_I or
  1225. opnum == rop.CALL_R or
  1226. opnum == rop.CALL_F or
  1227. opnum == rop.CALL_N)
  1228. @staticmethod
  1229. def is_call_loopinvariant(opnum):
  1230. return (opnum == rop.CALL_LOOPINVARIANT_I or
  1231. opnum == rop.CALL_LOOPINVARIANT_R or
  1232. opnum == rop.CALL_LOOPINVARIANT_F or
  1233. opnum == rop.CALL_LOOPINVARIANT_N)
  1234. @staticmethod
  1235. def get_gc_load(tp):
  1236. if tp == 'i':
  1237. return rop.GC_LOAD_I
  1238. elif tp == 'f':
  1239. return rop.GC_LOAD_F
  1240. else:
  1241. assert tp == 'r'
  1242. return rop.GC_LOAD_R
  1243. @staticmethod
  1244. def get_gc_load_indexed(tp):
  1245. if tp == 'i':
  1246. return rop.GC_LOAD_INDEXED_I
  1247. elif tp == 'f':
  1248. return rop.GC_LOAD_INDEXED_F
  1249. else:
  1250. assert tp == 'r'
  1251. return rop.GC_LOAD_INDEXED_R
  1252. @staticmethod
  1253. def inputarg_from_tp(tp):
  1254. if tp == 'i':
  1255. return InputArgInt()
  1256. elif tp == 'r' or tp == 'p':
  1257. return InputArgRef()
  1258. elif tp == 'v':
  1259. return InputArgVector()
  1260. else:
  1261. assert tp == 'f'
  1262. return InputArgFloat()
  1263. @staticmethod
  1264. def create_vec_expand(arg, bytesize, signed, count):
  1265. if arg.type == 'i':
  1266. opnum = rop.VEC_EXPAND_I
  1267. else:
  1268. assert arg.type == 'f'
  1269. opnum = rop.VEC_EXPAND_F
  1270. return VecOperationNew(opnum, [arg], arg.type, bytesize, signed, count)
  1271. @staticmethod
  1272. def create_vec(datatype, bytesize, signed, count):
  1273. if datatype == 'i':
  1274. opnum = rop.VEC_I
  1275. else:
  1276. assert datatype == 'f'
  1277. opnum = rop.VEC_F
  1278. return VecOperationNew(opnum, [], datatype, bytesize, signed, count)
  1279. @staticmethod
  1280. def create_vec_pack(datatype, args, bytesize, signed, count):
  1281. if datatype == 'i':
  1282. opnum = rop.VEC_PACK_I
  1283. else:
  1284. assert datatype == 'f'
  1285. opnum = rop.VEC_PACK_F
  1286. return VecOperationNew(opnum, args, datatype, bytesize, signed, count)
  1287. @staticmethod
  1288. def create_vec_unpack(datatype, args, bytesize, signed, count):
  1289. if datatype == 'i':
  1290. opnum = rop.VEC_UNPACK_I
  1291. else:
  1292. assert datatype == 'f'
  1293. opnum = rop.VEC_UNPACK_F
  1294. return VecOperationNew(opnum, args, datatype, bytesize, signed, count)
  1295. opclasses = [] # mapping numbers to the concrete ResOp class
  1296. opname = {} # mapping numbers to the original names, for debugging
  1297. oparity = [] # mapping numbers to the arity of the operation or -1
  1298. opwithdescr = [] # mapping numbers to a flag "takes a descr"
  1299. optypes = [] # mapping numbers to type of return
  1300. def setup(debug_print=False):
  1301. i = 0
  1302. for name in _oplist:
  1303. if '/' in name:
  1304. name, arity, result = name.split('/')
  1305. withdescr = 'd' in arity
  1306. boolresult = 'b' in arity
  1307. arity = arity.rstrip('db')
  1308. if arity == '*':
  1309. arity = -1
  1310. else:
  1311. arity = int(arity)
  1312. else:
  1313. arity, withdescr, boolresult, result = -1, True, False, None # default
  1314. if not name.startswith('_'):
  1315. for r in result:
  1316. if len(result) == 1:
  1317. cls_name = name
  1318. else:
  1319. cls_name = name + '_' + r.upper()
  1320. setattr(rop, cls_name, i)
  1321. opname[i] = cls_name
  1322. cls = create_class_for_op(cls_name, i, arity, withdescr, r)
  1323. cls._cls_has_bool_result = boolresult
  1324. opclasses.append(cls)
  1325. oparity.append(arity)
  1326. opwithdescr.append(withdescr)
  1327. optypes.append(r)
  1328. if debug_print:
  1329. print '%30s = %d' % (cls_name, i)
  1330. i += 1
  1331. else:
  1332. setattr(rop, name, i)
  1333. opclasses.append(None)
  1334. oparity.append(-1)
  1335. opwithdescr.append(False)
  1336. optypes.append(' ')
  1337. if debug_print:
  1338. print '%30s = %d' % (name, i)
  1339. i += 1
  1340. # for optimizeopt/pure.py's getrecentops()
  1341. assert (rop.INT_ADD_OVF - rop._OVF_FIRST ==
  1342. rop.INT_ADD - rop._ALWAYS_PURE_FIRST)
  1343. assert (rop.INT_SUB_OVF - rop._OVF_FIRST ==
  1344. rop.INT_SUB - rop._ALWAYS_PURE_FIRST)
  1345. assert (rop.INT_MUL_OVF - rop._OVF_FIRST ==
  1346. rop.INT_MUL - rop._ALWAYS_PURE_FIRST)
  1347. def get_base_class(mixins, base):
  1348. try:
  1349. return get_base_class.cache[(base,) + mixins]
  1350. except KeyError:
  1351. arity_name = mixins[0].__name__[:-2] # remove the trailing "Op"
  1352. name = arity_name + base.__name__ # something like BinaryPlainResOp
  1353. bases = mixins + (base,)
  1354. cls = type(name, bases, {})
  1355. get_base_class.cache[(base,) + mixins] = cls
  1356. return cls
  1357. get_base_class.cache = {}
  1358. def create_class_for_op(name, opnum, arity, withdescr, result_type):
  1359. arity2mixin = {
  1360. 0: NullaryOp,
  1361. 1: UnaryOp,
  1362. 2: BinaryOp,
  1363. 3: TernaryOp
  1364. }
  1365. is_guard = name.startswith('GUARD')
  1366. if name.startswith('VEC'):
  1367. if name.startswith('VEC_GUARD'):
  1368. baseclass = VectorGuardOp
  1369. else:
  1370. baseclass = VectorOp
  1371. elif is_guard:
  1372. assert withdescr
  1373. baseclass = GuardResOp
  1374. elif withdescr:
  1375. baseclass = ResOpWithDescr
  1376. else:
  1377. baseclass = PlainResOp
  1378. mixins = [arity2mixin.get(arity, N_aryOp)]
  1379. if name in _cast_ops:
  1380. if "INT_SIGNEXT" in name:
  1381. mixins.append(SignExtOp)
  1382. mixins.append(CastOp)
  1383. cls_name = '%s_OP' % name
  1384. bases = (get_base_class(tuple(mixins), baseclass),)
  1385. dic = {'opnum': opnum}
  1386. res = type(cls_name, bases, dic)
  1387. if result_type == 'n':
  1388. result_type = 'v' # why?
  1389. res.type = result_type
  1390. return res
  1391. setup(__name__ == '__main__') # print out the table when run directly
  1392. del _oplist
  1393. _opboolinverse = {
  1394. rop.INT_EQ: rop.INT_NE,
  1395. rop.INT_NE: rop.INT_EQ,
  1396. rop.INT_LT: rop.INT_GE,
  1397. rop.INT_GE: rop.INT_LT,
  1398. rop.INT_GT: rop.INT_LE,
  1399. rop.INT_LE: rop.INT_GT,
  1400. rop.UINT_LT: rop.UINT_GE,
  1401. rop.UINT_GE: rop.UINT_LT,
  1402. rop.UINT_GT: rop.UINT_LE,
  1403. rop.UINT_LE: rop.UINT_GT,
  1404. rop.FLOAT_EQ: rop.FLOAT_NE,
  1405. rop.FLOAT_NE: rop.FLOAT_EQ,
  1406. rop.FLOAT_LT: rop.FLOAT_GE,
  1407. rop.FLOAT_GE: rop.FLOAT_LT,
  1408. rop.FLOAT_GT: rop.FLOAT_LE,
  1409. rop.FLOAT_LE: rop.FLOAT_GT,
  1410. rop.PTR_EQ: rop.PTR_NE,
  1411. rop.PTR_NE: rop.PTR_EQ,
  1412. }
  1413. _opboolreflex = {
  1414. rop.INT_EQ: rop.INT_EQ,
  1415. rop.INT_NE: rop.INT_NE,
  1416. rop.INT_LT: rop.INT_GT,
  1417. rop.INT_GE: rop.INT_LE,
  1418. rop.INT_GT: rop.INT_LT,
  1419. rop.INT_LE: rop.INT_GE,
  1420. rop.UINT_LT: rop.UINT_GT,
  1421. rop.UINT_GE: rop.UINT_LE,
  1422. rop.UINT_GT: rop.UINT_LT,
  1423. rop.UINT_LE: rop.UINT_GE,
  1424. rop.FLOAT_EQ: rop.FLOAT_EQ,
  1425. rop.FLOAT_NE: rop.FLOAT_NE,
  1426. rop.FLOAT_LT: rop.FLOAT_GT,
  1427. rop.FLOAT_GE: rop.FLOAT_LE,
  1428. rop.FLOAT_GT: rop.FLOAT_LT,
  1429. rop.FLOAT_LE: rop.FLOAT_GE,
  1430. rop.PTR_EQ: rop.PTR_EQ,
  1431. rop.PTR_NE: rop.PTR_NE,
  1432. }
  1433. _opvector = {
  1434. rop.RAW_LOAD_I: rop.VEC_RAW_LOAD_I,
  1435. rop.RAW_LOAD_F: rop.VEC_RAW_LOAD_F,
  1436. rop.GETARRAYITEM_RAW_I: rop.VEC_GETARRAYITEM_RAW_I,
  1437. rop.GETARRAYITEM_RAW_F: rop.VEC_GETARRAYITEM_RAW_F,
  1438. rop.GETARRAYITEM_GC_I: rop.VEC_GETARRAYITEM_GC_I,
  1439. rop.GETARRAYITEM_GC_F: rop.VEC_GETARRAYITEM_GC_F,
  1440. # note that there is no _PURE operation for vector operations.
  1441. # reason: currently we do not care if it is pure or not!
  1442. rop.GETARRAYITEM_GC_PURE_I: rop.VEC_GETARRAYITEM_GC_I,
  1443. rop.GETARRAYITEM_GC_PURE_F: rop.VEC_GETARRAYITEM_GC_F,
  1444. rop.RAW_STORE: rop.VEC_RAW_STORE,
  1445. rop.SETARRAYITEM_RAW: rop.VEC_SETARRAYITEM_RAW,
  1446. rop.SETARRAYITEM_GC: rop.VEC_SETARRAYITEM_GC,
  1447. rop.INT_ADD: rop.VEC_INT_ADD,
  1448. rop.INT_SUB: rop.VEC_INT_SUB,
  1449. rop.INT_MUL: rop.VEC_INT_MUL,
  1450. rop.INT_AND: rop.VEC_INT_AND,
  1451. rop.INT_OR: rop.VEC_INT_OR,
  1452. rop.INT_XOR: rop.VEC_INT_XOR,
  1453. rop.FLOAT_ADD: rop.VEC_FLOAT_ADD,
  1454. rop.FLOAT_SUB: rop.VEC_FLOAT_SUB,
  1455. rop.FLOAT_MUL: rop.VEC_FLOAT_MUL,
  1456. rop.FLOAT_TRUEDIV: rop.VEC_FLOAT_TRUEDIV,
  1457. rop.FLOAT_ABS: rop.VEC_FLOAT_ABS,
  1458. rop.FLOAT_NEG: rop.VEC_FLOAT_NEG,
  1459. rop.FLOAT_EQ: rop.VEC_FLOAT_EQ,
  1460. rop.FLOAT_NE: rop.VEC_FLOAT_NE,
  1461. rop.INT_IS_TRUE: rop.VEC_INT_IS_TRUE,
  1462. rop.INT_EQ: rop.VEC_INT_EQ,
  1463. rop.INT_NE: rop.VEC_INT_NE,
  1464. # casts
  1465. rop.INT_SIGNEXT: rop.VEC_INT_SIGNEXT,
  1466. rop.CAST_FLOAT_TO_SINGLEFLOAT: rop.VEC_CAST_FLOAT_TO_SINGLEFLOAT,
  1467. rop.CAST_SINGLEFLOAT_TO_FLOAT: rop.VEC_CAST_SINGLEFLOAT_TO_FLOAT,
  1468. rop.CAST_INT_TO_FLOAT: rop.VEC_CAST_INT_TO_FLOAT,
  1469. rop.CAST_FLOAT_TO_INT: rop.VEC_CAST_FLOAT_TO_INT,
  1470. # guard
  1471. rop.GUARD_TRUE: rop.VEC_GUARD_TRUE,
  1472. rop.GUARD_FALSE: rop.VEC_GUARD_FALSE,
  1473. }
  1474. def setup2():
  1475. for cls in opclasses:
  1476. if cls is None:
  1477. continue
  1478. opnum = cls.opnum
  1479. name = opname[opnum]
  1480. if opnum in _opboolreflex:
  1481. cls.boolreflex = _opboolreflex[opnum]
  1482. if opnum in _opboolinverse:
  1483. cls.boolinverse = _opboolinverse[opnum]
  1484. if opnum in _opvector:
  1485. cls.vector = _opvector[opnum]
  1486. if name in _cast_ops:
  1487. cls.cls_casts = _cast_ops[name]
  1488. if name.startswith('VEC'):
  1489. cls.vector = -2
  1490. setup2()
  1491. del _opboolinverse
  1492. del _opboolreflex
  1493. del _opvector
  1494. del _cast_ops
  1495. def get_deep_immutable_oplist(operations):
  1496. """
  1497. When not we_are_translated(), turns ``operations`` into a frozenlist and
  1498. monkey-patch its items to make sure they are not mutated.
  1499. When we_are_translated(), do nothing and just return the old list.
  1500. """
  1501. from rpython.tool.frozenlist import frozenlist
  1502. if we_are_translated():
  1503. return operations
  1504. #
  1505. def setarg(*args):
  1506. assert False, "operations cannot change at this point"
  1507. def setdescr(*args):
  1508. assert False, "operations cannot change at this point"
  1509. newops = frozenlist(operations)
  1510. for op in newops:
  1511. op.setarg = setarg
  1512. op.setdescr = setdescr
  1513. return newops
  1514. OpHelpers = rop