disasm.scm 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. ; Part of Scheme 48 1.9. See file COPYING for notices and license.
  2. ; Authors: Richard Kelsey, Jonathan Rees, Timo Harter, Mike Sperber
  3. ; Disassembler that uses the VM's data structures.
  4. ;(define (disassemble stuff . no-subtemplates)
  5. ; (let ((template (cond ((template? stuff) stuff)
  6. ; ((closure? stuff) (closure-template stuff))
  7. ; ((and (location? stuff)
  8. ; (closure? (contents stuff)))
  9. ; (closure-template (contents stuff)))
  10. ; (else
  11. ; (error "cannot coerce to template" stuff)))))
  12. ; (really-disassemble template
  13. ; 0
  14. ; (if (null? no-subtemplates)
  15. ; #f
  16. ; (car no-subtemplates)))
  17. ; (newline)))
  18. (define (disassemble code-pointer)
  19. (really-disassemble code-pointer 0 #f))
  20. (define (really-disassemble code level write-templates?)
  21. (let loop ((pc 0))
  22. (if (< pc (code-vector-length code))
  23. (loop (write-instruction code pc level write-templates?)))))
  24. (define (newline-indent n)
  25. (newline)
  26. (do ((i n (- i 1)))
  27. ((= i 0))
  28. (display #\space)))
  29. (define (write-pc pc)
  30. (if (< pc 100) (display " "))
  31. (if (< pc 10) (display " "))
  32. (write pc))
  33. (define (write-instruction code pc level write-sub-templates?)
  34. (let ((opcode (code-vector-ref code pc)))
  35. (newline-indent (* level 3))
  36. (write-pc pc)
  37. (display " (")
  38. (write (enumerand->name opcode op))
  39. (let ((pc (cond ((= opcode (enum op computed-goto))
  40. (display-computed-goto pc code))
  41. ((or (= opcode (enum op make-flat-env))
  42. (= opcode (enum op make-big-flat-env)))
  43. (display-flat-env pc code))
  44. ((= opcode (enum op protocol))
  45. (display-protocol pc code))
  46. ((= opcode (enum op cont-data))
  47. (+ pc (get-offset (+ pc 1) code)))
  48. (else
  49. (print-opcode-args opcode (+ pc 1) code
  50. level write-sub-templates?)))))
  51. (display #\))
  52. pc)))
  53. (define (display-computed-goto start-pc code)
  54. (display #\space)
  55. (let ((count (code-vector-ref code (+ start-pc 1))))
  56. (write count)
  57. (do ((pc (+ start-pc 2) (+ pc 2))
  58. (count count (- count 1)))
  59. ((= count 0) pc)
  60. (display #\space)
  61. (write `(=> ,(+ start-pc (get-offset pc code)))))))
  62. ; skip make-flat-env or make-big-flat-env
  63. ; pc must point to the opcode, returns pc of next opcode
  64. ;
  65. (define (skip-flat-env code pc)
  66. (let* ((big? (= (code-vector-ref code pc) (enum op make-big-flat-env)))
  67. (size (if big? 2 1))
  68. (fetch (if big? (lambda (code pc) (get-offset pc code)) code-vector-ref))
  69. (offset (+ pc 1)) ; skip opcode
  70. (total (fetch code offset)) ; # of values (total)
  71. (closures (fetch code (+ offset size))) ; # of closures
  72. (offset (+ offset size (* size closures))) ; skip template offset + offsets of templates in template
  73. (vars (fetch code offset)) ; # of vars in frame
  74. (offset (+ offset (* size vars))) ; skip offsets of vars in frame
  75. (envs (- total (+ closures vars)))) ; # of envs in frame
  76. (let loop ((offset offset) ; skip env information
  77. (env envs))
  78. (if (= env 0)
  79. offset ; position of next opcode
  80. (let ((env-vars (fetch code (+ offset size)))) ; # of vars in env
  81. (loop
  82. (+ offset size size (* size env-vars)) ; skip env offset, # of vars, offsets of vars in env
  83. (- env 1)))))))
  84. (define (display-flat-env pc code)
  85. (let ((total-count (code-vector-ref code (+ pc 1))))
  86. (display #\space) (write total-count) (display " ...")
  87. (skip-flat-env code pc)))
  88. ; (let loop ((pc (+ pc 2)) (count 0) (old-back 0))
  89. ; (if (= count total-count)
  90. ; pc
  91. ; (let ((back (+ (code-vector-ref code pc)
  92. ; old-back))
  93. ; (limit (+ pc 2 (code-vector-ref code (+ pc 1)))))
  94. ; (do ((pc (+ pc 2) (+ pc 1))
  95. ; (count count (+ count 1))
  96. ; (offsets '() (cons (code-vector-ref code pc) offsets)))
  97. ; ((= pc limit)
  98. ; (display #\space)
  99. ; (write `(,back ,(reverse offsets)))
  100. ; (loop pc count back))))))))
  101. (define (display-protocol pc code)
  102. (let ((protocol (code-vector-ref code (+ pc 1))))
  103. (display #\space)
  104. (+ pc (cond ((<= protocol maximum-stack-args)
  105. (display protocol)
  106. (if (= pc 0) 3 2))
  107. ((= protocol two-byte-nargs-protocol)
  108. (display (get-offset (+ pc 2) code))
  109. (if (= pc 0) 5 4))
  110. ((= protocol two-byte-nargs+list-protocol)
  111. (display (get-offset (+ pc 2) code))
  112. (display "+")
  113. (if (= pc 0) 5 4))
  114. ((= protocol args+nargs-protocol)
  115. (display "args+nargs")
  116. 2)
  117. ((= protocol ignore-values-protocol)
  118. (display "discard all values")
  119. 2)
  120. ((= protocol call-with-values-protocol)
  121. (display "call-with-values ")
  122. (write `(=> ,(+ pc (get-offset (+ pc 2) code))))
  123. 4)
  124. ((= protocol nary-dispatch-protocol)
  125. (display "nary-dispatch")
  126. (do ((i 0 (+ i 1)))
  127. ((= i 4))
  128. (let ((offset (code-vector-ref code (+ pc 2 i))))
  129. (if (not (= offset 0))
  130. (begin
  131. (display #\space)
  132. (display (list (if (= i 3) "3+" i)
  133. '=>
  134. (+ pc offset)))))))
  135. 5)
  136. (else
  137. (error "unknown protocol" protocol))))))
  138. (define (print-opcode-args op pc code level write-templates?)
  139. (let ((specs (vector-ref opcode-arg-specs op)))
  140. (let loop ((specs specs) (pc pc))
  141. (cond ((or (null? specs)
  142. (= 0 (arg-spec-size (car specs))))
  143. pc)
  144. (else
  145. (display #\space)
  146. (print-opcode-arg specs pc code level write-templates?)
  147. (loop (cdr specs) (+ pc (arg-spec-size (car specs)))))))))
  148. (define (arg-spec-size spec)
  149. (case spec
  150. ((nargs byte stob literal index stack-index) 1)
  151. ((offset two-bytes two-byte-index two-byte-stack-index) 2)
  152. (else 0)))
  153. (define (print-opcode-arg specs pc code level write-templates?)
  154. (case (car specs)
  155. ((nargs byte stack-index)
  156. (write (code-vector-ref code pc)))
  157. ((literal)
  158. (write (- (code-vector-ref code pc) 128)))
  159. ((two-bytes two-byte-stack-index)
  160. (write (get-offset pc code)))
  161. ((index)
  162. (write (code-vector-ref code pc)))
  163. ; (let ((thing (template-ref template (code-vector-ref code pc))))
  164. ; (write-literal-thing thing level write-templates?))
  165. ((two-byte-index)
  166. (write (code-vector-ref code pc)))
  167. ; (let ((thing (template-ref template (get-offset pc code))))
  168. ; (write-literal-thing thing level write-templates?))
  169. ((offset)
  170. (write `(=> ,(+ pc -1 (get-offset pc code))))) ; -1 to back up over opcode
  171. ((stob)
  172. (write (enumerand->name (code-vector-ref code pc) stob)))))
  173. (define (get-offset pc code)
  174. (+ (* (code-vector-ref code pc)
  175. byte-limit)
  176. (code-vector-ref code (+ pc 1))))
  177. (define (write-literal-thing thing level write-templates?)
  178. (cond ((location? thing)
  179. (write `(location ,thing ,(location-id thing))))
  180. ((not (template? thing))
  181. (display #\')
  182. (write thing))
  183. (write-templates?
  184. (really-disassemble thing (+ level 1) #t))
  185. (else
  186. (display "..."))))