PageRenderTime 44ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/jit/backend/llsupport/descr.py

https://bitbucket.org/pypy/pypy/
Python | 702 lines | 654 code | 37 blank | 11 comment | 50 complexity | 65b69ce5cdf48ef8b0bd26559f4a3711 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import py
  2. from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
  3. from rpython.rtyper.lltypesystem.lloperation import llop
  4. from rpython.jit.backend.llsupport import symbolic, support
  5. from rpython.jit.metainterp.history import AbstractDescr, getkind, FLOAT, INT
  6. from rpython.jit.metainterp import history
  7. from rpython.jit.codewriter import heaptracker, longlong
  8. from rpython.jit.codewriter.longlong import is_longlong
  9. from rpython.jit.metainterp.optimizeopt import intbounds
  10. from rpython.rtyper import rclass
  11. class GcCache(object):
  12. def __init__(self, translate_support_code, rtyper=None):
  13. self.translate_support_code = translate_support_code
  14. self.rtyper = rtyper
  15. self._cache_size = {}
  16. self._cache_field = {}
  17. self._cache_array = {}
  18. self._cache_arraylen = {}
  19. self._cache_call = {}
  20. self._cache_interiorfield = {}
  21. def setup_descrs(self):
  22. all_descrs = []
  23. for k, v in self._cache_size.iteritems():
  24. v.descr_index = len(all_descrs)
  25. all_descrs.append(v)
  26. for k, v in self._cache_field.iteritems():
  27. for k1, v1 in v.iteritems():
  28. v1.descr_index = len(all_descrs)
  29. all_descrs.append(v1)
  30. for k, v in self._cache_array.iteritems():
  31. v.descr_index = len(all_descrs)
  32. all_descrs.append(v)
  33. for k, v in self._cache_arraylen.iteritems():
  34. v.descr_index = len(all_descrs)
  35. all_descrs.append(v)
  36. for k, v in self._cache_call.iteritems():
  37. v.descr_index = len(all_descrs)
  38. all_descrs.append(v)
  39. for k, v in self._cache_interiorfield.iteritems():
  40. v.descr_index = len(all_descrs)
  41. all_descrs.append(v)
  42. assert len(all_descrs) < 2**15
  43. return all_descrs
  44. def init_size_descr(self, STRUCT, sizedescr):
  45. pass
  46. def init_array_descr(self, ARRAY, arraydescr):
  47. assert (isinstance(ARRAY, lltype.GcArray) or
  48. isinstance(ARRAY, lltype.GcStruct) and ARRAY._arrayfld)
  49. # ____________________________________________________________
  50. # SizeDescrs
  51. class SizeDescr(AbstractDescr):
  52. size = 0 # help translation
  53. tid = llop.combine_ushort(lltype.Signed, 0, 0)
  54. vtable = lltype.nullptr(rclass.OBJECT_VTABLE)
  55. immutable_flag = False
  56. def __init__(self, size, gc_fielddescrs=None, all_fielddescrs=None,
  57. vtable=lltype.nullptr(rclass.OBJECT_VTABLE),
  58. immutable_flag=False):
  59. assert lltype.typeOf(vtable) == lltype.Ptr(rclass.OBJECT_VTABLE)
  60. self.size = size
  61. self.gc_fielddescrs = gc_fielddescrs
  62. self.all_fielddescrs = all_fielddescrs
  63. self.vtable = vtable
  64. self.immutable_flag = immutable_flag
  65. def get_all_fielddescrs(self):
  66. return self.all_fielddescrs
  67. def repr_of_descr(self):
  68. return '<SizeDescr %s>' % self.size
  69. def is_object(self):
  70. return bool(self.vtable)
  71. def is_valid_class_for(self, struct):
  72. objptr = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct)
  73. cls = llmemory.cast_adr_to_ptr(
  74. heaptracker.int2adr(self.get_vtable()),
  75. lltype.Ptr(rclass.OBJECT_VTABLE))
  76. # this first comparison is necessary, since we want to make sure
  77. # that vtable for JitVirtualRef is the same without actually reading
  78. # fields
  79. return objptr.typeptr == cls or rclass.ll_isinstance(objptr, cls)
  80. def is_immutable(self):
  81. return self.immutable_flag
  82. def get_vtable(self):
  83. return heaptracker.adr2int(llmemory.cast_ptr_to_adr(self.vtable))
  84. def get_type_id(self):
  85. assert self.tid
  86. return self.tid
  87. def get_size_descr(gccache, STRUCT, vtable=lltype.nullptr(rclass.OBJECT_VTABLE)):
  88. cache = gccache._cache_size
  89. assert not isinstance(vtable, bool)
  90. try:
  91. return cache[STRUCT]
  92. except KeyError:
  93. size = symbolic.get_size(STRUCT, gccache.translate_support_code)
  94. immutable_flag = heaptracker.is_immutable_struct(STRUCT)
  95. if vtable:
  96. assert heaptracker.has_gcstruct_a_vtable(STRUCT)
  97. else:
  98. assert not heaptracker.has_gcstruct_a_vtable(STRUCT)
  99. sizedescr = SizeDescr(size, vtable=vtable,
  100. immutable_flag=immutable_flag)
  101. gccache.init_size_descr(STRUCT, sizedescr)
  102. cache[STRUCT] = sizedescr
  103. # XXX do we really need gc_fielddescrs if we also have
  104. # all_fielddescrs and can ask is_pointer_field() on them?
  105. gc_fielddescrs = heaptracker.gc_fielddescrs(gccache, STRUCT)
  106. sizedescr.gc_fielddescrs = gc_fielddescrs
  107. all_fielddescrs = heaptracker.all_fielddescrs(gccache, STRUCT)
  108. sizedescr.all_fielddescrs = all_fielddescrs
  109. return sizedescr
  110. # ____________________________________________________________
  111. # FieldDescrs
  112. FLAG_POINTER = 'P'
  113. FLAG_FLOAT = 'F'
  114. FLAG_UNSIGNED = 'U'
  115. FLAG_SIGNED = 'S'
  116. FLAG_STRUCT = 'X'
  117. FLAG_VOID = 'V'
  118. class ArrayOrFieldDescr(AbstractDescr):
  119. vinfo = None
  120. def get_vinfo(self):
  121. return self.vinfo
  122. class FieldDescr(ArrayOrFieldDescr):
  123. name = ''
  124. offset = 0 # help translation
  125. field_size = 0
  126. flag = '\x00'
  127. def __init__(self, name, offset, field_size, flag, index_in_parent=0,
  128. is_pure=False):
  129. self.name = name
  130. self.offset = offset
  131. self.field_size = field_size
  132. self.flag = flag
  133. self.index = index_in_parent
  134. self._is_pure = is_pure
  135. def is_always_pure(self):
  136. return self._is_pure
  137. def __repr__(self):
  138. return 'FieldDescr<%s>' % (self.name,)
  139. def assert_correct_type(self, struct):
  140. # similar to cpu.protect_speculative_field(), but works also
  141. # if supports_guard_gc_type is false (and is allowed to crash).
  142. if self.parent_descr.is_object():
  143. assert self.parent_descr.is_valid_class_for(struct)
  144. else:
  145. pass
  146. def is_pointer_field(self):
  147. return self.flag == FLAG_POINTER
  148. def is_float_field(self):
  149. return self.flag == FLAG_FLOAT
  150. def is_field_signed(self):
  151. return self.flag == FLAG_SIGNED
  152. def is_integer_bounded(self):
  153. return self.flag in (FLAG_SIGNED, FLAG_UNSIGNED) \
  154. and self.field_size < symbolic.WORD
  155. def get_integer_min(self):
  156. if self.flag == FLAG_UNSIGNED:
  157. return intbounds.get_integer_min(True, self.field_size)
  158. elif self.flag == FLAG_SIGNED:
  159. return intbounds.get_integer_min(False, self.field_size)
  160. assert False
  161. def get_integer_max(self):
  162. if self.flag == FLAG_UNSIGNED:
  163. return intbounds.get_integer_max(True, self.field_size)
  164. elif self.flag == FLAG_SIGNED:
  165. return intbounds.get_integer_max(False, self.field_size)
  166. assert False
  167. def sort_key(self):
  168. return self.offset
  169. def repr_of_descr(self):
  170. ispure = " pure" if self._is_pure else ""
  171. return '<Field%s %s %s%s>' % (self.flag, self.name, self.offset, ispure)
  172. def get_parent_descr(self):
  173. return self.parent_descr
  174. def get_index(self):
  175. return self.index
  176. def get_field_descr(gccache, STRUCT, fieldname):
  177. cache = gccache._cache_field
  178. try:
  179. return cache[STRUCT][fieldname]
  180. except KeyError:
  181. offset, size = symbolic.get_field_token(STRUCT, fieldname,
  182. gccache.translate_support_code)
  183. FIELDTYPE = getattr(STRUCT, fieldname)
  184. flag = get_type_flag(FIELDTYPE)
  185. name = '%s.%s' % (STRUCT._name, fieldname)
  186. index_in_parent = heaptracker.get_fielddescr_index_in(STRUCT, fieldname)
  187. is_pure = STRUCT._immutable_field(fieldname) != False
  188. fielddescr = FieldDescr(name, offset, size, flag, index_in_parent,
  189. is_pure)
  190. cachedict = cache.setdefault(STRUCT, {})
  191. cachedict[fieldname] = fielddescr
  192. if STRUCT is rclass.OBJECT:
  193. vtable = lltype.nullptr(rclass.OBJECT_VTABLE)
  194. else:
  195. vtable = heaptracker.get_vtable_for_gcstruct(gccache, STRUCT)
  196. fielddescr.parent_descr = get_size_descr(gccache, STRUCT, vtable)
  197. return fielddescr
  198. def get_type_flag(TYPE):
  199. if isinstance(TYPE, lltype.Ptr):
  200. if TYPE.TO._gckind == 'gc':
  201. return FLAG_POINTER
  202. else:
  203. return FLAG_UNSIGNED
  204. if isinstance(TYPE, lltype.Struct):
  205. return FLAG_STRUCT
  206. if TYPE is lltype.Float or is_longlong(TYPE):
  207. return FLAG_FLOAT
  208. if (TYPE is not lltype.Bool and isinstance(TYPE, lltype.Number) and
  209. rffi.cast(TYPE, -1) == -1):
  210. return FLAG_SIGNED
  211. return FLAG_UNSIGNED
  212. def get_field_arraylen_descr(gccache, ARRAY_OR_STRUCT):
  213. cache = gccache._cache_arraylen
  214. try:
  215. return cache[ARRAY_OR_STRUCT]
  216. except KeyError:
  217. tsc = gccache.translate_support_code
  218. (_, _, ofs) = symbolic.get_array_token(ARRAY_OR_STRUCT, tsc)
  219. size = symbolic.get_size(lltype.Signed, tsc)
  220. result = FieldDescr("len", ofs, size, get_type_flag(lltype.Signed))
  221. result.parent_descr = None
  222. cache[ARRAY_OR_STRUCT] = result
  223. return result
  224. # ____________________________________________________________
  225. # ArrayDescrs
  226. class ArrayDescr(ArrayOrFieldDescr):
  227. tid = 0
  228. basesize = 0 # workaround for the annotator
  229. itemsize = 0
  230. lendescr = None
  231. flag = '\x00'
  232. vinfo = None
  233. all_interiorfielddescrs = None
  234. concrete_type = '\x00'
  235. def __init__(self, basesize, itemsize, lendescr, flag, is_pure=False, concrete_type='\x00'):
  236. self.basesize = basesize # this includes +1 for STR
  237. self.itemsize = itemsize
  238. self.lendescr = lendescr # or None, if no length
  239. self.flag = flag
  240. self._is_pure = is_pure
  241. self.concrete_type = concrete_type
  242. def get_all_fielddescrs(self):
  243. return self.all_interiorfielddescrs
  244. def is_always_pure(self):
  245. return self._is_pure
  246. def getconcrete_type(self):
  247. return self.concrete_type
  248. def is_array_of_primitives(self):
  249. return self.flag == FLAG_FLOAT or \
  250. self.flag == FLAG_SIGNED or \
  251. self.flag == FLAG_UNSIGNED
  252. def is_array_of_pointers(self):
  253. return self.flag == FLAG_POINTER
  254. def is_array_of_floats(self):
  255. return self.flag == FLAG_FLOAT
  256. def is_item_signed(self):
  257. return self.flag == FLAG_SIGNED
  258. def get_item_size_in_bytes(self):
  259. return self.itemsize
  260. def is_array_of_structs(self):
  261. return self.flag == FLAG_STRUCT
  262. def is_item_integer_bounded(self):
  263. return self.flag in (FLAG_SIGNED, FLAG_UNSIGNED) \
  264. and self.itemsize < symbolic.WORD
  265. def get_item_integer_min(self):
  266. if self.flag == FLAG_UNSIGNED:
  267. return intbounds.get_integer_min(True, self.itemsize)
  268. elif self.flag == FLAG_SIGNED:
  269. return intbounds.get_integer_min(False, self.itemsize)
  270. assert False
  271. def get_item_integer_max(self):
  272. if self.flag == FLAG_UNSIGNED:
  273. return intbounds.get_integer_max(True, self.itemsize)
  274. elif self.flag == FLAG_SIGNED:
  275. return intbounds.get_integer_max(False, self.itemsize)
  276. assert False
  277. def get_type_id(self):
  278. assert self.tid
  279. return self.tid
  280. def repr_of_descr(self):
  281. return '<Array%s %s>' % (self.flag, self.itemsize)
  282. def get_array_descr(gccache, ARRAY_OR_STRUCT):
  283. cache = gccache._cache_array
  284. try:
  285. return cache[ARRAY_OR_STRUCT]
  286. except KeyError:
  287. tsc = gccache.translate_support_code
  288. basesize, itemsize, _ = symbolic.get_array_token(ARRAY_OR_STRUCT, tsc)
  289. if isinstance(ARRAY_OR_STRUCT, lltype.Array):
  290. ARRAY_INSIDE = ARRAY_OR_STRUCT
  291. else:
  292. ARRAY_INSIDE = ARRAY_OR_STRUCT._flds[ARRAY_OR_STRUCT._arrayfld]
  293. if ARRAY_INSIDE._hints.get('nolength', False):
  294. lendescr = None
  295. else:
  296. lendescr = get_field_arraylen_descr(gccache, ARRAY_OR_STRUCT)
  297. flag = get_type_flag(ARRAY_INSIDE.OF)
  298. is_pure = bool(ARRAY_INSIDE._immutable_field(None))
  299. arraydescr = ArrayDescr(basesize, itemsize, lendescr, flag, is_pure)
  300. if ARRAY_INSIDE.OF is lltype.SingleFloat or \
  301. ARRAY_INSIDE.OF is lltype.Float:
  302. # it would be better to set the flag as FLOAT_TYPE
  303. # for single float -> leads to problems
  304. arraydescr = ArrayDescr(basesize, itemsize, lendescr, flag, is_pure, concrete_type='f')
  305. cache[ARRAY_OR_STRUCT] = arraydescr
  306. if isinstance(ARRAY_INSIDE.OF, lltype.Struct):
  307. descrs = heaptracker.all_interiorfielddescrs(gccache,
  308. ARRAY_INSIDE, get_field_descr=get_interiorfield_descr)
  309. arraydescr.all_interiorfielddescrs = descrs
  310. if ARRAY_OR_STRUCT._gckind == 'gc':
  311. gccache.init_array_descr(ARRAY_OR_STRUCT, arraydescr)
  312. return arraydescr
  313. # ____________________________________________________________
  314. # InteriorFieldDescr
  315. class InteriorFieldDescr(AbstractDescr):
  316. arraydescr = ArrayDescr(0, 0, None, '\x00') # workaround for the annotator
  317. fielddescr = FieldDescr('', 0, 0, '\x00')
  318. def __init__(self, arraydescr, fielddescr):
  319. assert arraydescr.flag == FLAG_STRUCT
  320. self.arraydescr = arraydescr
  321. self.fielddescr = fielddescr
  322. def get_index(self):
  323. return self.fielddescr.get_index()
  324. def get_arraydescr(self):
  325. return self.arraydescr
  326. def get_field_descr(self):
  327. return self.fielddescr
  328. def sort_key(self):
  329. return self.fielddescr.sort_key()
  330. def is_pointer_field(self):
  331. return self.fielddescr.is_pointer_field()
  332. def is_float_field(self):
  333. return self.fielddescr.is_float_field()
  334. def is_integer_bounded(self):
  335. return self.fielddescr.is_integer_bounded()
  336. def get_integer_min(self):
  337. return self.fielddescr.get_integer_min()
  338. def get_integer_max(self):
  339. return self.fielddescr.get_integer_max()
  340. def repr_of_descr(self):
  341. return '<InteriorFieldDescr %s>' % self.fielddescr.repr_of_descr()
  342. def get_interiorfield_descr(gc_ll_descr, ARRAY, name, arrayfieldname=None):
  343. # can be used either with a GcArray of Structs, or with a GcStruct
  344. # containing an inlined GcArray of Structs (then arrayfieldname != None).
  345. cache = gc_ll_descr._cache_interiorfield
  346. try:
  347. return cache[(ARRAY, name, arrayfieldname)]
  348. except KeyError:
  349. arraydescr = get_array_descr(gc_ll_descr, ARRAY)
  350. if arrayfieldname is None:
  351. REALARRAY = ARRAY
  352. else:
  353. REALARRAY = getattr(ARRAY, arrayfieldname)
  354. fielddescr = get_field_descr(gc_ll_descr, REALARRAY.OF, name)
  355. descr = InteriorFieldDescr(arraydescr, fielddescr)
  356. cache[(ARRAY, name, arrayfieldname)] = descr
  357. return descr
  358. # ____________________________________________________________
  359. # CallDescrs
  360. def _missing_call_stub_i(func, args_i, args_r, args_f):
  361. return 0
  362. def _missing_call_stub_r(func, args_i, args_r, args_f):
  363. return lltype.nullptr(llmemory.GCREF.TO)
  364. def _missing_call_stub_f(func, args_i, args_r, args_f):
  365. return longlong.ZEROF
  366. class CallDescr(AbstractDescr):
  367. arg_classes = '' # <-- annotation hack
  368. result_type = '\x00'
  369. result_flag = '\x00'
  370. ffi_flags = 1
  371. def __init__(self, arg_classes, result_type, result_signed, result_size,
  372. extrainfo=None, ffi_flags=1):
  373. """
  374. 'arg_classes' is a string of characters, one per argument:
  375. 'i', 'r', 'f', 'L', 'S'
  376. 'result_type' is one character from the same list or 'v'
  377. 'result_signed' is a boolean True/False
  378. """
  379. self.arg_classes = arg_classes
  380. self.result_type = result_type
  381. self.result_size = result_size
  382. self.extrainfo = extrainfo
  383. self.ffi_flags = ffi_flags
  384. self.call_stub_i = _missing_call_stub_i
  385. self.call_stub_r = _missing_call_stub_r
  386. self.call_stub_f = _missing_call_stub_f
  387. # NB. the default ffi_flags is 1, meaning FUNCFLAG_CDECL, which
  388. # makes sense on Windows as it's the one for all the C functions
  389. # we are compiling together with the JIT. On non-Windows platforms
  390. # it is just ignored anyway.
  391. if result_type == 'v':
  392. result_flag = FLAG_VOID
  393. elif result_type == 'i':
  394. if result_signed:
  395. result_flag = FLAG_SIGNED
  396. else:
  397. result_flag = FLAG_UNSIGNED
  398. elif result_type == history.REF:
  399. result_flag = FLAG_POINTER
  400. elif result_type == history.FLOAT or result_type == 'L':
  401. result_flag = FLAG_FLOAT
  402. elif result_type == 'S':
  403. result_flag = FLAG_UNSIGNED
  404. else:
  405. raise NotImplementedError("result_type = '%s'" % (result_type,))
  406. self.result_flag = result_flag
  407. def __repr__(self):
  408. res = 'CallDescr(%s)' % (self.arg_classes,)
  409. extraeffect = getattr(self.extrainfo, 'extraeffect', None)
  410. if extraeffect is not None:
  411. res += ' EF=%r' % extraeffect
  412. oopspecindex = getattr(self.extrainfo, 'oopspecindex', 0)
  413. if oopspecindex:
  414. from rpython.jit.codewriter.effectinfo import EffectInfo
  415. for key, value in EffectInfo.__dict__.items():
  416. if key.startswith('OS_') and value == oopspecindex:
  417. break
  418. else:
  419. key = 'oopspecindex=%r' % oopspecindex
  420. res += ' ' + key
  421. return '<%s>' % res
  422. def get_extra_info(self):
  423. return self.extrainfo
  424. def get_ffi_flags(self):
  425. return self.ffi_flags
  426. def get_call_conv(self):
  427. from rpython.rlib.clibffi import get_call_conv
  428. return get_call_conv(self.ffi_flags, True)
  429. def get_arg_types(self):
  430. return self.arg_classes
  431. def get_result_type(self):
  432. return self.result_type
  433. def get_normalized_result_type(self):
  434. if self.result_type == 'S':
  435. return 'i'
  436. if self.result_type == 'L':
  437. return 'f'
  438. return self.result_type
  439. def get_result_size(self):
  440. return self.result_size
  441. def is_result_signed(self):
  442. return self.result_flag == FLAG_SIGNED
  443. def create_call_stub(self, rtyper, RESULT):
  444. from rpython.rlib.clibffi import FFI_DEFAULT_ABI
  445. assert self.get_call_conv() == FFI_DEFAULT_ABI, (
  446. "%r: create_call_stub() with a non-default call ABI" % (self,))
  447. def process(c):
  448. if c == 'L':
  449. assert longlong.supports_longlong
  450. c = 'f'
  451. elif c == 'f' and longlong.supports_longlong:
  452. return 'longlong.getrealfloat(%s)' % (process('L'),)
  453. elif c == 'S':
  454. return 'longlong.int2singlefloat(%s)' % (process('i'),)
  455. arg = 'args_%s[%d]' % (c, seen[c])
  456. seen[c] += 1
  457. return arg
  458. def TYPE(arg):
  459. if arg == 'i':
  460. return lltype.Signed
  461. elif arg == 'f':
  462. return lltype.Float
  463. elif arg == 'r':
  464. return llmemory.GCREF
  465. elif arg == 'v':
  466. return lltype.Void
  467. elif arg == 'L':
  468. return lltype.SignedLongLong
  469. elif arg == 'S':
  470. return lltype.SingleFloat
  471. else:
  472. raise AssertionError(arg)
  473. seen = {'i': 0, 'r': 0, 'f': 0}
  474. args = ", ".join([process(c) for c in self.arg_classes])
  475. result_type = self.get_result_type()
  476. if result_type == history.INT:
  477. result = 'rffi.cast(lltype.Signed, res)'
  478. category = 'i'
  479. elif result_type == history.REF:
  480. assert RESULT == llmemory.GCREF # should be ensured by the caller
  481. result = 'lltype.cast_opaque_ptr(llmemory.GCREF, res)'
  482. category = 'r'
  483. elif result_type == history.FLOAT:
  484. result = 'longlong.getfloatstorage(res)'
  485. category = 'f'
  486. elif result_type == 'L':
  487. result = 'rffi.cast(lltype.SignedLongLong, res)'
  488. category = 'f'
  489. elif result_type == history.VOID:
  490. result = '0'
  491. category = 'i'
  492. elif result_type == 'S':
  493. result = 'longlong.singlefloat2int(res)'
  494. category = 'i'
  495. else:
  496. assert 0
  497. source = py.code.Source("""
  498. def call_stub(func, args_i, args_r, args_f):
  499. fnptr = rffi.cast(lltype.Ptr(FUNC), func)
  500. res = support.maybe_on_top_of_llinterp(rtyper, fnptr)(%(args)s)
  501. return %(result)s
  502. """ % locals())
  503. ARGS = [TYPE(arg) for arg in self.arg_classes]
  504. FUNC = lltype.FuncType(ARGS, RESULT)
  505. d = globals().copy()
  506. d.update(locals())
  507. exec source.compile() in d
  508. call_stub = d['call_stub']
  509. # store the function into one of three attributes, to preserve
  510. # type-correctness of the return value
  511. setattr(self, 'call_stub_%s' % category, call_stub)
  512. def verify_types(self, args_i, args_r, args_f, return_type):
  513. assert self.result_type in return_type
  514. assert (self.arg_classes.count('i') +
  515. self.arg_classes.count('S')) == len(args_i or ())
  516. assert self.arg_classes.count('r') == len(args_r or ())
  517. assert (self.arg_classes.count('f') +
  518. self.arg_classes.count('L')) == len(args_f or ())
  519. def repr_of_descr(self):
  520. res = 'Call%s %d' % (self.result_type, self.result_size)
  521. if self.arg_classes:
  522. res += ' ' + self.arg_classes
  523. if self.extrainfo:
  524. res += ' EF=%d' % self.extrainfo.extraeffect
  525. oopspecindex = self.extrainfo.oopspecindex
  526. if oopspecindex:
  527. res += ' OS=%d' % oopspecindex
  528. return '<%s>' % res
  529. def map_type_to_argclass(ARG, accept_void=False):
  530. kind = getkind(ARG)
  531. if kind == 'int':
  532. if ARG is lltype.SingleFloat: return 'S'
  533. else: return 'i'
  534. elif kind == 'ref': return 'r'
  535. elif kind == 'float':
  536. if is_longlong(ARG): return 'L'
  537. else: return 'f'
  538. elif kind == 'void':
  539. if accept_void: return 'v'
  540. raise NotImplementedError('ARG = %r' % (ARG,))
  541. def get_call_descr(gccache, ARGS, RESULT, extrainfo=None):
  542. arg_classes = map(map_type_to_argclass, ARGS)
  543. arg_classes = ''.join(arg_classes)
  544. result_type = map_type_to_argclass(RESULT, accept_void=True)
  545. RESULT_ERASED = RESULT
  546. if RESULT is lltype.Void:
  547. result_size = 0
  548. result_signed = False
  549. else:
  550. if isinstance(RESULT, lltype.Ptr):
  551. # avoid too many CallDescrs
  552. if result_type == 'r':
  553. RESULT_ERASED = llmemory.GCREF
  554. else:
  555. RESULT_ERASED = llmemory.Address
  556. result_size = symbolic.get_size(RESULT_ERASED,
  557. gccache.translate_support_code)
  558. result_signed = get_type_flag(RESULT) == FLAG_SIGNED
  559. key = (arg_classes, result_type, result_signed, RESULT_ERASED, extrainfo)
  560. cache = gccache._cache_call
  561. try:
  562. calldescr = cache[key]
  563. except KeyError:
  564. calldescr = CallDescr(arg_classes, result_type, result_signed,
  565. result_size, extrainfo)
  566. calldescr.create_call_stub(gccache.rtyper, RESULT_ERASED)
  567. cache[key] = calldescr
  568. assert repr(calldescr.result_size) == repr(result_size)
  569. return calldescr
  570. def unpack_arraydescr(arraydescr):
  571. assert isinstance(arraydescr, ArrayDescr)
  572. ofs = arraydescr.basesize # this includes +1 for STR
  573. size = arraydescr.itemsize
  574. sign = arraydescr.is_item_signed()
  575. return size, ofs, sign
  576. def unpack_fielddescr(fielddescr):
  577. assert isinstance(fielddescr, FieldDescr)
  578. ofs = fielddescr.offset
  579. size = fielddescr.field_size
  580. sign = fielddescr.is_field_signed()
  581. return ofs, size, sign
  582. unpack_fielddescr._always_inline_ = True
  583. def unpack_interiorfielddescr(descr):
  584. assert isinstance(descr, InteriorFieldDescr)
  585. arraydescr = descr.arraydescr
  586. ofs = arraydescr.basesize
  587. itemsize = arraydescr.itemsize
  588. fieldsize = descr.fielddescr.field_size
  589. sign = descr.fielddescr.is_field_signed()
  590. ofs += descr.fielddescr.offset
  591. return ofs, itemsize, fieldsize, sign