jart / sectorlisp

Bootstrapping LISP in a Boot Sector
ISC License
1.29k stars 56 forks source link

Referencing bound variables in lambdas crashes the interpreter in QEMU #18

Closed woodrush closed 2 years ago

woodrush commented 2 years ago

Evaluating the following expression in QEMU using make test1 crashes the interpreter:

((LAMBDA (B) B)(QUOTE C))

When this expression starts being evaluated, the interpreter stops running and no output or input prompts occur afterwards.

The following expressions do work:

((LAMBDA () (QUOTE A)))
((LAMBDA (B) (QUOTE A))(QUOTE C))

The difference here is whether the bounded variables are referenced or not, so it seems that referencing bounded variables in lambdas are currently failing.

Since variable bindings do not work, the metacircular evaluator in ./test/eval10.lisp and eval15.lisp doesn't work as well.

This issue does not happen at all in Blinkenlights, so it may be an x86 forward compatibility issue.

woodrush commented 2 years ago

I found that the last working commit without this issue is 88e749ea79fcc0c361f1, and the first commit that has this issue is a557787f5fe5030f9cd2.

The relevant code was this part:

+Assoc: mov     %dx,%si                         # Assoc(x:ax,y:dx):ax
+1:     mov     (%si),%di
+       mov     (%bx,%si),%si
+       scasw
+       jne     1b
+       .byte   0xF6                            # test §mov/cmp (nop next bytes)
 Cadr:  mov     (%bx,%di),%di                   # contents of decrement register
        .byte   0x3C                            # cmp §scasw,%al (nop next byte)
 Cdr:   scasw                                   # increments our data index by 2
 Car:   mov     (%di),%ax                       # contents of address register!!
 2:     ret

-Assoc: mov     %dx,%si                         # Assoc(x:ax,y:dx):ax
-1:     mov     (%si),%di
-       mov     (%bx,%si),%si
-       scasw
-       jne     1b
-       jmp     Car

Reverting these changes resolved the issue. There are two more lines that were changed in isEq: and retT:, but reverting only these changes did not work.

However, reverting these changes adds an extra byte to the program. To prevent this, I tried exploring if we could change the byte at .byte 0xF6 to make this part work, which leaves the program size unchanged. I'll be posting some details soon.