Advertisement
Guest User

Untitled

a guest
Sep 18th, 2019
137
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.60 KB | None | 0 0
  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.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement