rtl.test 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. ;;;; Low-level tests of the bytecode assembler -*- mode: scheme; coding: utf-8; -*-
  2. ;;;;
  3. ;;;; Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015 Free Software Foundation, Inc.
  4. ;;;;
  5. ;;;; This library is free software; you can redistribute it and/or
  6. ;;;; modify it under the terms of the GNU Lesser General Public
  7. ;;;; License as published by the Free Software Foundation; either
  8. ;;;; version 3 of the License, or (at your option) any later version.
  9. ;;;;
  10. ;;;; This library is distributed in the hope that it will be useful,
  11. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  13. ;;;; Lesser General Public License for more details.
  14. ;;;;
  15. ;;;; You should have received a copy of the GNU Lesser General Public
  16. ;;;; License along with this library; if not, write to the Free Software
  17. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  18. (define-module (tests bytecode)
  19. #:use-module (test-suite lib)
  20. #:use-module (system vm assembler)
  21. #:use-module (system vm program)
  22. #:use-module (system vm loader)
  23. #:use-module (system vm linker)
  24. #:use-module (system vm debug))
  25. (define (assemble-program instructions)
  26. "Take the sequence of instructions @var{instructions}, assemble them
  27. into bytecode, link an image, and load that image from memory. Returns
  28. a procedure."
  29. (let ((asm (make-assembler)))
  30. (emit-text asm instructions)
  31. (load-thunk-from-memory (link-assembly asm #:page-aligned? #f))))
  32. (define-syntax-rule (assert-equal val expr)
  33. (let ((x val))
  34. (pass-if (object->string x) (equal? expr x))))
  35. (define (return-constant val)
  36. (assemble-program `((begin-program foo
  37. ((name . foo)))
  38. (begin-standard-arity () 2 #f)
  39. (load-constant 0 ,val)
  40. (return-values 2)
  41. (end-arity)
  42. (end-program))))
  43. (define-syntax-rule (assert-constants val ...)
  44. (begin
  45. (assert-equal val ((return-constant val)))
  46. ...))
  47. (with-test-prefix "load-constant"
  48. (assert-constants
  49. 1
  50. -1
  51. 0
  52. most-positive-fixnum
  53. most-negative-fixnum
  54. #t
  55. #\c
  56. (integer->char 16000)
  57. 3.14
  58. "foo"
  59. 'foo
  60. #:foo
  61. "æ" ;; a non-ASCII Latin-1 string
  62. "λ" ;; non-ascii, non-latin-1
  63. '(1 . 2)
  64. '(1 2 3 4)
  65. #(1 2 3)
  66. #("foo" "bar" 'baz)
  67. #vu8()
  68. #vu8(1 2 3 4 128 129 130)
  69. #u32()
  70. #u32(1 2 3 4 128 129 130 255 1000)
  71. ;; FIXME: Add more tests for arrays (uniform and otherwise)
  72. ))
  73. (with-test-prefix "static procedure"
  74. (assert-equal 42
  75. (((assemble-program `((begin-program foo
  76. ((name . foo)))
  77. (begin-standard-arity () 2 #f)
  78. (load-static-procedure 0 bar)
  79. (return-values 2)
  80. (end-arity)
  81. (end-program)
  82. (begin-program bar
  83. ((name . bar)))
  84. (begin-standard-arity () 2 #f)
  85. (load-constant 0 42)
  86. (return-values 2)
  87. (end-arity)
  88. (end-program)))))))
  89. (with-test-prefix "loop"
  90. (assert-equal (* 999 500)
  91. (let ((sumto
  92. (assemble-program
  93. ;; 0: limit
  94. ;; 1: n
  95. ;; 2: accum
  96. '((begin-program countdown
  97. ((name . countdown)))
  98. (begin-standard-arity (x) 4 #f)
  99. (definition closure 0 scm)
  100. (definition x 1 scm)
  101. (br fix-body)
  102. (label loop-head)
  103. (br-if-= 1 2 #f out)
  104. (add 0 1 0)
  105. (add/immediate 1 1 1)
  106. (br loop-head)
  107. (label fix-body)
  108. (load-constant 1 0)
  109. (load-constant 0 0)
  110. (br loop-head)
  111. (label out)
  112. (mov 2 0)
  113. (return-values 2)
  114. (end-arity)
  115. (end-program)))))
  116. (sumto 1000))))
  117. (with-test-prefix "accum"
  118. (assert-equal (+ 1 2 3)
  119. (let ((make-accum
  120. (assemble-program
  121. ;; 0: elt
  122. ;; 1: tail
  123. ;; 2: head
  124. '((begin-program make-accum
  125. ((name . make-accum)))
  126. (begin-standard-arity () 3 #f)
  127. (load-constant 1 0)
  128. (box 1 1)
  129. (make-closure 0 accum 1)
  130. (free-set! 0 1 0)
  131. (mov 1 0)
  132. (return-values 2)
  133. (end-arity)
  134. (end-program)
  135. (begin-program accum
  136. ((name . accum)))
  137. (begin-standard-arity (x) 4 #f)
  138. (definition closure 0 scm)
  139. (definition x 1 scm)
  140. (free-ref 1 3 0)
  141. (box-ref 0 1)
  142. (add 0 0 2)
  143. (box-set! 1 0)
  144. (mov 2 0)
  145. (return-values 2)
  146. (end-arity)
  147. (end-program)))))
  148. (let ((accum (make-accum)))
  149. (accum 1)
  150. (accum 2)
  151. (accum 3)))))
  152. (with-test-prefix "call"
  153. (assert-equal 42
  154. (let ((call ;; (lambda (x) (x))
  155. (assemble-program
  156. '((begin-program call
  157. ((name . call)))
  158. (begin-standard-arity (f) 7 #f)
  159. (definition closure 0 scm)
  160. (definition f 1 scm)
  161. (mov 1 5)
  162. (call 5 1)
  163. (receive 1 5 7)
  164. (return-values 2)
  165. (end-arity)
  166. (end-program)))))
  167. (call (lambda () 42))))
  168. (assert-equal 6
  169. (let ((call-with-3 ;; (lambda (x) (x 3))
  170. (assemble-program
  171. '((begin-program call-with-3
  172. ((name . call-with-3)))
  173. (begin-standard-arity (f) 7 #f)
  174. (definition closure 0 scm)
  175. (definition f 1 scm)
  176. (mov 1 5)
  177. (load-constant 0 3)
  178. (call 5 2)
  179. (receive 1 5 7)
  180. (return-values 2)
  181. (end-arity)
  182. (end-program)))))
  183. (call-with-3 (lambda (x) (* x 2))))))
  184. (with-test-prefix "tail-call"
  185. (assert-equal 3
  186. (let ((call ;; (lambda (x) (x))
  187. (assemble-program
  188. '((begin-program call
  189. ((name . call)))
  190. (begin-standard-arity (f) 2 #f)
  191. (definition closure 0 scm)
  192. (definition f 1 scm)
  193. (mov 1 0)
  194. (tail-call 1)
  195. (end-arity)
  196. (end-program)))))
  197. (call (lambda () 3))))
  198. (assert-equal 6
  199. (let ((call-with-3 ;; (lambda (x) (x 3))
  200. (assemble-program
  201. '((begin-program call-with-3
  202. ((name . call-with-3)))
  203. (begin-standard-arity (f) 2 #f)
  204. (definition closure 0 scm)
  205. (definition f 1 scm)
  206. (mov 1 0) ;; R0 <- R1
  207. (load-constant 0 3) ;; R1 <- 3
  208. (tail-call 2)
  209. (end-arity)
  210. (end-program)))))
  211. (call-with-3 (lambda (x) (* x 2))))))
  212. (with-test-prefix "cached-toplevel-ref"
  213. (assert-equal 5.0
  214. (let ((get-sqrt-trampoline
  215. (assemble-program
  216. '((begin-program get-sqrt-trampoline
  217. ((name . get-sqrt-trampoline)))
  218. (begin-standard-arity () 2 #f)
  219. (current-module 0)
  220. (cache-current-module! 0 sqrt-scope)
  221. (load-static-procedure 0 sqrt-trampoline)
  222. (return-values 2)
  223. (end-arity)
  224. (end-program)
  225. (begin-program sqrt-trampoline
  226. ((name . sqrt-trampoline)))
  227. (begin-standard-arity (x) 3 #f)
  228. (definition closure 0 scm)
  229. (definition x 1 scm)
  230. (cached-toplevel-box 0 sqrt-scope sqrt #t)
  231. (box-ref 2 0)
  232. (tail-call 2)
  233. (end-arity)
  234. (end-program)))))
  235. ((get-sqrt-trampoline) 25.0))))
  236. (define *top-val* 0)
  237. (with-test-prefix "cached-toplevel-set!"
  238. (let ((prev *top-val*))
  239. (assert-equal (1+ prev)
  240. (let ((make-top-incrementor
  241. (assemble-program
  242. '((begin-program make-top-incrementor
  243. ((name . make-top-incrementor)))
  244. (begin-standard-arity () 2 #f)
  245. (current-module 0)
  246. (cache-current-module! 0 top-incrementor)
  247. (load-static-procedure 0 top-incrementor)
  248. (return-values 2)
  249. (end-arity)
  250. (end-program)
  251. (begin-program top-incrementor
  252. ((name . top-incrementor)))
  253. (begin-standard-arity () 3 #f)
  254. (cached-toplevel-box 1 top-incrementor *top-val* #t)
  255. (box-ref 0 1)
  256. (add/immediate 0 0 1)
  257. (box-set! 1 0)
  258. (return-values 1)
  259. (end-arity)
  260. (end-program)))))
  261. ((make-top-incrementor))
  262. *top-val*))))
  263. (with-test-prefix "cached-module-ref"
  264. (assert-equal 5.0
  265. (let ((get-sqrt-trampoline
  266. (assemble-program
  267. '((begin-program get-sqrt-trampoline
  268. ((name . get-sqrt-trampoline)))
  269. (begin-standard-arity () 2 #f)
  270. (load-static-procedure 0 sqrt-trampoline)
  271. (return-values 2)
  272. (end-arity)
  273. (end-program)
  274. (begin-program sqrt-trampoline
  275. ((name . sqrt-trampoline)))
  276. (begin-standard-arity (x) 3 #f)
  277. (definition closure 0 scm)
  278. (definition x 1 scm)
  279. (cached-module-box 0 (guile) sqrt #t #t)
  280. (box-ref 2 0)
  281. (tail-call 2)
  282. (end-arity)
  283. (end-program)))))
  284. ((get-sqrt-trampoline) 25.0))))
  285. (with-test-prefix "cached-module-set!"
  286. (let ((prev *top-val*))
  287. (assert-equal (1+ prev)
  288. (let ((make-top-incrementor
  289. (assemble-program
  290. '((begin-program make-top-incrementor
  291. ((name . make-top-incrementor)))
  292. (begin-standard-arity () 2 #f)
  293. (load-static-procedure 0 top-incrementor)
  294. (return-values 2)
  295. (end-arity)
  296. (end-program)
  297. (begin-program top-incrementor
  298. ((name . top-incrementor)))
  299. (begin-standard-arity () 3 #f)
  300. (cached-module-box 1 (tests bytecode) *top-val* #f #t)
  301. (box-ref 0 1)
  302. (add/immediate 0 0 1)
  303. (box-set! 1 0)
  304. (mov 1 0)
  305. (return-values 2)
  306. (end-arity)
  307. (end-program)))))
  308. ((make-top-incrementor))
  309. *top-val*))))
  310. (with-test-prefix "debug contexts"
  311. (let ((return-3 (assemble-program
  312. '((begin-program return-3 ((name . return-3)))
  313. (begin-standard-arity () 2 #f)
  314. (load-constant 0 3)
  315. (return-values 2)
  316. (end-arity)
  317. (end-program)))))
  318. (pass-if "program name"
  319. (and=> (find-program-debug-info (program-code return-3))
  320. (lambda (pdi)
  321. (equal? (program-debug-info-name pdi)
  322. 'return-3))))
  323. (pass-if "program address"
  324. (and=> (find-program-debug-info (program-code return-3))
  325. (lambda (pdi)
  326. (equal? (program-debug-info-addr pdi)
  327. (program-code return-3)))))))
  328. (with-test-prefix "procedure name"
  329. (pass-if-equal 'foo
  330. (procedure-name
  331. (assemble-program
  332. '((begin-program foo ((name . foo)))
  333. (begin-standard-arity () 2 #f)
  334. (load-constant 0 42)
  335. (return-values 2)
  336. (end-arity)
  337. (end-program))))))
  338. (with-test-prefix "simple procedure arity"
  339. (pass-if-equal "#<procedure foo ()>"
  340. (object->string
  341. (assemble-program
  342. '((begin-program foo ((name . foo)))
  343. (begin-standard-arity () 2 #f)
  344. (definition closure 0 scm)
  345. (load-constant 0 42)
  346. (return-values 2)
  347. (end-arity)
  348. (end-program)))))
  349. (pass-if-equal "#<procedure foo (x y)>"
  350. (object->string
  351. (assemble-program
  352. '((begin-program foo ((name . foo)))
  353. (begin-standard-arity (x y) 3 #f)
  354. (definition closure 0 scm)
  355. (definition x 1 scm)
  356. (definition y 2 scm)
  357. (load-constant 1 42)
  358. (return-values 2)
  359. (end-arity)
  360. (end-program)))))
  361. (pass-if-equal "#<procedure foo (x #:optional y . z)>"
  362. (object->string
  363. (assemble-program
  364. '((begin-program foo ((name . foo)))
  365. (begin-opt-arity (x) (y) z 4 #f)
  366. (definition closure 0 scm)
  367. (definition x 1 scm)
  368. (definition y 2 scm)
  369. (definition z 3 scm)
  370. (load-constant 2 42)
  371. (return-values 2)
  372. (end-arity)
  373. (end-program))))))
  374. (with-test-prefix "procedure docstrings"
  375. (pass-if-equal "qux qux"
  376. (procedure-documentation
  377. (assemble-program
  378. '((begin-program foo ((name . foo) (documentation . "qux qux")))
  379. (begin-standard-arity () 2 #f)
  380. (load-constant 0 42)
  381. (return-values 2)
  382. (end-arity)
  383. (end-program))))))
  384. (with-test-prefix "procedure properties"
  385. ;; No properties.
  386. (pass-if-equal '()
  387. (procedure-properties
  388. (assemble-program
  389. '((begin-program foo ())
  390. (begin-standard-arity () 2 #f)
  391. (load-constant 0 42)
  392. (return-values 2)
  393. (end-arity)
  394. (end-program)))))
  395. ;; Name and docstring (which actually don't go out to procprops).
  396. (pass-if-equal '((name . foo)
  397. (documentation . "qux qux"))
  398. (procedure-properties
  399. (assemble-program
  400. '((begin-program foo ((name . foo) (documentation . "qux qux")))
  401. (begin-standard-arity () 2 #f)
  402. (load-constant 0 42)
  403. (return-values 2)
  404. (end-arity)
  405. (end-program)))))
  406. ;; A property that actually needs serialization.
  407. (pass-if-equal '((name . foo)
  408. (documentation . "qux qux")
  409. (moo . "mooooooooooooo"))
  410. (procedure-properties
  411. (assemble-program
  412. '((begin-program foo ((name . foo)
  413. (documentation . "qux qux")
  414. (moo . "mooooooooooooo")))
  415. (begin-standard-arity () 2 #f)
  416. (load-constant 0 42)
  417. (return-values 2)
  418. (end-arity)
  419. (end-program)))))
  420. ;; Procedure-name still works in this case.
  421. (pass-if-equal 'foo
  422. (procedure-name
  423. (assemble-program
  424. '((begin-program foo ((name . foo)
  425. (documentation . "qux qux")
  426. (moo . "mooooooooooooo")))
  427. (begin-standard-arity () 2 #f)
  428. (load-constant 0 42)
  429. (return-values 2)
  430. (end-arity)
  431. (end-program))))))