rtl.test 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474
  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. (define-syntax-rule (assert-bad-constants val ...)
  74. (begin
  75. (pass-if-exception (object->string val) exception:miscellaneous-error
  76. (return-constant val))
  77. ...))
  78. (with-test-prefix "bad constants"
  79. (assert-bad-constants (make-symbol "foo")
  80. (lambda () 100)))
  81. (with-test-prefix "static procedure"
  82. (assert-equal 42
  83. (((assemble-program `((begin-program foo
  84. ((name . foo)))
  85. (begin-standard-arity () 2 #f)
  86. (load-static-procedure 0 bar)
  87. (return-values 2)
  88. (end-arity)
  89. (end-program)
  90. (begin-program bar
  91. ((name . bar)))
  92. (begin-standard-arity () 2 #f)
  93. (load-constant 0 42)
  94. (return-values 2)
  95. (end-arity)
  96. (end-program)))))))
  97. (with-test-prefix "loop"
  98. (assert-equal (* 999 500)
  99. (let ((sumto
  100. (assemble-program
  101. ;; 0: limit
  102. ;; 1: n
  103. ;; 2: accum
  104. '((begin-program countdown
  105. ((name . countdown)))
  106. (begin-standard-arity (x) 4 #f)
  107. (definition closure 0 scm)
  108. (definition x 1 scm)
  109. (br fix-body)
  110. (label loop-head)
  111. (br-if-= 1 2 #f out)
  112. (add 0 1 0)
  113. (add/immediate 1 1 1)
  114. (br loop-head)
  115. (label fix-body)
  116. (load-constant 1 0)
  117. (load-constant 0 0)
  118. (br loop-head)
  119. (label out)
  120. (mov 2 0)
  121. (return-values 2)
  122. (end-arity)
  123. (end-program)))))
  124. (sumto 1000))))
  125. (with-test-prefix "accum"
  126. (assert-equal (+ 1 2 3)
  127. (let ((make-accum
  128. (assemble-program
  129. ;; 0: elt
  130. ;; 1: tail
  131. ;; 2: head
  132. '((begin-program make-accum
  133. ((name . make-accum)))
  134. (begin-standard-arity () 3 #f)
  135. (load-constant 1 0)
  136. (box 1 1)
  137. (make-closure 0 accum 1)
  138. (free-set! 0 1 0)
  139. (mov 1 0)
  140. (return-values 2)
  141. (end-arity)
  142. (end-program)
  143. (begin-program accum
  144. ((name . accum)))
  145. (begin-standard-arity (x) 4 #f)
  146. (definition closure 0 scm)
  147. (definition x 1 scm)
  148. (free-ref 1 3 0)
  149. (box-ref 0 1)
  150. (add 0 0 2)
  151. (box-set! 1 0)
  152. (mov 2 0)
  153. (return-values 2)
  154. (end-arity)
  155. (end-program)))))
  156. (let ((accum (make-accum)))
  157. (accum 1)
  158. (accum 2)
  159. (accum 3)))))
  160. (with-test-prefix "call"
  161. (assert-equal 42
  162. (let ((call ;; (lambda (x) (x))
  163. (assemble-program
  164. '((begin-program call
  165. ((name . call)))
  166. (begin-standard-arity (f) 7 #f)
  167. (definition closure 0 scm)
  168. (definition f 1 scm)
  169. (mov 1 5)
  170. (call 5 1)
  171. (receive 1 5 7)
  172. (return-values 2)
  173. (end-arity)
  174. (end-program)))))
  175. (call (lambda () 42))))
  176. (assert-equal 6
  177. (let ((call-with-3 ;; (lambda (x) (x 3))
  178. (assemble-program
  179. '((begin-program call-with-3
  180. ((name . call-with-3)))
  181. (begin-standard-arity (f) 7 #f)
  182. (definition closure 0 scm)
  183. (definition f 1 scm)
  184. (mov 1 5)
  185. (load-constant 0 3)
  186. (call 5 2)
  187. (receive 1 5 7)
  188. (return-values 2)
  189. (end-arity)
  190. (end-program)))))
  191. (call-with-3 (lambda (x) (* x 2))))))
  192. (with-test-prefix "tail-call"
  193. (assert-equal 3
  194. (let ((call ;; (lambda (x) (x))
  195. (assemble-program
  196. '((begin-program call
  197. ((name . call)))
  198. (begin-standard-arity (f) 2 #f)
  199. (definition closure 0 scm)
  200. (definition f 1 scm)
  201. (mov 1 0)
  202. (tail-call 1)
  203. (end-arity)
  204. (end-program)))))
  205. (call (lambda () 3))))
  206. (assert-equal 6
  207. (let ((call-with-3 ;; (lambda (x) (x 3))
  208. (assemble-program
  209. '((begin-program call-with-3
  210. ((name . call-with-3)))
  211. (begin-standard-arity (f) 2 #f)
  212. (definition closure 0 scm)
  213. (definition f 1 scm)
  214. (mov 1 0) ;; R0 <- R1
  215. (load-constant 0 3) ;; R1 <- 3
  216. (tail-call 2)
  217. (end-arity)
  218. (end-program)))))
  219. (call-with-3 (lambda (x) (* x 2))))))
  220. (with-test-prefix "cached-toplevel-ref"
  221. (assert-equal 5.0
  222. (let ((get-sqrt-trampoline
  223. (assemble-program
  224. '((begin-program get-sqrt-trampoline
  225. ((name . get-sqrt-trampoline)))
  226. (begin-standard-arity () 2 #f)
  227. (current-module 0)
  228. (cache-current-module! 0 sqrt-scope)
  229. (load-static-procedure 0 sqrt-trampoline)
  230. (return-values 2)
  231. (end-arity)
  232. (end-program)
  233. (begin-program sqrt-trampoline
  234. ((name . sqrt-trampoline)))
  235. (begin-standard-arity (x) 3 #f)
  236. (definition closure 0 scm)
  237. (definition x 1 scm)
  238. (cached-toplevel-box 0 sqrt-scope sqrt #t)
  239. (box-ref 2 0)
  240. (tail-call 2)
  241. (end-arity)
  242. (end-program)))))
  243. ((get-sqrt-trampoline) 25.0))))
  244. (define *top-val* 0)
  245. (with-test-prefix "cached-toplevel-set!"
  246. (let ((prev *top-val*))
  247. (assert-equal (1+ prev)
  248. (let ((make-top-incrementor
  249. (assemble-program
  250. '((begin-program make-top-incrementor
  251. ((name . make-top-incrementor)))
  252. (begin-standard-arity () 2 #f)
  253. (current-module 0)
  254. (cache-current-module! 0 top-incrementor)
  255. (load-static-procedure 0 top-incrementor)
  256. (return-values 2)
  257. (end-arity)
  258. (end-program)
  259. (begin-program top-incrementor
  260. ((name . top-incrementor)))
  261. (begin-standard-arity () 3 #f)
  262. (cached-toplevel-box 1 top-incrementor *top-val* #t)
  263. (box-ref 0 1)
  264. (add/immediate 0 0 1)
  265. (box-set! 1 0)
  266. (return-values 1)
  267. (end-arity)
  268. (end-program)))))
  269. ((make-top-incrementor))
  270. *top-val*))))
  271. (with-test-prefix "cached-module-ref"
  272. (assert-equal 5.0
  273. (let ((get-sqrt-trampoline
  274. (assemble-program
  275. '((begin-program get-sqrt-trampoline
  276. ((name . get-sqrt-trampoline)))
  277. (begin-standard-arity () 2 #f)
  278. (load-static-procedure 0 sqrt-trampoline)
  279. (return-values 2)
  280. (end-arity)
  281. (end-program)
  282. (begin-program sqrt-trampoline
  283. ((name . sqrt-trampoline)))
  284. (begin-standard-arity (x) 3 #f)
  285. (definition closure 0 scm)
  286. (definition x 1 scm)
  287. (cached-module-box 0 (guile) sqrt #t #t)
  288. (box-ref 2 0)
  289. (tail-call 2)
  290. (end-arity)
  291. (end-program)))))
  292. ((get-sqrt-trampoline) 25.0))))
  293. (with-test-prefix "cached-module-set!"
  294. (let ((prev *top-val*))
  295. (assert-equal (1+ prev)
  296. (let ((make-top-incrementor
  297. (assemble-program
  298. '((begin-program make-top-incrementor
  299. ((name . make-top-incrementor)))
  300. (begin-standard-arity () 2 #f)
  301. (load-static-procedure 0 top-incrementor)
  302. (return-values 2)
  303. (end-arity)
  304. (end-program)
  305. (begin-program top-incrementor
  306. ((name . top-incrementor)))
  307. (begin-standard-arity () 3 #f)
  308. (cached-module-box 1 (tests bytecode) *top-val* #f #t)
  309. (box-ref 0 1)
  310. (add/immediate 0 0 1)
  311. (box-set! 1 0)
  312. (mov 1 0)
  313. (return-values 2)
  314. (end-arity)
  315. (end-program)))))
  316. ((make-top-incrementor))
  317. *top-val*))))
  318. (with-test-prefix "debug contexts"
  319. (let ((return-3 (assemble-program
  320. '((begin-program return-3 ((name . return-3)))
  321. (begin-standard-arity () 2 #f)
  322. (load-constant 0 3)
  323. (return-values 2)
  324. (end-arity)
  325. (end-program)))))
  326. (pass-if "program name"
  327. (and=> (find-program-debug-info (program-code return-3))
  328. (lambda (pdi)
  329. (equal? (program-debug-info-name pdi)
  330. 'return-3))))
  331. (pass-if "program address"
  332. (and=> (find-program-debug-info (program-code return-3))
  333. (lambda (pdi)
  334. (equal? (program-debug-info-addr pdi)
  335. (program-code return-3)))))))
  336. (with-test-prefix "procedure name"
  337. (pass-if-equal 'foo
  338. (procedure-name
  339. (assemble-program
  340. '((begin-program foo ((name . foo)))
  341. (begin-standard-arity () 2 #f)
  342. (load-constant 0 42)
  343. (return-values 2)
  344. (end-arity)
  345. (end-program))))))
  346. (with-test-prefix "simple procedure arity"
  347. (pass-if-equal "#<procedure foo ()>"
  348. (object->string
  349. (assemble-program
  350. '((begin-program foo ((name . foo)))
  351. (begin-standard-arity () 2 #f)
  352. (definition closure 0 scm)
  353. (load-constant 0 42)
  354. (return-values 2)
  355. (end-arity)
  356. (end-program)))))
  357. (pass-if-equal "#<procedure foo (x y)>"
  358. (object->string
  359. (assemble-program
  360. '((begin-program foo ((name . foo)))
  361. (begin-standard-arity (x y) 3 #f)
  362. (definition closure 0 scm)
  363. (definition x 1 scm)
  364. (definition y 2 scm)
  365. (load-constant 1 42)
  366. (return-values 2)
  367. (end-arity)
  368. (end-program)))))
  369. (pass-if-equal "#<procedure foo (x #:optional y . z)>"
  370. (object->string
  371. (assemble-program
  372. '((begin-program foo ((name . foo)))
  373. (begin-opt-arity (x) (y) z 4 #f)
  374. (definition closure 0 scm)
  375. (definition x 1 scm)
  376. (definition y 2 scm)
  377. (definition z 3 scm)
  378. (load-constant 2 42)
  379. (return-values 2)
  380. (end-arity)
  381. (end-program))))))
  382. (with-test-prefix "procedure docstrings"
  383. (pass-if-equal "qux qux"
  384. (procedure-documentation
  385. (assemble-program
  386. '((begin-program foo ((name . foo) (documentation . "qux qux")))
  387. (begin-standard-arity () 2 #f)
  388. (load-constant 0 42)
  389. (return-values 2)
  390. (end-arity)
  391. (end-program))))))
  392. (with-test-prefix "procedure properties"
  393. ;; No properties.
  394. (pass-if-equal '()
  395. (procedure-properties
  396. (assemble-program
  397. '((begin-program foo ())
  398. (begin-standard-arity () 2 #f)
  399. (load-constant 0 42)
  400. (return-values 2)
  401. (end-arity)
  402. (end-program)))))
  403. ;; Name and docstring (which actually don't go out to procprops).
  404. (pass-if-equal '((name . foo)
  405. (documentation . "qux qux"))
  406. (procedure-properties
  407. (assemble-program
  408. '((begin-program foo ((name . foo) (documentation . "qux qux")))
  409. (begin-standard-arity () 2 #f)
  410. (load-constant 0 42)
  411. (return-values 2)
  412. (end-arity)
  413. (end-program)))))
  414. ;; A property that actually needs serialization.
  415. (pass-if-equal '((name . foo)
  416. (documentation . "qux qux")
  417. (moo . "mooooooooooooo"))
  418. (procedure-properties
  419. (assemble-program
  420. '((begin-program foo ((name . foo)
  421. (documentation . "qux qux")
  422. (moo . "mooooooooooooo")))
  423. (begin-standard-arity () 2 #f)
  424. (load-constant 0 42)
  425. (return-values 2)
  426. (end-arity)
  427. (end-program)))))
  428. ;; Procedure-name still works in this case.
  429. (pass-if-equal 'foo
  430. (procedure-name
  431. (assemble-program
  432. '((begin-program foo ((name . foo)
  433. (documentation . "qux qux")
  434. (moo . "mooooooooooooo")))
  435. (begin-standard-arity () 2 #f)
  436. (load-constant 0 42)
  437. (return-values 2)
  438. (end-arity)
  439. (end-program))))))