mirror of
https://git.savannah.gnu.org/git/guile.git
synced 2025-05-20 19:50:24 +02:00
Change `write-bytecode' to accept a bytevector.
* module/language/assembly/compile-bytecode.scm (write-bytecode): Replace the WRITE-BYTE and GET-ADDR parameters with PORT. New ADDRESS and EMIT-OPCODE? parameters. Callers updated. [write-byte, get-addr]: New procedures. Adjust to write to PORT. (compile-bytecode): Update accordingly. * test-suite/tests/asm-to-bytecode.test (munge-bytecode): Return a bytevector instead of a u8vector. (comp-test): Deal with bytevectors.
This commit is contained in:
parent
0c368d2b28
commit
bde92e6b3b
2 changed files with 41 additions and 38 deletions
|
@ -24,27 +24,32 @@
|
||||||
#:use-module (system vm instruction)
|
#:use-module (system vm instruction)
|
||||||
#:use-module (srfi srfi-4)
|
#:use-module (srfi srfi-4)
|
||||||
#:use-module (rnrs bytevector)
|
#:use-module (rnrs bytevector)
|
||||||
|
#:use-module (rnrs io ports)
|
||||||
#:use-module ((srfi srfi-1) #:select (fold))
|
#:use-module ((srfi srfi-1) #:select (fold))
|
||||||
|
#:use-module ((srfi srfi-26) #:select (cut))
|
||||||
#:use-module ((system vm objcode) #:select (byte-order))
|
#:use-module ((system vm objcode) #:select (byte-order))
|
||||||
#:export (compile-bytecode write-bytecode))
|
#:export (compile-bytecode write-bytecode))
|
||||||
|
|
||||||
(define (compile-bytecode assembly env . opts)
|
(define (compile-bytecode assembly env . opts)
|
||||||
(pmatch assembly
|
(pmatch assembly
|
||||||
((load-program . _)
|
((load-program . _)
|
||||||
;; the 1- and -1 are so that we drop the load-program byte
|
(call-with-values open-bytevector-output-port
|
||||||
(letrec ((v (make-u8vector (1- (byte-length assembly))))
|
(lambda (port get-bytevector)
|
||||||
(i -1)
|
;; Don't emit the `load-program' byte.
|
||||||
(write-byte (lambda (b)
|
(write-bytecode assembly port '() 0 #f)
|
||||||
(if (>= i 0) (u8vector-set! v i b))
|
(values (get-bytevector) env env))))
|
||||||
(set! i (1+ i))))
|
|
||||||
(get-addr (lambda () i)))
|
|
||||||
(write-bytecode assembly write-byte get-addr '())
|
|
||||||
(if (= i (u8vector-length v))
|
|
||||||
(values v env env)
|
|
||||||
(error "incorrect length in assembly" i (u8vector-length v)))))
|
|
||||||
(else (error "bad assembly" assembly))))
|
(else (error "bad assembly" assembly))))
|
||||||
|
|
||||||
(define (write-bytecode asm write-byte get-addr labels)
|
(define (write-bytecode asm port labels address emit-opcode?)
|
||||||
|
;; Write ASM's bytecode to PORT, a (binary) output port. If EMIT-OPCODE? is
|
||||||
|
;; false, don't emit bytecode for the first opcode encountered. Assume code
|
||||||
|
;; starts at ADDRESS (an integer). LABELS is assumed to be an alist mapping
|
||||||
|
;; labels to addresses.
|
||||||
|
(define write-byte (cut put-u8 port <>))
|
||||||
|
(define get-addr
|
||||||
|
(let ((start (port-position port)))
|
||||||
|
(lambda ()
|
||||||
|
(+ address (- (port-position port) start)))))
|
||||||
(define (write-char c)
|
(define (write-char c)
|
||||||
(write-byte (char->integer c)))
|
(write-byte (char->integer c)))
|
||||||
(define (write-string s)
|
(define (write-string s)
|
||||||
|
@ -102,28 +107,24 @@
|
||||||
(else (error "unknown endianness" byte-order)))))
|
(else (error "unknown endianness" byte-order)))))
|
||||||
(let ((opcode (instruction->opcode inst))
|
(let ((opcode (instruction->opcode inst))
|
||||||
(len (instruction-length inst)))
|
(len (instruction-length inst)))
|
||||||
(write-byte opcode)
|
(if emit-opcode?
|
||||||
|
(write-byte opcode))
|
||||||
(pmatch asm
|
(pmatch asm
|
||||||
((load-program ,labels ,length ,meta . ,code)
|
((load-program ,labels ,length ,meta . ,code)
|
||||||
(write-uint32 length)
|
(write-uint32 length)
|
||||||
(write-uint32 (if meta (1- (byte-length meta)) 0))
|
(write-uint32 (if meta (1- (byte-length meta)) 0))
|
||||||
(letrec ((i 0)
|
(fold (lambda (asm address)
|
||||||
(write (lambda (x) (set! i (1+ i)) (write-byte x)))
|
(let ((start (port-position port)))
|
||||||
(get-addr (lambda () i)))
|
(write-bytecode asm port labels address #t)
|
||||||
(for-each (lambda (asm)
|
(+ address (- (port-position port) start))))
|
||||||
(write-bytecode asm write get-addr labels))
|
0
|
||||||
code))
|
code)
|
||||||
(if meta
|
(if meta
|
||||||
;; don't write the load-program byte for metadata
|
;; Don't emit the `load-program' byte for metadata. Note that
|
||||||
(letrec ((i -1)
|
;; META's bytecode meets the alignment requirements of
|
||||||
(write (lambda (x)
|
;; `scm_objcode', thanks to the alignment computed in `(language
|
||||||
(set! i (1+ i))
|
;; assembly)'.
|
||||||
(if (> i 0) (write-byte x))))
|
(write-bytecode meta port '() 0 #f)))
|
||||||
(get-addr (lambda () i)))
|
|
||||||
;; META's bytecode meets the alignment requirements of
|
|
||||||
;; `scm_objcode', thanks to the alignment computed in
|
|
||||||
;; `(language assembly)'.
|
|
||||||
(write-bytecode meta write get-addr '()))))
|
|
||||||
((make-char32 ,x) (write-uint32-be x))
|
((make-char32 ,x) (write-uint32-be x))
|
||||||
((load-number ,str) (write-loader str))
|
((load-number ,str) (write-loader str))
|
||||||
((load-string ,str) (write-loader str))
|
((load-string ,str) (write-loader str))
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
(define-module (test-suite tests asm-to-bytecode)
|
(define-module (test-suite tests asm-to-bytecode)
|
||||||
#:use-module (rnrs bytevector)
|
#:use-module (rnrs bytevector)
|
||||||
|
#:use-module ((rnrs io ports) #:select (open-bytevector-output-port))
|
||||||
#:use-module (test-suite lib)
|
#:use-module (test-suite lib)
|
||||||
#:use-module (system vm instruction)
|
#:use-module (system vm instruction)
|
||||||
#:use-module (language assembly compile-bytecode))
|
#:use-module (language assembly compile-bytecode))
|
||||||
|
@ -32,7 +33,7 @@
|
||||||
(define (munge-bytecode v)
|
(define (munge-bytecode v)
|
||||||
(let lp ((i 0) (out '()))
|
(let lp ((i 0) (out '()))
|
||||||
(if (= i (vector-length v))
|
(if (= i (vector-length v))
|
||||||
(list->u8vector (reverse out))
|
(u8-list->bytevector (reverse out))
|
||||||
(let ((x (vector-ref v i)))
|
(let ((x (vector-ref v i)))
|
||||||
(cond
|
(cond
|
||||||
((symbol? x)
|
((symbol? x)
|
||||||
|
@ -44,16 +45,17 @@
|
||||||
(else (error "bad test bytecode" x)))))))
|
(else (error "bad test bytecode" x)))))))
|
||||||
|
|
||||||
(define (comp-test x y)
|
(define (comp-test x y)
|
||||||
(let* ((y (munge-bytecode y))
|
(let* ((y (munge-bytecode y))
|
||||||
(len (u8vector-length y))
|
(len (bytevector-length y))
|
||||||
(v (make-u8vector len))
|
(v #f))
|
||||||
(i 0))
|
|
||||||
(define (write-byte b) (u8vector-set! v i b) (set! i (1+ i)))
|
|
||||||
(define (get-addr) i)
|
|
||||||
(run-test `(length ,x) #t
|
(run-test `(length ,x) #t
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(write-bytecode x write-byte get-addr '())
|
(call-with-values open-bytevector-output-port
|
||||||
(= i len)))
|
(lambda (port get-bytevector)
|
||||||
|
(write-bytecode x port '() 0 #t)
|
||||||
|
(set! v (get-bytevector))
|
||||||
|
(= (bytevector-length v) len)))))
|
||||||
(run-test `(compile-equal? ,x ,y) #t
|
(run-test `(compile-equal? ,x ,y) #t
|
||||||
(lambda ()
|
(lambda ()
|
||||||
(equal? v y)))))
|
(equal? v y)))))
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue