PageRenderTime 40ms CodeModel.GetById 8ms RepoModel.GetById 0ms app.codeStats 1ms

/pypy/rpython/lltypesystem/opimpl.py

https://bitbucket.org/pypy/pypy/
Python | 618 lines | 509 code | 91 blank | 18 comment | 59 complexity | 490a479734085b241135915d8628f52c MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import sys
  2. import math
  3. from pypy.tool.sourcetools import func_with_new_name
  4. from pypy.rpython.lltypesystem import lltype, llmemory
  5. from pypy.rpython.lltypesystem.lloperation import opimpls
  6. from pypy.rlib import debug
  7. # ____________________________________________________________
  8. # Implementation of the 'canfold' operations
  9. # implementations of ops from flow.operation
  10. ops_returning_a_bool = {'gt': True, 'ge': True,
  11. 'lt': True, 'le': True,
  12. 'eq': True, 'ne': True,
  13. 'is_true': True}
  14. ops_unary = {'is_true': True, 'neg': True, 'abs': True, 'invert': True}
  15. # global synonyms for some types
  16. from pypy.rlib.rarithmetic import intmask
  17. from pypy.rlib.rarithmetic import r_int, r_uint, r_longlong, r_ulonglong
  18. from pypy.rpython.lltypesystem.llmemory import AddressAsInt
  19. if r_longlong is r_int:
  20. r_longlong_arg = (r_longlong, int)
  21. r_longlong_result = int
  22. else:
  23. r_longlong_arg = r_longlong
  24. r_longlong_result = r_longlong
  25. argtype_by_name = {
  26. 'int': int,
  27. 'float': float,
  28. 'uint': r_uint,
  29. 'llong': r_longlong_arg,
  30. 'ullong': r_ulonglong,
  31. }
  32. def no_op(x):
  33. return x
  34. def get_primitive_op_src(fullopname):
  35. assert '_' in fullopname, "%s: not a primitive op" % (fullopname,)
  36. typname, opname = fullopname.split('_', 1)
  37. if opname not in opimpls and (opname + '_') in opimpls:
  38. func = opimpls[opname + '_'] # or_, and_
  39. else:
  40. assert opname in opimpls, "%s: not a primitive op" % (fullopname,)
  41. func = opimpls[opname]
  42. if typname == 'char':
  43. # char_lt, char_eq, ...
  44. def op_function(x, y):
  45. if not isinstance(x, str) or len(x) != 1:
  46. raise TypeError("%r arg must be a char, got %r instead" % (
  47. fullopname, typname, type(x).__name__))
  48. if not isinstance(y, str) or len(y) != 1:
  49. raise TypeError("%r arg must be a char, got %r instead" % (
  50. fullopname, typname, type(y).__name__))
  51. return func(x, y)
  52. else:
  53. if typname == 'int' and opname not in ops_returning_a_bool:
  54. adjust_result = intmask
  55. else:
  56. adjust_result = no_op
  57. assert typname in argtype_by_name, "%s: not a primitive op" % (
  58. fullopname,)
  59. argtype = argtype_by_name[typname]
  60. if opname in ops_unary:
  61. def op_function(x):
  62. if not isinstance(x, argtype):
  63. raise TypeError("%r arg must be %s, got %r instead" % (
  64. fullopname, typname, type(x).__name__))
  65. return adjust_result(func(x))
  66. else:
  67. def op_function(x, y):
  68. if not isinstance(x, argtype):
  69. if not (isinstance(x, AddressAsInt) and argtype is int):
  70. raise TypeError("%r arg 1 must be %s, got %r instead"% (
  71. fullopname, typname, type(x).__name__))
  72. if not isinstance(y, argtype):
  73. if not (isinstance(y, AddressAsInt) and argtype is int):
  74. raise TypeError("%r arg 2 must be %s, got %r instead"% (
  75. fullopname, typname, type(y).__name__))
  76. return adjust_result(func(x, y))
  77. return func_with_new_name(op_function, 'op_' + fullopname)
  78. def checkptr(ptr):
  79. if not isinstance(lltype.typeOf(ptr), lltype.Ptr):
  80. raise TypeError("arg must be a pointer, got %r instead" % (
  81. lltype.typeOf(ptr),))
  82. def checkadr(adr):
  83. if lltype.typeOf(adr) is not llmemory.Address:
  84. raise TypeError("arg must be an address, got %r instead" % (
  85. lltype.typeOf(adr),))
  86. def op_ptr_eq(ptr1, ptr2):
  87. checkptr(ptr1)
  88. checkptr(ptr2)
  89. return ptr1 == ptr2
  90. def op_ptr_ne(ptr1, ptr2):
  91. checkptr(ptr1)
  92. checkptr(ptr2)
  93. return ptr1 != ptr2
  94. def op_ptr_nonzero(ptr1):
  95. checkptr(ptr1)
  96. return bool(ptr1)
  97. def op_ptr_iszero(ptr1):
  98. checkptr(ptr1)
  99. return not bool(ptr1)
  100. def op_getsubstruct(obj, field):
  101. checkptr(obj)
  102. # check the difference between op_getfield and op_getsubstruct:
  103. assert isinstance(getattr(lltype.typeOf(obj).TO, field),
  104. lltype.ContainerType)
  105. return getattr(obj, field)
  106. def op_getarraysubstruct(array, index):
  107. checkptr(array)
  108. result = array[index]
  109. return result
  110. # the diff between op_getarrayitem and op_getarraysubstruct
  111. # is the same as between op_getfield and op_getsubstruct
  112. def op_getinteriorarraysize(obj, *offsets):
  113. checkptr(obj)
  114. ob = obj
  115. for o in offsets:
  116. if isinstance(o, str):
  117. ob = getattr(ob, o)
  118. else:
  119. ob = ob[o]
  120. return len(ob)
  121. def op_getinteriorfield(obj, *offsets):
  122. checkptr(obj)
  123. ob = obj
  124. for o in offsets:
  125. innermostcontainer = ob
  126. if isinstance(o, str):
  127. ob = getattr(ob, o)
  128. else:
  129. ob = ob[o]
  130. # we can constant-fold this if the innermost structure from which we
  131. # read the final field is immutable.
  132. T = lltype.typeOf(innermostcontainer).TO
  133. if not T._immutable_field(offsets[-1]):
  134. raise TypeError("cannot fold getinteriorfield on mutable struct")
  135. assert not isinstance(ob, lltype._interior_ptr)
  136. return ob
  137. def op_getarraysize(array):
  138. checkptr(array)
  139. return len(array)
  140. def op_direct_fieldptr(obj, field):
  141. checkptr(obj)
  142. assert isinstance(field, str)
  143. return lltype.direct_fieldptr(obj, field)
  144. def op_direct_arrayitems(obj):
  145. checkptr(obj)
  146. return lltype.direct_arrayitems(obj)
  147. def op_direct_ptradd(obj, index):
  148. checkptr(obj)
  149. assert isinstance(index, int)
  150. return lltype.direct_ptradd(obj, index)
  151. def op_bool_not(b):
  152. assert type(b) is bool
  153. return not b
  154. def op_int_add(x, y):
  155. if not isinstance(x, (int, llmemory.AddressOffset)):
  156. from pypy.rpython.lltypesystem import llgroup
  157. assert isinstance(x, llgroup.CombinedSymbolic)
  158. assert isinstance(y, (int, llmemory.AddressOffset))
  159. return intmask(x + y)
  160. def op_int_sub(x, y):
  161. if not isinstance(x, int):
  162. from pypy.rpython.lltypesystem import llgroup
  163. assert isinstance(x, llgroup.CombinedSymbolic)
  164. assert isinstance(y, int)
  165. return intmask(x - y)
  166. def op_int_ge(x, y):
  167. # special case for 'AddressOffset >= 0'
  168. assert isinstance(x, (int, llmemory.AddressOffset))
  169. assert isinstance(y, int)
  170. return x >= y
  171. def op_int_lt(x, y):
  172. # special case for 'AddressOffset < 0'
  173. assert isinstance(x, (int, llmemory.AddressOffset))
  174. assert isinstance(y, int)
  175. return x < y
  176. def op_int_between(a, b, c):
  177. assert lltype.typeOf(a) is lltype.Signed
  178. assert lltype.typeOf(b) is lltype.Signed
  179. assert lltype.typeOf(c) is lltype.Signed
  180. return a <= b < c
  181. def op_int_and(x, y):
  182. if not isinstance(x, int):
  183. from pypy.rpython.lltypesystem import llgroup
  184. assert isinstance(x, llgroup.CombinedSymbolic)
  185. assert isinstance(y, int)
  186. return x & y
  187. def op_int_or(x, y):
  188. if not isinstance(x, int):
  189. from pypy.rpython.lltypesystem import llgroup
  190. assert isinstance(x, llgroup.CombinedSymbolic)
  191. assert isinstance(y, int)
  192. return x | y
  193. def op_int_xor(x, y):
  194. # used in computing hashes
  195. if isinstance(x, AddressAsInt): x = llmemory.cast_adr_to_int(x.adr)
  196. if isinstance(y, AddressAsInt): y = llmemory.cast_adr_to_int(y.adr)
  197. assert isinstance(x, int)
  198. assert isinstance(y, int)
  199. return x ^ y
  200. def op_int_mul(x, y):
  201. assert isinstance(x, (int, llmemory.AddressOffset))
  202. assert isinstance(y, (int, llmemory.AddressOffset))
  203. return intmask(x * y)
  204. def op_int_rshift(x, y):
  205. if not isinstance(x, int):
  206. from pypy.rpython.lltypesystem import llgroup
  207. assert isinstance(x, llgroup.CombinedSymbolic)
  208. assert isinstance(y, int)
  209. return x >> y
  210. def op_int_floordiv(x, y):
  211. assert isinstance(x, (int, llmemory.AddressOffset))
  212. assert isinstance(y, (int, llmemory.AddressOffset))
  213. r = x//y
  214. if x^y < 0 and x%y != 0:
  215. r += 1
  216. return r
  217. def op_int_mod(x, y):
  218. assert isinstance(x, (int, llmemory.AddressOffset))
  219. assert isinstance(y, (int, llmemory.AddressOffset))
  220. r = x%y
  221. if x^y < 0 and x%y != 0:
  222. r -= y
  223. return r
  224. def op_llong_floordiv(x, y):
  225. assert isinstance(x, r_longlong_arg)
  226. assert isinstance(y, r_longlong_arg)
  227. r = x//y
  228. if x^y < 0 and x%y != 0:
  229. r += 1
  230. return r
  231. def op_llong_mod(x, y):
  232. assert isinstance(x, r_longlong_arg)
  233. assert isinstance(y, r_longlong_arg)
  234. r = x%y
  235. if x^y < 0 and x%y != 0:
  236. r -= y
  237. return r
  238. def op_uint_lshift(x, y):
  239. assert isinstance(x, r_uint)
  240. assert isinstance(y, int)
  241. return r_uint(x << y)
  242. def op_uint_rshift(x, y):
  243. assert isinstance(x, r_uint)
  244. assert isinstance(y, int)
  245. return r_uint(x >> y)
  246. def op_llong_lshift(x, y):
  247. assert isinstance(x, r_longlong_arg)
  248. assert isinstance(y, int)
  249. return r_longlong_result(x << y)
  250. def op_llong_rshift(x, y):
  251. assert isinstance(x, r_longlong_arg)
  252. assert isinstance(y, int)
  253. return r_longlong_result(x >> y)
  254. def op_ullong_lshift(x, y):
  255. assert isinstance(x, r_ulonglong)
  256. assert isinstance(y, int)
  257. return r_ulonglong(x << y)
  258. def op_ullong_rshift(x, y):
  259. assert isinstance(x, r_ulonglong)
  260. assert isinstance(y, int)
  261. return r_ulonglong(x >> y)
  262. def op_same_as(x):
  263. return x
  264. def op_cast_primitive(TYPE, value):
  265. assert isinstance(lltype.typeOf(value), lltype.Primitive)
  266. return lltype.cast_primitive(TYPE, value)
  267. op_cast_primitive.need_result_type = True
  268. def op_cast_int_to_float(i):
  269. assert type(i) is int
  270. return float(i)
  271. def op_cast_uint_to_float(u):
  272. assert type(u) is r_uint
  273. return float(u)
  274. def op_cast_longlong_to_float(i):
  275. assert isinstance(i, r_longlong_arg)
  276. # take first 31 bits
  277. li = float(int(i & r_longlong(0x7fffffff)))
  278. ui = float(int(i >> 31)) * float(0x80000000)
  279. return ui + li
  280. def op_cast_ulonglong_to_float(i):
  281. assert isinstance(i, r_ulonglong)
  282. # take first 32 bits
  283. li = float(int(i & r_ulonglong(0xffffffff)))
  284. ui = float(int(i >> 32)) * float(0x100000000)
  285. return ui + li
  286. def op_cast_int_to_char(b):
  287. assert type(b) is int
  288. return chr(b)
  289. def op_cast_bool_to_int(b):
  290. assert type(b) is bool
  291. return int(b)
  292. def op_cast_bool_to_uint(b):
  293. assert type(b) is bool
  294. return r_uint(int(b))
  295. def op_cast_bool_to_float(b):
  296. assert type(b) is bool
  297. return float(b)
  298. def op_cast_float_to_int(f):
  299. assert type(f) is float
  300. return intmask(int(f))
  301. def op_cast_float_to_uint(f):
  302. assert type(f) is float
  303. return r_uint(long(f))
  304. def op_cast_float_to_longlong(f):
  305. assert type(f) is float
  306. r = float(0x100000000)
  307. small = f / r
  308. high = int(small)
  309. truncated = int((small - high) * r)
  310. return r_longlong_result(high) * 0x100000000 + truncated
  311. def op_cast_float_to_ulonglong(f):
  312. assert type(f) is float
  313. return r_ulonglong(long(f))
  314. def op_cast_char_to_int(b):
  315. assert type(b) is str and len(b) == 1
  316. return ord(b)
  317. def op_cast_unichar_to_int(b):
  318. assert type(b) is unicode and len(b) == 1
  319. return ord(b)
  320. def op_cast_int_to_unichar(b):
  321. assert type(b) is int
  322. return unichr(b)
  323. def op_cast_int_to_uint(b):
  324. assert type(b) is int
  325. return r_uint(b)
  326. def op_cast_uint_to_int(b):
  327. assert type(b) is r_uint
  328. return intmask(b)
  329. def op_cast_int_to_longlong(b):
  330. assert type(b) is int
  331. return r_longlong_result(b)
  332. def op_truncate_longlong_to_int(b):
  333. assert isinstance(b, r_longlong_arg)
  334. return intmask(b)
  335. def op_cast_pointer(RESTYPE, obj):
  336. checkptr(obj)
  337. return lltype.cast_pointer(RESTYPE, obj)
  338. op_cast_pointer.need_result_type = True
  339. def op_cast_adr_to_ptr(TYPE, adr):
  340. checkadr(adr)
  341. return llmemory.cast_adr_to_ptr(adr, TYPE)
  342. op_cast_adr_to_ptr.need_result_type = True
  343. def op_cast_int_to_adr(int):
  344. return llmemory.cast_int_to_adr(int)
  345. ##def op_cast_int_to_adr(x):
  346. ## assert type(x) is int
  347. ## return llmemory.cast_int_to_adr(x)
  348. def op_unichar_eq(x, y):
  349. assert isinstance(x, unicode) and len(x) == 1
  350. assert isinstance(y, unicode) and len(y) == 1
  351. return x == y
  352. def op_unichar_ne(x, y):
  353. assert isinstance(x, unicode) and len(x) == 1
  354. assert isinstance(y, unicode) and len(y) == 1
  355. return x != y
  356. def op_adr_lt(addr1, addr2):
  357. checkadr(addr1)
  358. checkadr(addr2)
  359. return addr1 < addr2
  360. def op_adr_le(addr1, addr2):
  361. checkadr(addr1)
  362. checkadr(addr2)
  363. return addr1 <= addr2
  364. def op_adr_eq(addr1, addr2):
  365. checkadr(addr1)
  366. checkadr(addr2)
  367. return addr1 == addr2
  368. def op_adr_ne(addr1, addr2):
  369. checkadr(addr1)
  370. checkadr(addr2)
  371. return addr1 != addr2
  372. def op_adr_gt(addr1, addr2):
  373. checkadr(addr1)
  374. checkadr(addr2)
  375. return addr1 > addr2
  376. def op_adr_ge(addr1, addr2):
  377. checkadr(addr1)
  378. checkadr(addr2)
  379. return addr1 >= addr2
  380. def op_adr_add(addr, offset):
  381. checkadr(addr)
  382. assert lltype.typeOf(offset) is lltype.Signed
  383. return addr + offset
  384. def op_adr_sub(addr, offset):
  385. checkadr(addr)
  386. assert lltype.typeOf(offset) is lltype.Signed
  387. return addr - offset
  388. def op_adr_delta(addr1, addr2):
  389. checkadr(addr1)
  390. checkadr(addr2)
  391. return addr1 - addr2
  392. def op_gc_writebarrier_before_copy(source, dest,
  393. source_start, dest_start, length):
  394. A = lltype.typeOf(source)
  395. assert A == lltype.typeOf(dest)
  396. assert isinstance(A.TO, lltype.GcArray)
  397. assert isinstance(A.TO.OF, lltype.Ptr)
  398. assert A.TO.OF.TO._gckind == 'gc'
  399. assert type(source_start) is int
  400. assert type(dest_start) is int
  401. assert type(length) is int
  402. return True
  403. def op_getfield(p, name):
  404. checkptr(p)
  405. TYPE = lltype.typeOf(p).TO
  406. if not TYPE._immutable_field(name):
  407. raise TypeError("cannot fold getfield on mutable struct")
  408. return getattr(p, name)
  409. def op_getarrayitem(p, index):
  410. checkptr(p)
  411. ARRAY = lltype.typeOf(p).TO
  412. if not ARRAY._immutable_field(index):
  413. raise TypeError("cannot fold getarrayitem on mutable array")
  414. return p[index]
  415. def _normalize(x):
  416. if not isinstance(x, str):
  417. TYPE = lltype.typeOf(x)
  418. if (isinstance(TYPE, lltype.Ptr) and TYPE.TO._name == 'rpy_string'
  419. or getattr(TYPE, '_name', '') == 'String'): # ootype
  420. from pypy.rpython.annlowlevel import hlstr
  421. return hlstr(x)
  422. return x
  423. def op_debug_print(*args):
  424. debug.debug_print(*map(_normalize, args))
  425. def op_debug_start(category):
  426. debug.debug_start(_normalize(category))
  427. def op_debug_stop(category):
  428. debug.debug_stop(_normalize(category))
  429. def op_debug_offset():
  430. return debug.debug_offset()
  431. def op_debug_flush():
  432. pass
  433. def op_have_debug_prints():
  434. return debug.have_debug_prints()
  435. def op_debug_nonnull_pointer(x):
  436. assert x
  437. def op_gc_stack_bottom():
  438. pass # marker for trackgcroot.py
  439. def op_jit_force_virtualizable(*args):
  440. pass
  441. def op_jit_force_virtual(x):
  442. return x
  443. def op_jit_is_virtual(x):
  444. return False
  445. def op_jit_force_quasi_immutable(*args):
  446. pass
  447. def op_jit_record_known_class(x, y):
  448. pass
  449. def op_get_group_member(TYPE, grpptr, memberoffset):
  450. from pypy.rpython.lltypesystem import llgroup
  451. assert isinstance(memberoffset, llgroup.GroupMemberOffset)
  452. member = memberoffset._get_group_member(grpptr)
  453. return lltype.cast_pointer(TYPE, member)
  454. op_get_group_member.need_result_type = True
  455. def op_get_next_group_member(TYPE, grpptr, memberoffset, skipoffset):
  456. from pypy.rpython.lltypesystem import llgroup
  457. assert isinstance(memberoffset, llgroup.GroupMemberOffset)
  458. member = memberoffset._get_next_group_member(grpptr, skipoffset)
  459. return lltype.cast_pointer(TYPE, member)
  460. op_get_next_group_member.need_result_type = True
  461. def op_is_group_member_nonzero(memberoffset):
  462. from pypy.rpython.lltypesystem import llgroup
  463. if isinstance(memberoffset, llgroup.GroupMemberOffset):
  464. return memberoffset.index != 0
  465. else:
  466. assert isinstance(memberoffset, int)
  467. return memberoffset != 0
  468. def op_extract_ushort(combinedoffset):
  469. from pypy.rpython.lltypesystem import llgroup
  470. assert isinstance(combinedoffset, llgroup.CombinedSymbolic)
  471. return combinedoffset.lowpart
  472. def op_combine_ushort(ushort, rest):
  473. from pypy.rpython.lltypesystem import llgroup
  474. return llgroup.CombinedSymbolic(ushort, rest)
  475. def op_gc_gettypeptr_group(TYPE, obj, grpptr, skipoffset, vtableinfo):
  476. HDR = vtableinfo[0]
  477. size_gc_header = vtableinfo[1]
  478. fieldname = vtableinfo[2]
  479. objaddr = llmemory.cast_ptr_to_adr(obj)
  480. hdraddr = objaddr - size_gc_header
  481. hdr = llmemory.cast_adr_to_ptr(hdraddr, lltype.Ptr(HDR))
  482. typeid = getattr(hdr, fieldname)
  483. if lltype.typeOf(typeid) == lltype.Signed:
  484. typeid = op_extract_ushort(typeid)
  485. return op_get_next_group_member(TYPE, grpptr, typeid, skipoffset)
  486. op_gc_gettypeptr_group.need_result_type = True
  487. def op_get_member_index(memberoffset):
  488. raise NotImplementedError
  489. def op_gc_assume_young_pointers(addr):
  490. pass
  491. def op_shrink_array(array, smallersize):
  492. return False
  493. def op_ll_read_timestamp():
  494. from pypy.rlib.rtimer import read_timestamp
  495. return read_timestamp()
  496. # ____________________________________________________________
  497. def get_op_impl(opname):
  498. # get the op_xxx() function from the globals above
  499. try:
  500. return globals()['op_' + opname]
  501. except KeyError:
  502. return get_primitive_op_src(opname)