Hacker News new | ask | show | jobs
by Jtsummers 1431 days ago
> Thanks, learned something new today with return-from! I’d be curious how different cl implementations implement it.

At least in SBCL, with it compiling the function, it turns into exactly the kind of assembly code you'd expect. Using disassemble:

    CL-USER> (defun foo (n)
               (when (< n 0) (return-from foo 20))
               (* 20 n))

    CL-USER> (disassemble #'foo)
    ; disassembly for FOO
    ; Size: 54 bytes. Origin: #x53642F41                          ; FOO
    ; 41:       498B4510         MOV RAX, [R13+16]                ; thread.binding-stack-pointer
    ; 45:       488945F8         MOV [RBP-8], RAX
    ; 49:       488B55F0         MOV RDX, [RBP-16]
    ; 4D:       31FF             XOR EDI, EDI
    ; 4F:       FF14252001A052   CALL QWORD PTR [#x52A00120]      ; SB-VM::GENERIC-<
    ; 56:       7C16             JL L1
    ; 58:       488B55F0         MOV RDX, [RBP-16]
    ; 5C:       BF28000000       MOV EDI, 40
    ; 61:       FF14251001A052   CALL QWORD PTR [#x52A00110]      ; SB-VM::GENERIC-*
    ; 68: L0:   488BE5           MOV RSP, RBP
    ; 6B:       F8               CLC
    ; 6C:       5D               POP RBP
    ; 6D:       C3               RET
    ; 6E: L1:   BA28000000       MOV EDX, 40
    ; 73:       EBF3             JMP L0
    ; 75:       CC10             INT3 16                          ; Invalid argument count trap
This sets up the call for the comparison, conditionally jumps based on the result (JL), and then returns one of the two results. Note that the "40" in 5C and 6E are really "20", this is a consequence of how many CL implementations handle integers, the low-order bit is used as a tag so not really part of the value. If you wrote it in C it would be very similar.

https://godbolt.org/z/cYPhdW3qd

The biggest difference is that the C version doesn't need a call for the comparison.