disasm.scm 9.6 KB

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