SHARE
TWEET

Untitled

a guest Sep 18th, 2019 97 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # Scheme x86 Compiler - Debugging wrong call
  2.  
  3. Input:
  4.  
  5. ```scheme
  6. ((lambda (g x) (g x)) (lambda (x) (prim-apply + 1 x)) 2)
  7. ```
  8.  
  9. **Problem**: generated code contains two functions.
  10.  
  11. We want to jump to `(lambda (g x) (g x))` (`label_0`) first.
  12.  
  13. Instead, the code jumps to the `(lambda (x) (prim-apply + 1 x))` (`label_1`) first.
  14.  
  15. ### Debugging with GDB
  16.  
  17. ```
  18. (gdb) p $label_1
  19. $2 = {<text variable, no debug info>} 0x565e6a30 <label_1>
  20. (gdb) p $label_0
  21. $3 = {<text variable, no debug info>} 0x565e6a42 <label_0>
  22. ```
  23.  
  24. We **want to jump to `label_0` first**.
  25.  
  26. Dissecting the evaluation of arguments. First we evaluate the closure at
  27. `label_1`:
  28.  
  29.       movl 16(%esp), %esi
  30.       movl $label_1, %eax
  31.       movl %eax, 0(%esi)
  32.       movl %esi, %eax
  33.       orl $6, %eax
  34.       addl $4, %esi
  35.       movl %eax, -12(%esp)
  36.  
  37. After `movl $label_1, %eax` in `%eax`: `0x565e6a30`
  38.  
  39. Then we move `%eax` to the location pointed to by `%esi`, our heap pointer: `movl %eax, 0(%esi)`
  40.  
  41. Let's see if it's there. Here is what `%esi` contains:
  42.  
  43. ```
  44. (gdb) p/x $esi
  45. $5 = 0xf7187010
  46. ```
  47.  
  48. And here is what is _at_ `0xf7187010`:
  49.  
  50. ```
  51. (gdb) x $esi
  52. 0xf7187010:     0x565e6a30
  53. ```
  54.  
  55. Our label.
  56.  
  57. Then `%esi` gets copied to `%eax`, because this pointer is the result of the
  58. evaluation.
  59.  
  60. ```
  61. movl %esi, %eax
  62. ```
  63.  
  64. Now we need to tag it.
  65.  
  66. Before, here are hex, binary, decimal representations:
  67.  
  68. ```
  69. 0xf7187010  11110111000110000111000000010000    4145573904
  70. 0x565e6a30  01010110010111100110101000110000    1449028144
  71. ```
  72.  
  73. What we want to tag is `0xf7187010`
  74.  
  75. Now, after executing `orl $6, %eax`:
  76.  
  77. ```
  78. (gdb) x $eax
  79. 0xf7187016:     0x00000000
  80. ```
  81.  
  82. That is
  83.  
  84. ```
  85. 0xf7187016  11110111000110000111000000010110    4145573910
  86. ```
  87.  
  88. Our tag is `6`, which is `110`, so the tag worked.
  89.  
  90. Then we evaluate the next argument, the `2`:
  91.  
  92. ```
  93.     movl $8, %eax
  94.     movl %eax, -16(%esp)
  95. ```
  96.  
  97. Then we evaluate the closure we want to call:
  98.  
  99. ```
  100.     movl $label_0, %eax
  101.     movl %eax, 0(%esi)
  102.     movl %esi, %eax
  103.     orl $6, %eax
  104.     addl $4, %esi
  105. ```
  106.  
  107. After `movl $label_0, %eax` in `%eax`: `0x565e6a42`
  108.  
  109. Then we also move `%eax` to the location pointed to by `%esi`, our heap pointer: `movl %eax, 0(%esi)`
  110.  
  111. Let's see if it's there. Here is what `%esi` contains:
  112.  
  113. ```
  114. (gdb) p/x $esi
  115. $7 = 0xf7187014
  116. ```
  117.  
  118. And here is what is _at_ `0xf7187014`:
  119.  
  120. ```
  121. (gdb) x $esi
  122. 0xf7187014:     0x565e6a42
  123. ```
  124.  
  125. That is `$label_0`. Looks good. Move it to `%eax`:
  126.  
  127. ```
  128. (gdb) x $eax
  129. 0xf7187014:     0x565e6a42
  130. ```
  131.  
  132. ```
  133. 0xf7187014  11110111000110000111000000010100    4145573908
  134. 0x565e6a42  01010110010111100110101001000010    1449028162
  135. ```
  136.  
  137. And now we tag it in `%eax`:
  138.  
  139. ```
  140. 0xf7187016  11110111000110000111000000010110    4145573910
  141. 0x565e      00000000000000000101011001011110    22110
  142. ```
  143.  
  144. Uh oh. The pointer has only been incremented by `2`.
  145.  
  146. That means, when we then _untag_ the pointer and do a `subl $6, %eax`, we decrease by `6`, which doesn't get us to the correct original pointer.
  147.  
  148. Realization: the problem is that after we tag the first closure pointer, we only
  149. advance `%esi` by _a single wordsize_, `4`. That is not enough to align the
  150. pointer at 8 bytes, which would allow us to use the lowest 3 bits for tagging.
  151.  
  152. What we need to do: instead of advancing `%esi` by a single word. We need to align it at double-word boundaries.
  153.  
  154. Yep, that's it. If we change the existing code from
  155.  
  156. ```scheme
  157. (emit "orl $~a, %eax" object-tag-closure)
  158. (emit "addl $~a, %esi" wordsize)
  159. ```
  160.  
  161. to this:
  162.  
  163. ```scheme
  164. (emit "orl $~a, %eax" object-tag-closure)
  165. ;; Add 7+4 to pointer in %esi because
  166. ;; * 7 to align to multiple of 8
  167. ;; * 4 because that's the size of the label we stored and want to skip.
  168. ;; then bitwise-AND it with -8
  169. (emit "addl $11, %esi")
  170. (emit "andl $-8, %esi")
  171. ```
  172.  
  173. Then **every test passes!**
  174.  
  175. Thanks for tuning in.
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top