rtl.test 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. ;;;; Low-level tests of the bytecode assembler -*- mode: scheme; coding: utf-8; -*-
  2. ;;;;
  3. ;;;; Copyright (C) 2010-2015, 2017-2019 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 #t () 1 #f)
  39. (load-constant 0 ,val)
  40. (return-values)
  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 #t () 1 #f)
  86. (load-static-procedure 0 bar)
  87. (return-values)
  88. (end-arity)
  89. (end-program)
  90. (begin-program bar
  91. ((name . bar)))
  92. (begin-standard-arity #t () 1 #f)
  93. (load-constant 0 42)
  94. (return-values)
  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 #t (x) 4 #f)
  107. (definition closure 0 scm)
  108. (definition x 1 scm)
  109. (j fix-body)
  110. (label loop-head)
  111. (=? 1 2)
  112. (je out)
  113. (add 0 1 0)
  114. (add/immediate 1 1 1)
  115. (j loop-head)
  116. (label fix-body)
  117. (load-constant 1 0)
  118. (load-constant 0 0)
  119. (j loop-head)
  120. (label out)
  121. (mov 3 0)
  122. (reset-frame 1)
  123. (return-values)
  124. (end-arity)
  125. (end-program)))))
  126. (sumto 1000))))
  127. (with-test-prefix "call"
  128. (assert-equal 42
  129. (let ((call ;; (lambda (x) (x))
  130. (assemble-program
  131. '((begin-program call
  132. ((name . call)))
  133. (begin-standard-arity #t (f) 7 #f)
  134. (definition closure 0 scm)
  135. (definition f 1 scm)
  136. (mov 1 5)
  137. (call 5 1)
  138. (receive 0 5 7)
  139. (reset-frame 1)
  140. (return-values)
  141. (end-arity)
  142. (end-program)))))
  143. (call (lambda () 42))))
  144. (assert-equal 6
  145. (let ((call-with-3 ;; (lambda (x) (x 3))
  146. (assemble-program
  147. '((begin-program call-with-3
  148. ((name . call-with-3)))
  149. (begin-standard-arity #t (f) 7 #f)
  150. (definition closure 0 scm)
  151. (definition f 1 scm)
  152. (mov 1 5)
  153. (load-constant 0 3)
  154. (call 5 2)
  155. (receive 0 5 7)
  156. (reset-frame 1)
  157. (return-values)
  158. (end-arity)
  159. (end-program)))))
  160. (call-with-3 (lambda (x) (* x 2))))))
  161. (with-test-prefix "tail-call"
  162. (assert-equal 3
  163. (let ((call ;; (lambda (x) (x))
  164. (assemble-program
  165. '((begin-program call
  166. ((name . call)))
  167. (begin-standard-arity #t (f) 2 #f)
  168. (definition closure 0 scm)
  169. (definition f 1 scm)
  170. (mov 1 0)
  171. (reset-frame 1)
  172. (tail-call)
  173. (end-arity)
  174. (end-program)))))
  175. (call (lambda () 3))))
  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 #t (f) 2 #f)
  182. (definition closure 0 scm)
  183. (definition f 1 scm)
  184. (mov 1 0) ;; R0 <- R1
  185. (load-constant 0 3) ;; R1 <- 3
  186. (tail-call)
  187. (end-arity)
  188. (end-program)))))
  189. (call-with-3 (lambda (x) (* x 2))))))
  190. (with-test-prefix "debug contexts"
  191. (let ((return-3 (assemble-program
  192. '((begin-program return-3 ((name . return-3)))
  193. (begin-standard-arity #t () 1 #f)
  194. (load-constant 0 3)
  195. (return-values)
  196. (end-arity)
  197. (end-program)))))
  198. (pass-if "program name"
  199. (and=> (find-program-debug-info (program-code return-3))
  200. (lambda (pdi)
  201. (equal? (program-debug-info-name pdi)
  202. 'return-3))))
  203. (pass-if "program address"
  204. (and=> (find-program-debug-info (program-code return-3))
  205. (lambda (pdi)
  206. (equal? (program-debug-info-addr pdi)
  207. (program-code return-3)))))))
  208. (with-test-prefix "procedure name"
  209. (pass-if-equal 'foo
  210. (procedure-name
  211. (assemble-program
  212. '((begin-program foo ((name . foo)))
  213. (begin-standard-arity #t () 1 #f)
  214. (load-constant 0 42)
  215. (return-values)
  216. (end-arity)
  217. (end-program))))))
  218. (with-test-prefix "simple procedure arity"
  219. (pass-if-equal "#<procedure foo ()>"
  220. (object->string
  221. (assemble-program
  222. '((begin-program foo ((name . foo)))
  223. (begin-standard-arity #t () 1 #f)
  224. (definition closure 0 scm)
  225. (load-constant 0 42)
  226. (return-values)
  227. (end-arity)
  228. (end-program)))))
  229. (pass-if-equal "#<procedure foo (x y)>"
  230. (object->string
  231. (assemble-program
  232. '((begin-program foo ((name . foo)))
  233. (begin-standard-arity #t (x y) 3 #f)
  234. (definition closure 0 scm)
  235. (definition x 1 scm)
  236. (definition y 2 scm)
  237. (load-constant 2 42)
  238. (reset-frame 1)
  239. (return-values)
  240. (end-arity)
  241. (end-program)))))
  242. (pass-if-equal "#<procedure foo (x #:optional y . z)>"
  243. (object->string
  244. (assemble-program
  245. '((begin-program foo ((name . foo)))
  246. (begin-opt-arity #t (x) (y) z 4 #f)
  247. (definition closure 0 scm)
  248. (definition x 1 scm)
  249. (definition y 2 scm)
  250. (definition z 3 scm)
  251. (load-constant 3 42)
  252. (reset-frame 1)
  253. (return-values)
  254. (end-arity)
  255. (end-program))))))
  256. (with-test-prefix "procedure docstrings"
  257. (pass-if-equal "qux qux"
  258. (procedure-documentation
  259. (assemble-program
  260. '((begin-program foo ((name . foo) (documentation . "qux qux")))
  261. (begin-standard-arity #t () 1 #f)
  262. (load-constant 0 42)
  263. (return-values)
  264. (end-arity)
  265. (end-program))))))
  266. (with-test-prefix "procedure properties"
  267. ;; No properties.
  268. (pass-if-equal '()
  269. (procedure-properties
  270. (assemble-program
  271. '((begin-program foo ())
  272. (begin-standard-arity #t () 1 #f)
  273. (load-constant 0 42)
  274. (return-values)
  275. (end-arity)
  276. (end-program)))))
  277. ;; Name and docstring (which actually don't go out to procprops).
  278. (pass-if-equal '((name . foo)
  279. (documentation . "qux qux"))
  280. (procedure-properties
  281. (assemble-program
  282. '((begin-program foo ((name . foo) (documentation . "qux qux")))
  283. (begin-standard-arity #t () 1 #f)
  284. (load-constant 0 42)
  285. (return-values)
  286. (end-arity)
  287. (end-program)))))
  288. ;; A property that actually needs serialization.
  289. (pass-if-equal '((name . foo)
  290. (documentation . "qux qux")
  291. (moo . "mooooooooooooo"))
  292. (procedure-properties
  293. (assemble-program
  294. '((begin-program foo ((name . foo)
  295. (documentation . "qux qux")
  296. (moo . "mooooooooooooo")))
  297. (begin-standard-arity #t () 1 #f)
  298. (load-constant 0 42)
  299. (return-values)
  300. (end-arity)
  301. (end-program)))))
  302. ;; Procedure-name still works in this case.
  303. (pass-if-equal 'foo
  304. (procedure-name
  305. (assemble-program
  306. '((begin-program foo ((name . foo)
  307. (documentation . "qux qux")
  308. (moo . "mooooooooooooo")))
  309. (begin-standard-arity #t () 1 #f)
  310. (load-constant 0 42)
  311. (return-values)
  312. (end-arity)
  313. (end-program))))))