asm-to-bytecode.test 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. ;;;; Assembly to bytecode compilation -*- mode: scheme; coding: utf-8; -*-
  2. ;;;;
  3. ;;;; Copyright (C) 2010, 2011, 2012 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 (test-suite tests asm-to-bytecode)
  19. #:use-module (rnrs bytevectors)
  20. #:use-module ((rnrs io ports) #:select (open-bytevector-output-port))
  21. #:use-module (test-suite lib)
  22. #:use-module (system vm instruction)
  23. #:use-module (system vm objcode)
  24. #:use-module (system base target)
  25. #:use-module (language assembly)
  26. #:use-module (language assembly compile-bytecode))
  27. (define (->u8-list sym val)
  28. (let ((entry (assq-ref `((uint16 2 ,bytevector-u16-native-set!)
  29. (uint32 4 ,bytevector-u32-native-set!))
  30. sym)))
  31. (or entry (error "unknown sym" sym))
  32. (let ((bv (make-bytevector (car entry))))
  33. ((cadr entry) bv 0 val)
  34. (bytevector->u8-list bv))))
  35. (define (munge-bytecode v)
  36. (let lp ((i 0) (out '()))
  37. (if (= i (vector-length v))
  38. (u8-list->bytevector (reverse out))
  39. (let ((x (vector-ref v i)))
  40. (cond
  41. ((symbol? x)
  42. (lp (1+ i) (cons (instruction->opcode x) out)))
  43. ((integer? x)
  44. (lp (1+ i) (cons x out)))
  45. ((pair? x)
  46. (lp (1+ i) (append (reverse (apply ->u8-list x)) out)))
  47. (else (error "bad test bytecode" x)))))))
  48. (define (comp-test x y)
  49. (let* ((y (munge-bytecode y))
  50. (len (bytevector-length y))
  51. (v #f))
  52. (run-test `(length ,x) #t
  53. (lambda ()
  54. (let* ((wrapped `(load-program () ,(byte-length x) #f ,x))
  55. (bv (compile-bytecode wrapped '())))
  56. (set! v (make-bytevector (- (bytevector-length bv) 8)))
  57. (bytevector-copy! bv 8 v 0 (bytevector-length v))
  58. (= (bytevector-length v) len))))
  59. (run-test `(compile-equal? ,x ,y) #t
  60. (lambda ()
  61. (equal? v y)))))
  62. (with-test-prefix "compiler"
  63. (with-test-prefix "asm-to-bytecode"
  64. (comp-test '(make-int8 3)
  65. #(make-int8 3))
  66. (comp-test '(load-number "3.14")
  67. (vector 'load-number 0 0 4 (char->integer #\3) (char->integer #\.)
  68. (char->integer #\1) (char->integer #\4)))
  69. (comp-test '(load-string "foo")
  70. (vector 'load-string 0 0 3 (char->integer #\f) (char->integer #\o)
  71. (char->integer #\o)))
  72. (comp-test '(load-symbol "foo")
  73. (vector 'load-symbol 0 0 3 (char->integer #\f) (char->integer #\o)
  74. (char->integer #\o)))
  75. (comp-test '(load-string "æ") ;; a non-ASCII Latin-1 string
  76. (vector 'load-string 0 0 1 230))
  77. (comp-test '(load-wide-string "λ")
  78. (apply vector 'load-wide-string 0 0 4
  79. (if (eq? (native-endianness) (endianness little))
  80. '(187 3 0 0)
  81. '(0 0 3 187))))
  82. (comp-test '(load-program () 3 #f (make-int8 3) (return))
  83. #(load-program
  84. (uint32 3) ;; len
  85. (uint32 0) ;; metalen
  86. make-int8 3
  87. return))
  88. ;; the nops are to pad meta to an 8-byte alignment. not strictly
  89. ;; necessary for this test, but representative of the common case.
  90. (comp-test '(load-program () 8
  91. (load-program () 3
  92. #f
  93. (make-int8 3) (return))
  94. (make-int8 3) (return)
  95. (nop) (nop) (nop) (nop) (nop))
  96. #(load-program
  97. (uint32 8) ;; len
  98. (uint32 11) ;; metalen
  99. make-int8 3
  100. return
  101. nop nop nop nop nop
  102. (uint32 3) ;; len
  103. (uint32 0) ;; metalen
  104. make-int8 3
  105. return))))
  106. (define (test-triplet cpu vendor os)
  107. (let ((triplet (string-append cpu "-" vendor "-" os)))
  108. (pass-if (format #f "triplet ~a" triplet)
  109. (with-target triplet
  110. (lambda ()
  111. (and (string=? (target-cpu) cpu)
  112. (string=? (target-vendor) vendor)
  113. (string=? (target-os) os)))))))
  114. (define (native-cpu)
  115. (with-target %host-type target-cpu))
  116. (define (native-word-size)
  117. ((@ (system foreign) sizeof) '*))
  118. (define %objcode-cookie-size
  119. (string-length "GOOF----LE-8"))
  120. (define (test-target triplet endian word-size)
  121. (pass-if (format #f "target `~a' honored" triplet)
  122. (call-with-values (lambda ()
  123. (open-bytevector-output-port))
  124. (lambda (p get-objcode)
  125. (with-target triplet
  126. (lambda ()
  127. (let ((word-size
  128. ;; When the target is the native CPU, rather trust
  129. ;; the native CPU's word size. This is because
  130. ;; Debian's `sparc64-linux-gnu' port, for instance,
  131. ;; actually has a 32-bit user-land, for instance (see
  132. ;; <http://www.debian.org/ports/sparc/#sparc64bit>
  133. ;; for details.)
  134. (if (string=? (native-cpu) (target-cpu))
  135. (native-word-size)
  136. word-size))
  137. (b (compile-bytecode
  138. '(load-program () 16 #f
  139. (assert-nargs-ee/locals 1)
  140. (make-int8 77)
  141. (toplevel-ref 1)
  142. (local-ref 0)
  143. (mul)
  144. (add)
  145. (return)
  146. (nop) (nop) (nop)
  147. (nop) (nop))
  148. #f)))
  149. (write-objcode (bytecode->objcode b) p)
  150. (let ((cookie (make-bytevector %objcode-cookie-size))
  151. (expected (format #f "GOOF----~a-~a"
  152. (cond ((eq? endian (endianness little))
  153. "LE")
  154. ((eq? endian (endianness big))
  155. "BE")
  156. (else
  157. (error "unknown endianness"
  158. endian)))
  159. word-size)))
  160. (bytevector-copy! (get-objcode) 0 cookie 0
  161. %objcode-cookie-size)
  162. (string=? (utf8->string cookie) expected)))))))))
  163. (with-test-prefix "cross-compilation"
  164. (test-triplet "i586" "pc" "gnu0.3")
  165. (test-triplet "x86_64" "unknown" "linux-gnu")
  166. (test-triplet "x86_64" "unknown" "kfreebsd-gnu")
  167. (test-target "i586-pc-gnu0.3" (endianness little) 4)
  168. (test-target "x86_64-pc-linux-gnu" (endianness little) 8)
  169. (test-target "powerpc-unknown-linux-gnu" (endianness big) 4)
  170. (test-target "sparc64-unknown-freebsd8.2" (endianness big) 8)
  171. (pass-if-exception "unknown target"
  172. exception:miscellaneous-error
  173. (call-with-values (lambda ()
  174. (open-bytevector-output-port))
  175. (lambda (p get-objcode)
  176. (let* ((b (compile-bytecode '(load-program () 3 #f
  177. (make-int8 77)
  178. (return))
  179. #f))
  180. (o (bytecode->objcode b)))
  181. (with-target "fcpu-unknown-gnu1.0"
  182. (lambda ()
  183. (write-objcode o p))))))))
  184. ;; Local Variables:
  185. ;; eval: (put 'with-target 'scheme-indent-function 1)
  186. ;; End: