disasm.scm 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317
  1. ; -*- Mode: Scheme; Syntax: Scheme; Package: Scheme; -*-
  2. ; Copyright (c) 1993-2008 by Richard Kelsey and Jonathan Rees. See file COPYING.
  3. ;;;; Disassembler
  4. ; This will need to track the template's offset. Drat.
  5. ; This defines a command processor command
  6. ; dis <expression>
  7. ; that evaluates <expression> to obtain a procedure or lambda-expression,
  8. ; which is then disassembled.
  9. ; The assembly language is designed to be rereadable. See env/assem.scm.
  10. (define-command-syntax 'dis "[<exp>]" "disassemble procedure"
  11. '(&opt expression))
  12. ; The command. The thing to be disassembled defaults to the focus object (##).
  13. (define (dis . maybe-exp)
  14. (disassemble (if (null? maybe-exp)
  15. (focus-object)
  16. (eval (car maybe-exp) (environment-for-commands)))))
  17. (define (disassemble obj)
  18. (really-disassemble (coerce-to-template-or-code obj) 0)
  19. (newline))
  20. (define (really-disassemble template-or-code level)
  21. (let* ((template (if (template? template-or-code)
  22. template-or-code
  23. #f))
  24. (code (if template
  25. (template-code template)
  26. template-or-code)))
  27. (parse-template-code template code level disasm-attribution)))
  28. (define (disasm-init-template level template p-args push-template? push-env? push-closure?)
  29. (if (template-name template)
  30. (write (template-name template)))
  31. (print-opcode (enum op protocol) 0 level)
  32. (show-protocol p-args 0)
  33. (if (or push-template? push-env? push-closure?)
  34. (begin
  35. (display " (push")
  36. (if push-closure?
  37. (display " closure"))
  38. (if push-env?
  39. (display " env"))
  40. (if push-template?
  41. (display " template"))
  42. (display #\))))
  43. (display #\))
  44. level)
  45. (define (disasm-attribute-literal literal index level)
  46. level)
  47. (define (disasm-make-label target-pc)
  48. target-pc)
  49. (define (disasm-at-label label level)
  50. level)
  51. (define disasm-table (make-opcode-table
  52. (lambda (opcode template level pc len . args)
  53. (print-opcode opcode pc level)
  54. (print-opcode-args args)
  55. (display #\))
  56. level)))
  57. (define disasm-attribution
  58. (make-attribution disasm-init-template disasm-attribute-literal
  59. disasm-table disasm-make-label disasm-at-label))
  60. (define-syntax define-disasm
  61. (syntax-rules ()
  62. ((define-disasm inst disasm)
  63. (opcode-table-set! disasm-table (enum op inst) disasm))))
  64. ;------------------------------
  65. (define-disasm protocol
  66. (lambda (opcode template level pc len p-args)
  67. (print-opcode opcode pc level)
  68. (show-protocol (cdr p-args) pc)
  69. (display #\))
  70. level))
  71. (define (show-protocol p-args pc)
  72. (let ((protocol (car p-args)))
  73. (display #\space)
  74. (cond ((<= protocol maximum-stack-args)
  75. (display protocol))
  76. ((= protocol two-byte-nargs-protocol)
  77. (display (cadr p-args)))
  78. ((= protocol two-byte-nargs+list-protocol)
  79. (display (cadr p-args))
  80. (display " +"))
  81. ((= protocol ignore-values-protocol)
  82. (display "discard all values"))
  83. ((= protocol call-with-values-protocol)
  84. (display "call-with-values")
  85. (let ((target-pc (cadr p-args)))
  86. (if (not (= pc target-pc))
  87. (begin
  88. (display #\space)
  89. (write `(=> ,(cadr p-args)))))))
  90. ((= protocol args+nargs-protocol)
  91. (display "args+nargs ")
  92. (display (cadr p-args))
  93. (display "+"))
  94. ((= protocol nary-dispatch-protocol)
  95. (display "nary-dispatch")
  96. (for-each display-dispatch (cdr p-args) (list 0 1 2 "3+")))
  97. ((= protocol big-stack-protocol)
  98. (apply
  99. (lambda (real-attribution stack-size)
  100. (display "big-stack")
  101. (show-protocol real-attribution pc)
  102. (display #\space)
  103. (display stack-size))
  104. (cdr p-args)))
  105. (else
  106. (error "unknown protocol" protocol)))))
  107. (define (display-dispatch target-pc tag)
  108. (if target-pc
  109. (begin
  110. (display #\space)
  111. (display (list tag '=> target-pc)))))
  112. ;------------------------------
  113. (define-disasm global
  114. (lambda (opcode template level pc len index-to-template index-within-template)
  115. (print-opcode opcode pc level)
  116. (print-opcode-args (list index-to-template index-within-template))
  117. (display #\space)
  118. (display-global-reference template (cdr index-within-template))
  119. (display #\))
  120. level))
  121. (define-disasm set-global!
  122. (lambda (opcode template level pc len index-to-template index-within-template)
  123. (print-opcode opcode pc level)
  124. (print-opcode-args (list index-to-template index-within-template))
  125. (display #\space)
  126. (display-global-reference template (cdr index-within-template))
  127. (display #\))
  128. level))
  129. (define (display-global-reference template index)
  130. (let ((loc (if template
  131. (template-ref template index)
  132. #f)))
  133. (cond ((location? loc)
  134. (write (or (location-name loc)
  135. `(location ,(location-id loc)))))
  136. (else
  137. (display #\')
  138. (write loc)))))
  139. ;------------------------------
  140. (define (disasm-make-flat-env opcode template level pc len env-data-arg)
  141. (let ((env-data (cdr env-data-arg)))
  142. (print-opcode opcode pc level)
  143. (display #\space)
  144. (write (env-data-total-count env-data))
  145. (display #\space)
  146. (let ((closure-offsets (env-data-closure-offsets env-data)))
  147. (if (not (null? closure-offsets))
  148. (begin
  149. (write (length closure-offsets))
  150. (display-flat-env-closures env-data))
  151. (write 0)))
  152. (display #\space)
  153. (display (env-data-frame-offsets env-data))
  154. (for-each (lambda (env-offset)
  155. (display #\space)
  156. (display #\()
  157. (display (car env-offset))
  158. (display " => ")
  159. (display (cdr env-offset))
  160. (display #\)))
  161. (env-data-env-offsets env-data))
  162. (display #\))
  163. level))
  164. (define (display-flat-env-closures env-data)
  165. (display " (closures from ")
  166. (display (env-data-maybe-template-index env-data))
  167. (display #\:)
  168. (for-each (lambda (offset)
  169. (display #\space)
  170. (display offset))
  171. (env-data-closure-offsets env-data))
  172. (display #\)))
  173. (define-disasm make-flat-env disasm-make-flat-env)
  174. (define-disasm make-big-flat-env disasm-make-flat-env)
  175. ;------------------------------
  176. (define (display-cont-data cont-data)
  177. (write-char #\space)
  178. (display (list '=> (cont-data-pc cont-data)))
  179. (write-char #\space)
  180. (display (list 'depth (cont-data-depth cont-data)))
  181. (write-char #\space)
  182. (display (list 'template (cont-data-template cont-data)))
  183. (write-char #\space)
  184. (cond
  185. ((cont-data-live-offsets cont-data)
  186. => (lambda (offsets)
  187. (display (cons 'live offsets))))
  188. (else
  189. (display "all-live"))))
  190. (define-disasm cont-data
  191. (lambda (opcode template level pc len cont-data-arg)
  192. (print-opcode opcode pc level)
  193. (display-cont-data (cdr cont-data-arg))
  194. (display #\))
  195. level))
  196. ;------------------------------
  197. (define (display-shuffle opcode template level pc len moves-data)
  198. (print-opcode opcode pc level)
  199. (write-char #\space)
  200. (let ((moves (cdr moves-data)))
  201. (display (length moves))
  202. (for-each (lambda (move)
  203. (write-char #\space)
  204. (display (list (car move) (cdr move))))
  205. moves)
  206. (write-char #\))
  207. level))
  208. (define-disasm stack-shuffle! display-shuffle)
  209. (define-disasm big-stack-shuffle! display-shuffle)
  210. (define (write-instruction code template pc level write-sub-templates?)
  211. ;; An in the previous version, WRITE-SUB-TEMPLATES? is ignored and
  212. ;; sub templates are never written.
  213. (call-with-values
  214. (lambda ()
  215. (parse-instruction template code pc level disasm-attribution))
  216. (lambda (len level)
  217. (+ pc len))))
  218. ;------------------------------
  219. (define (print-opcode opcode pc level)
  220. (newline-indent (* level 3))
  221. (write-pc pc)
  222. (display " (")
  223. (write (enumerand->name opcode op)))
  224. ; Generic opcode argument printer.
  225. (define (print-opcode-args args)
  226. (for-each (lambda (arg)
  227. (display #\space)
  228. (print-opcode-arg arg))
  229. args))
  230. ; Print out the particular type of argument.
  231. ; This works only for the generic argument types, the special types
  232. ; are handled by the instruction disassemblers themselves
  233. (define (print-opcode-arg spec.arg)
  234. (let ((spec (car spec.arg))
  235. (arg (cdr spec.arg)))
  236. (case spec
  237. ((byte two-bytes nargs two-byte-nargs literal index two-byte-index
  238. stack-index two-byte-stack-index)
  239. (write arg))
  240. ((offset)
  241. (write `(=> ,arg)))
  242. ((offset-)
  243. (write `(=> ,arg)))
  244. ((stob)
  245. (write (enumerand->name arg stob)))
  246. (else
  247. (error "unknown arg spec" spec)))))
  248. ;----------------
  249. ; Utilities.
  250. ; Turn OBJ into a template, if possible.
  251. (define (coerce-to-template-or-code obj)
  252. (cond ((template? obj)
  253. obj)
  254. ((closure? obj)
  255. (closure-template obj))
  256. ((continuation? obj)
  257. (or (continuation-template obj)
  258. (continuation-code obj)))
  259. (else
  260. (error "expected a procedure or continuation" obj))))
  261. ; Indenting and aligning the program counter.
  262. (define (newline-indent n)
  263. (newline)
  264. (do ((i n (- i 1)))
  265. ((= i 0))
  266. (display #\space)))
  267. (define (write-pc pc)
  268. (if (< pc 100) (display " "))
  269. (if (< pc 10) (display " "))
  270. (write pc))