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