|
|
|
|
|
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. |
|