Stateful assembler like Guile, hope to extend to interface for compiler
This commit is contained in:
parent
330aca002f
commit
490840e577
@ -1,5 +1,5 @@
|
|||||||
(define-module (scmvm debugger)
|
(define-module (scmvm debugger)
|
||||||
#:use-module (scmvm assembler)
|
#:use-module (scmvm language assembler)
|
||||||
#:use-module (scmvm vm)
|
#:use-module (scmvm vm)
|
||||||
#:use-module (srfi srfi-1)
|
#:use-module (srfi srfi-1)
|
||||||
#:use-module (srfi srfi-9)
|
#:use-module (srfi srfi-9)
|
||||||
@ -23,12 +23,12 @@
|
|||||||
(continuation debugger-continuation debugger-continuation-set!)
|
(continuation debugger-continuation debugger-continuation-set!)
|
||||||
(stepping debugger-stepping? debugger-stepping-set!))
|
(stepping debugger-stepping? debugger-stepping-set!))
|
||||||
|
|
||||||
(define (make-breakpoints labels)
|
(define (make-breakpoints asm)
|
||||||
(define the-breakpoints '())
|
(define the-breakpoints '())
|
||||||
(define (->index index/label)
|
(define (->index index/label)
|
||||||
(if (number? index/label)
|
(if (number? index/label)
|
||||||
index/label
|
index/label
|
||||||
(assq-ref labels index/label)))
|
(car (hash-ref (assembler-labels asm) index/label))))
|
||||||
(define-syntax-rule (ilambda (i) e ...)
|
(define-syntax-rule (ilambda (i) e ...)
|
||||||
(lambda (v) (let ([i (->index v)]) e ...)))
|
(lambda (v) (let ([i (->index v)]) e ...)))
|
||||||
(match-lambda
|
(match-lambda
|
||||||
@ -44,11 +44,11 @@
|
|||||||
(ilambda (i) (assq-ref the-breakpoints i))]))
|
(ilambda (i) (assq-ref the-breakpoints i))]))
|
||||||
|
|
||||||
(define (make-debugger* source)
|
(define (make-debugger* source)
|
||||||
(define-values (prgm symbols)
|
(define-values (prgm asm)
|
||||||
(call-with-values open-bytevector-output-port
|
(call-with-values open-bytevector-output-port
|
||||||
(lambda (port get-bv)
|
(lambda (port get-bv)
|
||||||
(define symbols (assemble source port))
|
(define asm (assemble source port))
|
||||||
(values (get-bv) symbols))))
|
(values (get-bv) asm))))
|
||||||
(define the-debugger #f)
|
(define the-debugger #f)
|
||||||
(define (debug)
|
(define (debug)
|
||||||
(shift k
|
(shift k
|
||||||
@ -58,7 +58,7 @@
|
|||||||
(k))))
|
(k))))
|
||||||
(define vm (make-vm #:debugger debug))
|
(define vm (make-vm #:debugger debug))
|
||||||
(vm-load-program! vm prgm)
|
(vm-load-program! vm prgm)
|
||||||
(set! the-debugger (make-debugger vm source (make-breakpoints symbols) #f #f))
|
(set! the-debugger (make-debugger vm source (make-breakpoints asm) #f #f))
|
||||||
(debugger-breakpoint-add! the-debugger 1)
|
(debugger-breakpoint-add! the-debugger 1)
|
||||||
(reset (run-vm vm))
|
(reset (run-vm vm))
|
||||||
the-debugger)
|
the-debugger)
|
||||||
|
@ -1,11 +1,12 @@
|
|||||||
(define-module (scmvm language assembler)
|
(define-module (scmvm language assembler)
|
||||||
#:use-module (srfi srfi-1)
|
#:use-module (srfi srfi-1)
|
||||||
|
#:use-module (srfi srfi-9)
|
||||||
|
#:use-module (srfi srfi-26)
|
||||||
#:use-module (scmvm vm)
|
#:use-module (scmvm vm)
|
||||||
#:use-module (rnrs bytevectors)
|
#:use-module (rnrs bytevectors)
|
||||||
#:use-module (rnrs io ports)
|
#:use-module ((scheme base) #:select (write-bytevector))
|
||||||
#:use-module ((scheme base)
|
#:export (assemble (make-assembler* . make-assembler)
|
||||||
#:select (write-u8 write-bytevector))
|
assembler-labels update-references))
|
||||||
#:export (assemble))
|
|
||||||
|
|
||||||
(define *aliases*
|
(define *aliases*
|
||||||
'((if . branch)))
|
'((if . branch)))
|
||||||
@ -31,58 +32,91 @@
|
|||||||
(not (variable? x))
|
(not (variable? x))
|
||||||
(not (ref? x))
|
(not (ref? x))
|
||||||
(not (set!? x))))
|
(not (set!? x))))
|
||||||
(define (instruction-size inst)
|
|
||||||
(case (car inst)
|
|
||||||
[(push) 5]
|
|
||||||
[(ref set!) 6]
|
|
||||||
[else 1]))
|
|
||||||
|
|
||||||
(define (label-pass instructions address)
|
(define (make-label) (cons #f '()))
|
||||||
(cond
|
|
||||||
[(null? instructions) '()]
|
|
||||||
[(label? (car instructions))
|
|
||||||
(acons (car instructions) address (label-pass (cdr instructions) address))]
|
|
||||||
[(variable? (car instructions))
|
|
||||||
(acons (cadar instructions) address (label-pass (cdr instructions) (+ address 4)))]
|
|
||||||
[else
|
|
||||||
(label-pass (cdr instructions) (+ address (instruction-size (car instructions))))]))
|
|
||||||
|
|
||||||
(define (write-word word)
|
(define-record-type <assembler>
|
||||||
(define bv (make-bytevector 4))
|
(make-assembler pos buf labels source)
|
||||||
(bytevector-u32-native-set! bv 0 word)
|
assembler?
|
||||||
(write-bytevector bv))
|
(pos assembler-pos assembler-pos-set!)
|
||||||
|
(buf assembler-buf assembler-buf-set!)
|
||||||
|
(labels assembler-labels)
|
||||||
|
(source assembler-source))
|
||||||
|
|
||||||
(define (assembly-pass seq labels)
|
(define (make-assembler*)
|
||||||
(cond
|
(make-assembler 0 (make-bytevector 1024) (make-hash-table) (make-hash-table)))
|
||||||
[(null? seq) '()]
|
|
||||||
[(label? (car seq)) (assembly-pass (cdr seq) labels)]
|
(define (assembler-buf-grow! asm)
|
||||||
[(variable? (car seq))
|
(let ([buf (make-bytevector (ash (bytevector-length (assembler-buf asm)) -1))])
|
||||||
(write-word (caddar seq))
|
(bytevector-copy! (assembler-buf asm) 0 buf 0 (bytevector-length (assembler-buf asm)))
|
||||||
(assembly-pass (cdr seq) labels)]
|
(assembler-buf-set! asm buf)))
|
||||||
[(ref? (car seq))
|
|
||||||
(write-u8 (cadr (lookup-instruction 'push)))
|
(define* (write-word word asm #:optional (pos (assembler-pos asm)))
|
||||||
(write-word (assq-ref labels (cadar seq)))
|
(when (> (+ pos 4) (bytevector-length (assembler-buf asm)))
|
||||||
(write-u8 (cadr (lookup-instruction '@)))
|
(assembler-buf-grow! asm))
|
||||||
(assembly-pass (cdr seq) labels)]
|
(bytevector-u32-native-set! (assembler-buf asm) pos word))
|
||||||
[(set!? (car seq))
|
|
||||||
(write-u8 (cadr (lookup-instruction 'push)))
|
(define* (write-byte byte asm #:optional (pos (assembler-pos asm)))
|
||||||
(write-word (assq-ref labels (cadar seq)))
|
(when (> (+ pos 1) (bytevector-length (assembler-buf asm)))
|
||||||
(write-u8 (cadr (lookup-instruction '!)))
|
(assembler-buf-grow! asm))
|
||||||
(assembly-pass (cdr seq) labels)]
|
(bytevector-u8-set! (assembler-buf asm) pos byte))
|
||||||
[else
|
|
||||||
(let* ([inst (car seq)]
|
(define (assembler-label-add-reference asm name addr)
|
||||||
[inst-obj (lookup-instruction (car inst))])
|
(when (not (hash-ref (assembler-labels asm) name))
|
||||||
(write-u8 (instruction-code inst-obj))
|
(hash-set! (assembler-labels asm) name (make-label)))
|
||||||
(when (eq? (car inst) 'push)
|
(let ([label (hash-ref (assembler-labels asm) name)])
|
||||||
(if (number? (cadr inst))
|
(set-cdr! label (cons addr (cdr label)))))
|
||||||
(write-word (cadr inst))
|
|
||||||
(let ([address (assq-ref labels (cadr inst))])
|
(define (assembler-label-add-value asm name val)
|
||||||
(if address
|
(when (not (hash-ref (assembler-labels asm) name))
|
||||||
(write-word (assq-ref labels (cadr inst)))
|
(hash-set! (assembler-labels asm) name (make-label)))
|
||||||
(error (format #f "Could not find label ~a" (cadr inst)))))))
|
;; 1+ to fudge for null pointers
|
||||||
(assembly-pass (cdr seq) labels))]))
|
(set-car! (hash-ref (assembler-labels asm) name) (1+ val)))
|
||||||
|
|
||||||
|
(define (emit-instruction asm inst)
|
||||||
|
(let ([inst-object (lookup-instruction (car inst))])
|
||||||
|
(write-byte (instruction-code inst-object) asm)
|
||||||
|
(assembler-pos-set! asm (+ (assembler-pos asm) 1))
|
||||||
|
(when (not (null? (cdr inst)))
|
||||||
|
(if (number? (cadr inst))
|
||||||
|
(write-word (cadr inst) asm)
|
||||||
|
(begin
|
||||||
|
(write-word 0 asm)
|
||||||
|
(assembler-label-add-reference asm (cadr inst) (assembler-pos asm))))
|
||||||
|
(assembler-pos-set! asm (+ (assembler-pos asm) 4)))))
|
||||||
|
|
||||||
|
(define (emit-label asm name)
|
||||||
|
(assembler-label-add-value asm name (assembler-pos asm)))
|
||||||
|
|
||||||
|
(define (assemble-instructions asm inst-seq)
|
||||||
|
(when (pair? inst-seq)
|
||||||
|
(cond
|
||||||
|
[(label? (car inst-seq))
|
||||||
|
(emit-label asm (car inst-seq))]
|
||||||
|
[(variable? (car inst-seq))
|
||||||
|
(emit-label asm (second (car inst-seq)))
|
||||||
|
(write-word (third (car inst-seq)) asm)
|
||||||
|
(assembler-pos-set! asm (+ (assembler-pos asm) 4))]
|
||||||
|
[(ref? (car inst-seq))
|
||||||
|
(emit-instruction asm `(push ,(second (car inst-seq))))
|
||||||
|
(emit-instruction asm '(@))]
|
||||||
|
[(set!? (car inst-seq))
|
||||||
|
(emit-instruction asm `(push ,(second (car inst-seq))))
|
||||||
|
(emit-instruction asm '(!))]
|
||||||
|
[else
|
||||||
|
(emit-instruction asm (car inst-seq))])
|
||||||
|
(assemble-instructions asm (cdr inst-seq))))
|
||||||
|
|
||||||
|
(define (update-references asm)
|
||||||
|
(define (install-location _name label)
|
||||||
|
(for-each
|
||||||
|
(cute write-word (car label) asm <>)
|
||||||
|
(cdr label)))
|
||||||
|
(hash-for-each install-location (assembler-labels asm)))
|
||||||
|
|
||||||
(define (assemble instructions port)
|
(define (assemble instructions port)
|
||||||
(define labels (label-pass instructions 1))
|
(define asm (make-assembler*))
|
||||||
(with-output-to-port port (lambda () (assembly-pass instructions labels)))
|
(assemble-instructions asm instructions)
|
||||||
labels)
|
(update-references asm)
|
||||||
|
(write-bytevector (assembler-buf asm) port 0 (assembler-pos asm))
|
||||||
|
asm)
|
||||||
|
Loading…
Reference in New Issue
Block a user