summaryrefslogtreecommitdiff
path: root/module/system/vm/disasm.scm
blob: bad1166a44a0515335f2da8928b557a3de53e20c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
;;; Guile VM Disassembler

;; Copyright (C) 2001 Free Software Foundation, Inc.

;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation; either version 2, or (at your option)
;; any later version.
;; 
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.
;; 
;; You should have received a copy of the GNU General Public License
;; along with this program; see the file COPYING.  If not, write to
;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
;; Boston, MA 02111-1307, USA.

;;; Code:

(define-module (system vm disasm)
  :use-module (system vm core)
  :use-module (system vm conv)
  :use-module (ice-9 regex)
  :use-module (ice-9 match)
  :use-module (ice-9 format)
  :use-module (ice-9 receive)
  :use-module (ice-9 and-let-star)
  :export (disassemble-bootcode disassemble-program))

(define (disassemble-bootcode bytes . opts)
  (if (not (bootcode? bytes)) (error "Invalid bootcode"))
  (format #t "Disassembly of bootcode:\n\n")
  (format #t "Compiled for Guile VM ~A\n\n" (bootcode-version bytes))
  (format #t "nlocs = ~A  nexts = ~A\n\n"
	  (bootcode-nlocs bytes) (bootcode-nexts bytes))
  (disassemble-bytecode (bootcode-bytecode bytes) #f))

(define (disassemble-program prog . opts)
  (let* ((arity (program-arity prog))
	 (nargs (car arity))
	 (nrest (cadr arity))
	 (nlocs (caddr arity))
	 (nexts (cadddr arity))
	 (bytes (program-bytecode prog))
	 (objs  (program-objects prog)))
    ;; Disassemble this bytecode
    (format #t "Disassembly of ~A:\n\n" prog)
    (format #t "nargs = ~A  nrest = ~A  nlocs = ~A nexts ~A\n\n"
	    nargs nrest nlocs nexts)
    (format #t "Bytecode:\n\n")
    (disassemble-bytecode bytes objs)
    (if (> (vector-length objs) 0)
	(disassemble-objects objs))
    ;; Disassemble other bytecode in it
    (for-each
     (lambda (x)
       (if (program? x)
	   (begin (display "----------------------------------------\n")
		  (apply disassemble-program x opts))))
     (vector->list objs))))

(define (disassemble-bytecode bytes objs)
  (let ((decode (make-byte-decoder bytes))
	(rest '()))
    (do ((addr+code (decode) (decode)))
	((not addr+code) (newline))
      (receive (addr code) addr+code
	(match code
	  (('load-program x)
	   (let ((sym (gensym "")))
	     (set! rest (acons sym x rest))
	     (print-info addr (format #f "load-program #~A" sym) #f)))
	  (else
	   (let ((info (list->info code))
		 (extra (original-value addr code objs)))
	     (print-info addr info extra))))))
    (for-each (lambda (sym+bytes)
		(format #t "Bytecode #~A:\n\n" (car sym+bytes))
		(disassemble-bytecode (cdr sym+bytes) #f))
	      (reverse! rest))))

(define (disassemble-objects objs)
  (display "Objects:\n\n")
  (let ((len (vector-length objs)))
    (do ((n 0 (1+ n)))
	((= n len) (newline))
      (let ((info (object->string (vector-ref objs n))))
	(print-info n info #f)))))

(define (disassemble-meta meta)
  (display "Meta info:\n\n")
  (for-each (lambda (data)
	      (print-info (car data) (list->info (cdr data)) #f))
	    meta)
  (newline))

(define (original-value addr code objs)
  (define (branch-code? code)
    (string-match "^(br|jump)" (symbol->string (car code))))
  (let ((code (code-unpack code)))
    (cond ((code->object code) => object->string)
	  ((branch-code? code)
	   (format #f "-> ~A" (+ addr (cadr code) 2)))
	  (else
	   (let ((inst (car code)) (args (cdr code)))
	     (case inst
	       ((make-false) "#f")
	       ((object-ref)
		(if objs (object->string (vector-ref objs (car args))) #f))
;;;	       ((local-ref local-set)
;;;		;;'(ref x))
;;;		#f)
;;;	     ((module-ref module-set)
;;;	      (let ((var (vector-ref objs (car args))))
;;;		(list (if (eq? inst 'module-ref) 'ref 'set)
;;;		      (if (pair? var) (car var) var))))
	       (else #f)))))))

(define (list->info list)
  (let ((str (object->string list)))
    (substring str 1 (1- (string-length str)))))

(define (print-info addr info extra)
  (if extra
      (format #t "~4@A    ~32A;; ~A\n" addr info extra)
      (format #t "~4@A    ~A\n" addr info)))