PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/rtyper/rptr.py

https://bitbucket.org/pypy/pypy/
Python | 343 lines | 286 code | 52 blank | 5 comment | 45 complexity | 6a450c6d734fb4057d5d807e54989618 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. from rpython.rtyper.llannotation import (
  2. SomePtr, SomeInteriorPtr, SomeLLADTMeth, lltype_to_annotation)
  3. from rpython.flowspace import model as flowmodel
  4. from rpython.rlib.rarithmetic import r_uint
  5. from rpython.rtyper.error import TyperError
  6. from rpython.rtyper.lltypesystem import lltype
  7. from rpython.rtyper.rmodel import Repr
  8. from rpython.rtyper.rint import IntegerRepr
  9. from rpython.tool.pairtype import pairtype
  10. class __extend__(SomePtr):
  11. def rtyper_makerepr(self, rtyper):
  12. return PtrRepr(self.ll_ptrtype, rtyper)
  13. def rtyper_makekey(self):
  14. return self.__class__, self.ll_ptrtype
  15. class __extend__(SomeInteriorPtr):
  16. def rtyper_makerepr(self, rtyper):
  17. return InteriorPtrRepr(self.ll_ptrtype)
  18. def rtyper_makekey(self):
  19. return self.__class__, self.ll_ptrtype
  20. class PtrRepr(Repr):
  21. def __init__(self, ptrtype, rtyper=None):
  22. assert isinstance(ptrtype, lltype.Ptr)
  23. self.lowleveltype = ptrtype
  24. if rtyper is not None:
  25. self.rtyper = rtyper # only for _convert_const_ptr()
  26. def ll_str(self, p):
  27. from rpython.rtyper.lltypesystem.rstr import ll_str
  28. id = lltype.cast_ptr_to_int(p)
  29. return ll_str.ll_int2hex(r_uint(id), True)
  30. def get_ll_eq_function(self):
  31. return None
  32. def rtype_getattr(self, hop):
  33. attr = hop.args_s[1].const
  34. if isinstance(hop.s_result, SomeLLADTMeth):
  35. return hop.inputarg(hop.r_result, arg=0)
  36. try:
  37. self.lowleveltype._example()._lookup_adtmeth(attr)
  38. except AttributeError:
  39. pass
  40. else:
  41. assert hop.s_result.is_constant()
  42. return hop.inputconst(hop.r_result, hop.s_result.const)
  43. assert attr in self.lowleveltype.TO._flds # check that the field exists
  44. FIELD_TYPE = getattr(self.lowleveltype.TO, attr)
  45. if isinstance(FIELD_TYPE, lltype.ContainerType):
  46. if (attr, FIELD_TYPE) == self.lowleveltype.TO._first_struct():
  47. return hop.genop('cast_pointer', [hop.inputarg(self, 0)],
  48. resulttype=hop.r_result.lowleveltype)
  49. elif isinstance(hop.r_result, InteriorPtrRepr):
  50. return hop.inputarg(self, 0)
  51. else:
  52. newopname = 'getsubstruct'
  53. else:
  54. newopname = 'getfield'
  55. vlist = hop.inputargs(self, lltype.Void)
  56. return hop.genop(newopname, vlist,
  57. resulttype = hop.r_result.lowleveltype)
  58. def rtype_setattr(self, hop):
  59. attr = hop.args_s[1].const
  60. FIELD_TYPE = getattr(self.lowleveltype.TO, attr)
  61. assert not isinstance(FIELD_TYPE, lltype.ContainerType)
  62. vlist = hop.inputargs(self, lltype.Void, hop.args_r[2])
  63. hop.genop('setfield', vlist)
  64. def rtype_len(self, hop):
  65. ARRAY = hop.args_r[0].lowleveltype.TO
  66. if isinstance(ARRAY, lltype.FixedSizeArray):
  67. return hop.inputconst(lltype.Signed, ARRAY.length)
  68. else:
  69. vlist = hop.inputargs(self)
  70. return hop.genop('getarraysize', vlist,
  71. resulttype = hop.r_result.lowleveltype)
  72. def rtype_bool(self, hop):
  73. vlist = hop.inputargs(self)
  74. return hop.genop('ptr_nonzero', vlist, resulttype=lltype.Bool)
  75. def rtype_simple_call(self, hop):
  76. if not isinstance(self.lowleveltype.TO, lltype.FuncType):
  77. raise TyperError("calling a non-function %r", self.lowleveltype.TO)
  78. vlist = hop.inputargs(*hop.args_r)
  79. nexpected = len(self.lowleveltype.TO.ARGS)
  80. nactual = len(vlist)-1
  81. if nactual != nexpected:
  82. raise TyperError("argcount mismatch: expected %d got %d" %
  83. (nexpected, nactual))
  84. if isinstance(vlist[0], flowmodel.Constant):
  85. if hasattr(vlist[0].value, 'graph'):
  86. hop.llops.record_extra_call(vlist[0].value.graph)
  87. opname = 'direct_call'
  88. else:
  89. opname = 'indirect_call'
  90. vlist.append(hop.inputconst(lltype.Void, None))
  91. hop.exception_is_here()
  92. return hop.genop(opname, vlist,
  93. resulttype = self.lowleveltype.TO.RESULT)
  94. def rtype_call_args(self, hop):
  95. raise TyperError("kwds args not supported")
  96. def convert_const(self, value):
  97. if hasattr(value, '_convert_const_ptr'):
  98. assert hasattr(self, 'rtyper')
  99. return value._convert_const_ptr(self)
  100. return Repr.convert_const(self, value)
  101. class __extend__(pairtype(PtrRepr, PtrRepr)):
  102. def convert_from_to((r_ptr1, r_ptr2), v, llop):
  103. if r_ptr1.lowleveltype == r_ptr2.lowleveltype:
  104. return v
  105. return NotImplemented
  106. class __extend__(pairtype(PtrRepr, IntegerRepr)):
  107. def rtype_getitem((r_ptr, r_int), hop):
  108. ARRAY = r_ptr.lowleveltype.TO
  109. ITEM_TYPE = ARRAY.OF
  110. if isinstance(ITEM_TYPE, lltype.ContainerType):
  111. if isinstance(hop.r_result, InteriorPtrRepr):
  112. v_array, v_index = hop.inputargs(r_ptr, lltype.Signed)
  113. INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index(ITEM_TYPE)
  114. cflags = hop.inputconst(lltype.Void, {'flavor': 'gc'})
  115. args = [flowmodel.Constant(INTERIOR_PTR_TYPE, lltype.Void),
  116. cflags]
  117. v_interior_ptr = hop.genop('malloc', args,
  118. resulttype=lltype.Ptr(INTERIOR_PTR_TYPE))
  119. hop.genop('setfield',
  120. [v_interior_ptr, flowmodel.Constant('ptr', lltype.Void), v_array])
  121. hop.genop('setfield',
  122. [v_interior_ptr, flowmodel.Constant('index', lltype.Void), v_index])
  123. return v_interior_ptr
  124. else:
  125. newopname = 'getarraysubstruct'
  126. else:
  127. newopname = 'getarrayitem'
  128. vlist = hop.inputargs(r_ptr, lltype.Signed)
  129. return hop.genop(newopname, vlist,
  130. resulttype = hop.r_result.lowleveltype)
  131. def rtype_setitem((r_ptr, r_int), hop):
  132. ARRAY = r_ptr.lowleveltype.TO
  133. ITEM_TYPE = ARRAY.OF
  134. assert not isinstance(ITEM_TYPE, lltype.ContainerType)
  135. vlist = hop.inputargs(r_ptr, lltype.Signed, hop.args_r[2])
  136. hop.genop('setarrayitem', vlist)
  137. # ____________________________________________________________
  138. #
  139. # Comparisons
  140. class __extend__(pairtype(PtrRepr, Repr)):
  141. def rtype_eq((r_ptr, r_any), hop):
  142. vlist = hop.inputargs(r_ptr, r_ptr)
  143. return hop.genop('ptr_eq', vlist, resulttype=lltype.Bool)
  144. def rtype_ne((r_ptr, r_any), hop):
  145. vlist = hop.inputargs(r_ptr, r_ptr)
  146. return hop.genop('ptr_ne', vlist, resulttype=lltype.Bool)
  147. class __extend__(pairtype(Repr, PtrRepr)):
  148. def rtype_eq((r_any, r_ptr), hop):
  149. vlist = hop.inputargs(r_ptr, r_ptr)
  150. return hop.genop('ptr_eq', vlist, resulttype=lltype.Bool)
  151. def rtype_ne((r_any, r_ptr), hop):
  152. vlist = hop.inputargs(r_ptr, r_ptr)
  153. return hop.genop('ptr_ne', vlist, resulttype=lltype.Bool)
  154. # ________________________________________________________________
  155. # ADT methods
  156. class __extend__(SomeLLADTMeth):
  157. def rtyper_makerepr(self, rtyper):
  158. return LLADTMethRepr(self, rtyper)
  159. def rtyper_makekey(self):
  160. return self.__class__, self.ll_ptrtype, self.func
  161. class LLADTMethRepr(Repr):
  162. def __init__(self, adtmeth, rtyper):
  163. self.func = adtmeth.func
  164. self.lowleveltype = adtmeth.ll_ptrtype
  165. self.ll_ptrtype = adtmeth.ll_ptrtype
  166. self.lowleveltype = rtyper.getrepr(lltype_to_annotation(adtmeth.ll_ptrtype)).lowleveltype
  167. def rtype_simple_call(self, hop):
  168. hop2 = hop.copy()
  169. func = self.func
  170. s_func = hop.rtyper.annotator.bookkeeper.immutablevalue(func)
  171. v_ptr = hop2.args_v[0]
  172. hop2.r_s_popfirstarg()
  173. hop2.v_s_insertfirstarg(v_ptr, lltype_to_annotation(self.ll_ptrtype))
  174. hop2.v_s_insertfirstarg(flowmodel.Constant(func), s_func)
  175. return hop2.dispatch()
  176. class __extend__(pairtype(PtrRepr, LLADTMethRepr)):
  177. def convert_from_to((r_from, r_to), v, llops):
  178. if r_from.lowleveltype == r_to.lowleveltype:
  179. return v
  180. return NotImplemented
  181. class InteriorPtrRepr(Repr):
  182. def __init__(self, ptrtype):
  183. assert isinstance(ptrtype, lltype.InteriorPtr)
  184. self._ptrtype = ptrtype # for debugging
  185. self.v_offsets = []
  186. numitemoffsets = 0
  187. for i, offset in enumerate(ptrtype.offsets):
  188. if isinstance(offset, int):
  189. numitemoffsets += 1
  190. self.v_offsets.append(None)
  191. else:
  192. assert isinstance(offset, str)
  193. self.v_offsets.append(flowmodel.Constant(offset, lltype.Void))
  194. self.parentptrtype = lltype.Ptr(ptrtype.PARENTTYPE)
  195. self.resulttype = lltype.Ptr(ptrtype.TO)
  196. assert numitemoffsets <= 1
  197. if numitemoffsets > 0:
  198. self.lowleveltype = lltype.Ptr(self.parentptrtype._interior_ptr_type_with_index(self.resulttype.TO))
  199. else:
  200. self.lowleveltype = self.parentptrtype
  201. def getinteriorfieldargs(self, hop, v_self):
  202. vlist = []
  203. if None in self.v_offsets:
  204. INTERIOR_TYPE = v_self.concretetype.TO
  205. nameiter = iter(INTERIOR_TYPE._names)
  206. name = nameiter.next()
  207. vlist.append(
  208. hop.genop('getfield',
  209. [v_self, flowmodel.Constant(name, lltype.Void)],
  210. resulttype=INTERIOR_TYPE._flds[name]))
  211. else:
  212. vlist.append(v_self)
  213. for v_offset in self.v_offsets:
  214. if v_offset is None:
  215. name = nameiter.next()
  216. vlist.append(
  217. hop.genop('getfield',
  218. [v_self, flowmodel.Constant(name, lltype.Void)],
  219. resulttype=INTERIOR_TYPE._flds[name]))
  220. else:
  221. vlist.append(v_offset)
  222. if None in self.v_offsets:
  223. try:
  224. nameiter.next()
  225. except StopIteration:
  226. pass
  227. else:
  228. assert False
  229. return vlist
  230. def rtype_len(self, hop):
  231. v_self, = hop.inputargs(self)
  232. vlist = self.getinteriorfieldargs(hop, v_self)
  233. return hop.genop('getinteriorarraysize', vlist,
  234. resulttype=lltype.Signed)
  235. def rtype_getattr(self, hop):
  236. attr = hop.args_s[1].const
  237. if isinstance(hop.s_result, SomeLLADTMeth):
  238. return hop.inputarg(hop.r_result, arg=0)
  239. FIELD_TYPE = getattr(self.resulttype.TO, attr)
  240. if isinstance(FIELD_TYPE, lltype.ContainerType):
  241. return hop.inputarg(self, 0)
  242. else:
  243. v_self, v_attr = hop.inputargs(self, lltype.Void)
  244. vlist = self.getinteriorfieldargs(hop, v_self) + [v_attr]
  245. return hop.genop('getinteriorfield', vlist,
  246. resulttype=hop.r_result.lowleveltype)
  247. def rtype_setattr(self, hop):
  248. attr = hop.args_s[1].const
  249. FIELD_TYPE = getattr(self.resulttype.TO, attr)
  250. assert not isinstance(FIELD_TYPE, lltype.ContainerType)
  251. v_self, v_fieldname, v_value = hop.inputargs(self, lltype.Void, hop.args_r[2])
  252. vlist = self.getinteriorfieldargs(hop, v_self) + [v_fieldname, v_value]
  253. return hop.genop('setinteriorfield', vlist)
  254. class __extend__(pairtype(InteriorPtrRepr, IntegerRepr)):
  255. def rtype_getitem((r_ptr, r_item), hop):
  256. ARRAY = r_ptr.resulttype.TO
  257. ITEM_TYPE = ARRAY.OF
  258. if isinstance(ITEM_TYPE, lltype.ContainerType):
  259. v_array, v_index = hop.inputargs(r_ptr, lltype.Signed)
  260. INTERIOR_PTR_TYPE = r_ptr.lowleveltype._interior_ptr_type_with_index(ITEM_TYPE)
  261. cflags = hop.inputconst(lltype.Void, {'flavor': 'gc'})
  262. args = [flowmodel.Constant(INTERIOR_PTR_TYPE, lltype.Void), cflags]
  263. v_interior_ptr = hop.genop('malloc', args,
  264. resulttype=lltype.Ptr(INTERIOR_PTR_TYPE))
  265. hop.genop('setfield',
  266. [v_interior_ptr, flowmodel.Constant('ptr', lltype.Void), v_array])
  267. hop.genop('setfield',
  268. [v_interior_ptr, flowmodel.Constant('index', lltype.Void), v_index])
  269. return v_interior_ptr
  270. else:
  271. v_self, v_index = hop.inputargs(r_ptr, lltype.Signed)
  272. vlist = r_ptr.getinteriorfieldargs(hop, v_self) + [v_index]
  273. return hop.genop('getinteriorfield', vlist,
  274. resulttype=ITEM_TYPE)
  275. def rtype_setitem((r_ptr, r_index), hop):
  276. ARRAY = r_ptr.resulttype.TO
  277. ITEM_TYPE = ARRAY.OF
  278. assert not isinstance(ITEM_TYPE, lltype.ContainerType)
  279. v_self, v_index, v_value = hop.inputargs(r_ptr, lltype.Signed, hop.args_r[2])
  280. vlist = r_ptr.getinteriorfieldargs(hop, v_self) + [v_index, v_value]
  281. hop.genop('setinteriorfield', vlist)
  282. class __extend__(pairtype(InteriorPtrRepr, LLADTMethRepr)):
  283. def convert_from_to((r_from, r_to), v, llops):
  284. if r_from.lowleveltype == r_to.lowleveltype:
  285. return v
  286. return NotImplemented
  287. class __extend__(pairtype(InteriorPtrRepr, InteriorPtrRepr)):
  288. def convert_from_to((r_from, r_to), v, llops):
  289. if r_from.__dict__ == r_to.__dict__:
  290. return v
  291. return NotImplemented