Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- # Scheme x86 Compiler - Debugging wrong call
- Input:
- ```scheme
- ((lambda (g x) (g x)) (lambda (x) (prim-apply + 1 x)) 2)
- ```
- **Problem**: generated code contains two functions.
- We want to jump to `(lambda (g x) (g x))` (`label_0`) first.
- Instead, the code jumps to the `(lambda (x) (prim-apply + 1 x))` (`label_1`) first.
- ### Debugging with GDB
- ```
- (gdb) p $label_1
- $2 = {<text variable, no debug info>} 0x565e6a30 <label_1>
- (gdb) p $label_0
- $3 = {<text variable, no debug info>} 0x565e6a42 <label_0>
- ```
- We **want to jump to `label_0` first**.
- Dissecting the evaluation of arguments. First we evaluate the closure at
- `label_1`:
- movl 16(%esp), %esi
- movl $label_1, %eax
- movl %eax, 0(%esi)
- movl %esi, %eax
- orl $6, %eax
- addl $4, %esi
- movl %eax, -12(%esp)
- After `movl $label_1, %eax` in `%eax`: `0x565e6a30`
- Then we move `%eax` to the location pointed to by `%esi`, our heap pointer: `movl %eax, 0(%esi)`
- Let's see if it's there. Here is what `%esi` contains:
- ```
- (gdb) p/x $esi
- $5 = 0xf7187010
- ```
- And here is what is _at_ `0xf7187010`:
- ```
- (gdb) x $esi
- 0xf7187010: 0x565e6a30
- ```
- Our label.
- Then `%esi` gets copied to `%eax`, because this pointer is the result of the
- evaluation.
- ```
- movl %esi, %eax
- ```
- Now we need to tag it.
- Before, here are hex, binary, decimal representations:
- ```
- 0xf7187010 11110111000110000111000000010000 4145573904
- 0x565e6a30 01010110010111100110101000110000 1449028144
- ```
- What we want to tag is `0xf7187010`
- Now, after executing `orl $6, %eax`:
- ```
- (gdb) x $eax
- 0xf7187016: 0x00000000
- ```
- That is
- ```
- 0xf7187016 11110111000110000111000000010110 4145573910
- ```
- Our tag is `6`, which is `110`, so the tag worked.
- Then we evaluate the next argument, the `2`:
- ```
- movl $8, %eax
- movl %eax, -16(%esp)
- ```
- Then we evaluate the closure we want to call:
- ```
- movl $label_0, %eax
- movl %eax, 0(%esi)
- movl %esi, %eax
- orl $6, %eax
- addl $4, %esi
- ```
- After `movl $label_0, %eax` in `%eax`: `0x565e6a42`
- Then we also move `%eax` to the location pointed to by `%esi`, our heap pointer: `movl %eax, 0(%esi)`
- Let's see if it's there. Here is what `%esi` contains:
- ```
- (gdb) p/x $esi
- $7 = 0xf7187014
- ```
- And here is what is _at_ `0xf7187014`:
- ```
- (gdb) x $esi
- 0xf7187014: 0x565e6a42
- ```
- That is `$label_0`. Looks good. Move it to `%eax`:
- ```
- (gdb) x $eax
- 0xf7187014: 0x565e6a42
- ```
- ```
- 0xf7187014 11110111000110000111000000010100 4145573908
- 0x565e6a42 01010110010111100110101001000010 1449028162
- ```
- And now we tag it in `%eax`:
- ```
- 0xf7187016 11110111000110000111000000010110 4145573910
- 0x565e 00000000000000000101011001011110 22110
- ```
- Uh oh. The pointer has only been incremented by `2`.
- 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.
- Realization: the problem is that after we tag the first closure pointer, we only
- advance `%esi` by _a single wordsize_, `4`. That is not enough to align the
- pointer at 8 bytes, which would allow us to use the lowest 3 bits for tagging.
- What we need to do: instead of advancing `%esi` by a single word. We need to align it at double-word boundaries.
- Yep, that's it. If we change the existing code from
- ```scheme
- (emit "orl $~a, %eax" object-tag-closure)
- (emit "addl $~a, %esi" wordsize)
- ```
- to this:
- ```scheme
- (emit "orl $~a, %eax" object-tag-closure)
- ;; Add 7+4 to pointer in %esi because
- ;; * 7 to align to multiple of 8
- ;; * 4 because that's the size of the label we stored and want to skip.
- ;; then bitwise-AND it with -8
- (emit "addl $11, %esi")
- (emit "andl $-8, %esi")
- ```
- Then **every test passes!**
- Thanks for tuning in.
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement