PageRenderTime 117ms CodeModel.GetById 22ms RepoModel.GetById 7ms app.codeStats 0ms

/rpython/rtyper/test/test_llann.py

https://bitbucket.org/pypy/pypy/
Python | 534 lines | 453 code | 78 blank | 3 comment | 43 complexity | 736df9ffed016f69ae3c5504c0f56b26 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import py
  2. from rpython.annotator import model as annmodel
  3. from rpython.rtyper.llannotation import SomePtr, lltype_to_annotation
  4. from rpython.conftest import option
  5. from rpython.rtyper.annlowlevel import (annotate_lowlevel_helper,
  6. MixLevelHelperAnnotator, PseudoHighLevelCallable, llhelper,
  7. cast_instance_to_base_ptr, cast_base_ptr_to_instance)
  8. from rpython.rtyper.llinterp import LLInterpreter
  9. from rpython.rtyper.lltypesystem.lltype import *
  10. from rpython.rtyper.rclass import fishllattr, OBJECTPTR
  11. from rpython.rtyper.test.test_llinterp import interpret
  12. from rpython.translator.translator import TranslationContext
  13. # helpers
  14. def annotated_calls(ann, ops=('simple_call,')):
  15. for block in ann.annotated:
  16. for op in block.operations:
  17. if op.opname in ops:
  18. yield op
  19. def derived(op, orig):
  20. if op.args[0].value.__name__.startswith(orig):
  21. return op.args[0].value
  22. else:
  23. return None
  24. class TestLowLevelAnnotateTestCase:
  25. from rpython.annotator.annrpython import RPythonAnnotator
  26. def annotate(self, ll_function, argtypes):
  27. self.a = self.RPythonAnnotator()
  28. graph = annotate_lowlevel_helper(self.a, ll_function, argtypes)
  29. if option.view:
  30. self.a.translator.view()
  31. return self.a.binding(graph.getreturnvar())
  32. def test_simple(self):
  33. S = GcStruct("s", ('v', Signed))
  34. def llf():
  35. s = malloc(S)
  36. return s.v
  37. s = self.annotate(llf, [])
  38. assert s.knowntype == int
  39. def test_simple2(self):
  40. S = Struct("s", ('v', Signed))
  41. S2 = GcStruct("s2", ('a', S), ('b', S))
  42. def llf():
  43. s = malloc(S2)
  44. return s.a.v+s.b.v
  45. s = self.annotate(llf, [])
  46. assert s.knowntype == int
  47. def test_array(self):
  48. A = GcArray(('v', Signed))
  49. def llf():
  50. a = malloc(A, 1)
  51. return a[0].v
  52. s = self.annotate(llf, [])
  53. assert s.knowntype == int
  54. def test_array_longlong(self):
  55. from rpython.rlib.rarithmetic import r_longlong
  56. A = GcArray(('v', Signed))
  57. one = r_longlong(1)
  58. def llf():
  59. a = malloc(A, one)
  60. return a[0].v
  61. s = self.annotate(llf, [])
  62. assert s.knowntype == int
  63. def test_prim_array(self):
  64. A = GcArray(Signed)
  65. def llf():
  66. a = malloc(A, 1)
  67. return a[0]
  68. s = self.annotate(llf, [])
  69. assert s.knowntype == int
  70. def test_prim_array_setitem(self):
  71. A = GcArray(Signed)
  72. def llf():
  73. a = malloc(A, 1)
  74. a[0] = 3
  75. return a[0]
  76. s = self.annotate(llf, [])
  77. assert s.knowntype == int
  78. def test_cast_simple_widening(self):
  79. S2 = Struct("s2", ('a', Signed))
  80. S1 = Struct("s1", ('sub1', S2), ('sub2', S2))
  81. PS1 = Ptr(S1)
  82. PS2 = Ptr(S2)
  83. def llf(p1):
  84. p2 = p1.sub1
  85. p3 = cast_pointer(PS1, p2)
  86. return p3
  87. s = self.annotate(llf, [SomePtr(PS1)])
  88. assert isinstance(s, SomePtr)
  89. assert s.ll_ptrtype == PS1
  90. def test_cast_simple_widening_from_gc(self):
  91. S2 = GcStruct("s2", ('a', Signed))
  92. S1 = GcStruct("s1", ('sub1', S2), ('x', Signed))
  93. PS1 = Ptr(S1)
  94. def llf():
  95. p1 = malloc(S1)
  96. p2 = p1.sub1
  97. p3 = cast_pointer(PS1, p2)
  98. return p3
  99. s = self.annotate(llf, [])
  100. assert isinstance(s, SomePtr)
  101. assert s.ll_ptrtype == PS1
  102. def test_cast_pointer(self):
  103. S3 = GcStruct("s3", ('a', Signed))
  104. S2 = GcStruct("s3", ('sub', S3))
  105. S1 = GcStruct("s1", ('sub', S2))
  106. PS1 = Ptr(S1)
  107. PS2 = Ptr(S2)
  108. PS3 = Ptr(S3)
  109. def llf():
  110. p1 = malloc(S1)
  111. p2 = p1.sub
  112. p3 = p2.sub
  113. p12 = cast_pointer(PS1, p2)
  114. p13 = cast_pointer(PS1, p3)
  115. p21 = cast_pointer(PS2, p1)
  116. p23 = cast_pointer(PS2, p3)
  117. p31 = cast_pointer(PS3, p1)
  118. p32 = cast_pointer(PS3, p2)
  119. return p12, p13, p21, p23, p31, p32
  120. s = self.annotate(llf, [])
  121. assert [x.ll_ptrtype for x in s.items] == [PS1, PS1, PS2, PS2, PS3, PS3]
  122. def test_array_length(self):
  123. A = GcArray(('v', Signed))
  124. def llf():
  125. a = malloc(A, 1)
  126. return len(a)
  127. s = self.annotate(llf, [])
  128. assert s.knowntype == int
  129. def test_funcptr(self):
  130. F = FuncType((Signed,), Signed)
  131. PF = Ptr(F)
  132. def llf(p):
  133. return p(0)
  134. s = self.annotate(llf, [SomePtr(PF)])
  135. assert s.knowntype == int
  136. def test_ll_calling_ll(self):
  137. A = GcArray(Float)
  138. B = GcArray(Signed)
  139. def ll_make(T, n):
  140. x = malloc(T, n)
  141. return x
  142. def ll_get(T, x, i):
  143. return x[i]
  144. def llf():
  145. a = ll_make(A, 3)
  146. b = ll_make(B, 2)
  147. a[0] = 1.0
  148. b[1] = 3
  149. y0 = ll_get(A, a, 1)
  150. y1 = ll_get(B, b, 1)
  151. #
  152. a2 = ll_make(A, 4)
  153. a2[0] = 2.0
  154. return ll_get(A, a2, 1)
  155. s = self.annotate(llf, [])
  156. a = self.a
  157. assert s == annmodel.SomeFloat()
  158. seen = {}
  159. ngraphs = len(a.translator.graphs)
  160. vTs = []
  161. for call in annotated_calls(a):
  162. if derived(call, "ll_"):
  163. func, T = [x.value for x in call.args[0:2]]
  164. if (func, T) in seen:
  165. continue
  166. seen[func, T] = True
  167. desc = a.bookkeeper.getdesc(func)
  168. g = desc.specialize([a.binding(x) for x in call.args[1:]])
  169. args = g.getargs()
  170. rv = g.getreturnvar()
  171. if func is ll_get:
  172. vT, vp, vi = args
  173. assert a.binding(vT) == a.bookkeeper.immutablevalue(T)
  174. assert a.binding(vi).knowntype == int
  175. assert a.binding(vp).ll_ptrtype.TO == T
  176. assert a.binding(rv) == lltype_to_annotation(T.OF)
  177. elif func is ll_make:
  178. vT, vn = args
  179. assert a.binding(vT) == a.bookkeeper.immutablevalue(T)
  180. assert a.binding(vn).knowntype == int
  181. assert a.binding(rv).ll_ptrtype.TO == T
  182. else:
  183. assert False, func
  184. vTs.append(vT)
  185. assert len(seen) == 4
  186. return a, vTs # reused by a test in test_rtyper
  187. def test_ll_calling_ll2(self):
  188. A = GcArray(Float)
  189. B = GcArray(Signed)
  190. def ll_make(T, n):
  191. x = malloc(T, n)
  192. return x
  193. def ll_get(x, i):
  194. return x[i]
  195. def makelen4(T):
  196. return ll_make(T, 4)
  197. def llf():
  198. a = ll_make(A, 3)
  199. b = ll_make(B, 2)
  200. a[0] = 1.0
  201. b[1] = 3
  202. y0 = ll_get(a, 1)
  203. y1 = ll_get(b, 1)
  204. #
  205. a2 = makelen4(A)
  206. a2[0] = 2.0
  207. return ll_get(a2, 1)
  208. s = self.annotate(llf, [])
  209. a = self.a
  210. assert s == annmodel.SomeFloat()
  211. seen = {}
  212. def q(v):
  213. s = a.binding(v)
  214. if s.is_constant():
  215. return s.const
  216. else:
  217. return s.ll_ptrtype
  218. vTs = []
  219. for call in annotated_calls(a):
  220. if derived(call, "ll_") or derived(call, "makelen4"):
  221. func, T = [q(x) for x in call.args[0:2]]
  222. if (func, T) in seen:
  223. continue
  224. seen[func, T] = True
  225. desc = a.bookkeeper.getdesc(func)
  226. g = desc.specialize([a.binding(x) for x in call.args[1:]])
  227. args = g.getargs()
  228. rv = g.getreturnvar()
  229. if func is ll_make:
  230. vT, vn = args
  231. assert a.binding(vT) == a.bookkeeper.immutablevalue(T)
  232. assert a.binding(vn).knowntype == int
  233. assert a.binding(rv).ll_ptrtype.TO == T
  234. vTs.append(vT)
  235. elif func is makelen4:
  236. vT, = args
  237. assert a.binding(vT) == a.bookkeeper.immutablevalue(T)
  238. assert a.binding(rv).ll_ptrtype.TO == T
  239. vTs.append(vT)
  240. elif func is ll_get:
  241. vp, vi = args
  242. assert a.binding(vi).knowntype == int
  243. assert a.binding(vp).ll_ptrtype == T
  244. assert a.binding(rv) == lltype_to_annotation(
  245. T.TO.OF)
  246. else:
  247. assert False, func
  248. assert len(seen) == 5
  249. return a, vTs # reused by a test in test_rtyper
  250. def test_ll_stararg(self):
  251. A = GcArray(Float)
  252. B = GcArray(Signed)
  253. def ll_sum(*args):
  254. result = 0
  255. if len(args) > 0:
  256. result += args[0]
  257. if len(args) > 1:
  258. result += args[1]
  259. if len(args) > 2:
  260. result += args[2]
  261. if len(args) > 3:
  262. result += args[3]
  263. return result
  264. def llf():
  265. a = ll_sum()
  266. b = ll_sum(4, 5)
  267. c = ll_sum(2.5)
  268. d = ll_sum(4, 5.25)
  269. e = ll_sum(1000, 200, 30, 4)
  270. f = ll_sum(1000, 200, 30, 5)
  271. return a, b, c, d, e, f
  272. s = self.annotate(llf, [])
  273. assert isinstance(s, annmodel.SomeTuple)
  274. assert s.items[0].knowntype is int
  275. assert s.items[0].const == 0
  276. assert s.items[1].knowntype is int
  277. assert s.items[2].knowntype is float
  278. assert s.items[3].knowntype is float
  279. assert s.items[4].knowntype is int
  280. assert s.items[5].knowntype is int
  281. def test_str_vs_ptr(self):
  282. S = GcStruct('s', ('x', Signed))
  283. def ll_stuff(x):
  284. if x is None or isinstance(x, str):
  285. return 2
  286. else:
  287. return 3
  288. def llf():
  289. x = ll_stuff("hello")
  290. y = ll_stuff(nullptr(S))
  291. return x, y
  292. s = self.annotate(llf, [])
  293. assert isinstance(s, annmodel.SomeTuple)
  294. assert s.items[0].is_constant()
  295. assert s.items[0].const == 2
  296. assert s.items[1].is_constant()
  297. assert s.items[1].const == 3
  298. def test_getRuntimeTypeInfo(self):
  299. S = GcStruct('s', ('x', Signed), rtti=True)
  300. def llf():
  301. return getRuntimeTypeInfo(S)
  302. s = self.annotate(llf, [])
  303. assert isinstance(s, SomePtr)
  304. assert s.ll_ptrtype == Ptr(RuntimeTypeInfo)
  305. assert s.const == getRuntimeTypeInfo(S)
  306. def test_runtime_type_info(self):
  307. S = GcStruct('s', ('x', Signed), rtti=True)
  308. def llf(p):
  309. return runtime_type_info(p)
  310. s = self.annotate(llf, [SomePtr(Ptr(S))])
  311. assert isinstance(s, SomePtr)
  312. assert s.ll_ptrtype == Ptr(RuntimeTypeInfo)
  313. def test_cast_primitive(self):
  314. def llf(u):
  315. return cast_primitive(Signed, u)
  316. s = self.annotate(llf, [annmodel.SomeInteger(unsigned=True)])
  317. assert s.knowntype == int
  318. def llf(s):
  319. return cast_primitive(Unsigned, s)
  320. s = self.annotate(llf, [annmodel.SomeInteger()])
  321. assert s.unsigned == True
  322. def test_pbctype(self):
  323. TYPE = Void
  324. TYPE2 = Signed
  325. def g(lst):
  326. n = lst[0]
  327. if isinstance(TYPE, Number):
  328. result = 123
  329. else:
  330. result = 456
  331. if isinstance(TYPE2, Number):
  332. result += 1
  333. return result + n
  334. def llf():
  335. lst = [5]
  336. g(lst)
  337. lst.append(6)
  338. self.annotate(llf, [])
  339. def test_adtmeths(self):
  340. def h_length(s):
  341. return s.foo
  342. S = GcStruct("S", ('foo', Signed),
  343. adtmeths={"h_length": h_length,
  344. "stuff": 12})
  345. def llf():
  346. s = malloc(S)
  347. s.foo = 321
  348. return s.h_length()
  349. s = self.annotate(llf, [])
  350. assert s.knowntype == int and not s.is_constant()
  351. def llf():
  352. s = malloc(S)
  353. return s.stuff
  354. s = self.annotate(llf, [])
  355. assert s.is_constant() and s.const == 12
  356. def test_pseudohighlevelcallable():
  357. t = TranslationContext()
  358. t.buildannotator()
  359. rtyper = t.buildrtyper()
  360. rtyper.specialize()
  361. a = MixLevelHelperAnnotator(rtyper)
  362. class A:
  363. value = 5
  364. def double(self):
  365. return self.value * 2
  366. def fn1(a):
  367. a2 = A()
  368. a2.value = a.double()
  369. return a2
  370. s_A, r_A = a.s_r_instanceof(A)
  371. fn1ptr = a.delayedfunction(fn1, [s_A], s_A)
  372. pseudo = PseudoHighLevelCallable(fn1ptr, [s_A], s_A)
  373. def fn2(n):
  374. a = A()
  375. a.value = n
  376. a2 = pseudo(a)
  377. return a2.value
  378. graph = a.getgraph(fn2, [annmodel.SomeInteger()], annmodel.SomeInteger())
  379. a.finish()
  380. llinterp = LLInterpreter(rtyper)
  381. res = llinterp.eval_graph(graph, [21])
  382. assert res == 42
  383. def test_llhelper():
  384. S = GcStruct('S', ('x', Signed), ('y', Signed))
  385. def f(s,z):
  386. return s.x*s.y+z
  387. def g(s):
  388. return s.x+s.y
  389. F = Ptr(FuncType([Ptr(S), Signed], Signed))
  390. G = Ptr(FuncType([Ptr(S)], Signed))
  391. def h(x, y, z):
  392. s = malloc(S)
  393. s.x = x
  394. s.y = y
  395. fptr = llhelper(F, f)
  396. gptr = llhelper(G, g)
  397. assert typeOf(fptr) == F
  398. return fptr(s, z)+fptr(s, z*2)+gptr(s)
  399. res = interpret(h, [8, 5, 2])
  400. assert res == 99
  401. def test_llhelper_multiple_functions():
  402. S = GcStruct('S', ('x', Signed), ('y', Signed))
  403. def f(s):
  404. return s.x - s.y
  405. def g(s):
  406. return s.x + s.y
  407. F = Ptr(FuncType([Ptr(S)], Signed))
  408. myfuncs = [f, g]
  409. def h(x, y, z):
  410. s = malloc(S)
  411. s.x = x
  412. s.y = y
  413. fptr = llhelper(F, myfuncs[z])
  414. assert typeOf(fptr) == F
  415. return fptr(s)
  416. res = interpret(h, [80, 5, 0])
  417. assert res == 75
  418. res = interpret(h, [80, 5, 1])
  419. assert res == 85
  420. def test_cast_instance_to_base_ptr():
  421. class A:
  422. def __init__(self, x, y):
  423. self.x = x
  424. self.y = y
  425. def f(x, y):
  426. if x > 20:
  427. a = None
  428. else:
  429. a = A(x, y)
  430. a1 = cast_instance_to_base_ptr(a)
  431. return a1
  432. res = interpret(f, [5, 10])
  433. assert typeOf(res) == OBJECTPTR
  434. assert fishllattr(res, 'x') == 5
  435. assert fishllattr(res, 'y') == 10
  436. res = interpret(f, [25, 10])
  437. assert res == nullptr(OBJECTPTR.TO)
  438. def test_cast_base_ptr_to_instance():
  439. class A:
  440. def __init__(self, x, y):
  441. self.x = x
  442. self.y = y
  443. def f(x, y):
  444. if x > 20:
  445. a = None
  446. else:
  447. a = A(x, y)
  448. a1 = cast_instance_to_base_ptr(a)
  449. b = cast_base_ptr_to_instance(A, a1)
  450. return a is b
  451. assert f(5, 10) is True
  452. assert f(25, 10) is True
  453. res = interpret(f, [5, 10])
  454. assert res is True
  455. res = interpret(f, [25, 10])
  456. assert res is True