Skip to content

Instantly share code, notes, and snippets.

@guicho271828
Last active November 30, 2019 17:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save guicho271828/e9436ae50b68bb2f6fa878280dea6b56 to your computer and use it in GitHub Desktop.
Save guicho271828/e9436ae50b68bb2f6fa878280dea6b56 to your computer and use it in GitHub Desktop.
SBCL 1.5.9 jump-table compilation for `case` and nested `if` sequence
;; This also gets converted into a jump table
(defun fn (x)
(if (eql x #\a)
:a
(if (eql x #\b)
:b
(if (eql x #\c)
:c
(if (eql x #\d)
:d)))))
;; This also gets converted into a jump table
(defun fn (x)
(tagbody
(if (eql x #\a)
(go :a)
(go :-a))
:a
(return-from fn :a)
:-a
(if (eql x #\b)
(go :b)
(go :-b))
:b
(return-from fn :b)
:-b
(if (eql x #\c)
(go :c)
(go :-c))
:c
(return-from fn :c)
:-c
(if (eql x #\d)
(go :d)
(go :-d))
:d
(return-from fn :d)
:-d
nil))
(defun fn (x)
(case x
(1 (print :one))
(2 (print :two))
(3 (print :three))
(4 (print :four))))
; disassembly for FN
; Size: 127 bytes. Origin: #x52D42C04 ; FN
; 04: 498B4510 MOV RAX, [R13+16] ; thread.binding-stack-pointer
; 08: 488945F8 MOV [RBP-8], RAX
; 0C: 4C8D5BFE LEA R11, [RBX-2]
; 10: 4983FB06 CMP R11, 6
; 14: 7710 JNBE L0
; 16: F6C301 TEST BL, 1
; 19: 750B JNE L0
; 1B: 488D059EFFFFFF LEA RAX, [RIP-98] ; = #x52D42BC0
; 22: 42FF2498 JMP QWORD PTR [RAX+R11*4]
; 26: L0: BA17001050 MOV EDX, #x50100017 ; NIL
; 2B: 488BE5 MOV RSP, RBP
; 2E: F8 CLC
; 2F: 5D POP RBP
; 30: C3 RET
; 31: L1: BA0FC34F50 MOV EDX, #x504FC30F ; :FOUR
; 36: B902000000 MOV ECX, 2
; 3B: FF7508 PUSH QWORD PTR [RBP+8]
; 3E: B8C2664850 MOV EAX, #x504866C2 ; #<FDEFN PRINT>
; 43: FFE0 JMP RAX
; 45: L2: BADFC24F50 MOV EDX, #x504FC2DF ; :THREE
; 4A: B902000000 MOV ECX, 2
; 4F: FF7508 PUSH QWORD PTR [RBP+8]
; 52: B8C2664850 MOV EAX, #x504866C2 ; #<FDEFN PRINT>
; 57: FFE0 JMP RAX
; 59: L3: BA7FC24F50 MOV EDX, #x504FC27F ; :TWO
; 5E: B902000000 MOV ECX, 2
; 63: FF7508 PUSH QWORD PTR [RBP+8]
; 66: B8C2664850 MOV EAX, #x504866C2 ; #<FDEFN PRINT>
; 6B: FFE0 JMP RAX
; 6D: L4: BA4FC24F50 MOV EDX, #x504FC24F ; :ONE
; 72: B902000000 MOV ECX, 2
; 77: FF7508 PUSH QWORD PTR [RBP+8]
; 7A: B8C2664850 MOV EAX, #x504866C2 ; #<FDEFN PRINT>
; 7F: FFE0 JMP RAX
; 81: CC10 INT3 16 ; Invalid argument count trap
;; nested IF + eql
(defun fn (x)
(if (eql x 1)
(print :one)
(if (eql x 2)
(print :two)
(if (eql x 3)
(print :three)
(if (eql x 4)
(print :four)
nil)))))
; disassembly for FN
; Size: 127 bytes. Origin: #x52D699F4 ; FN
; 9F4: 498B4510 MOV RAX, [R13+16] ; thread.binding-stack-pointer
; 9F8: 488945F8 MOV [RBP-8], RAX
; 9FC: 4C8D5BFE LEA R11, [RBX-2]
; A00: 4983FB06 CMP R11, 6
; A04: 7710 JNBE L0
; A06: F6C301 TEST BL, 1
; A09: 750B JNE L0
; A0B: 488D059EFFFFFF LEA RAX, [RIP-98] ; = #x52D699B0
; A12: 42FF2498 JMP QWORD PTR [RAX+R11*4]
; A16: L0: BA17001050 MOV EDX, #x50100017 ; NIL
; A1B: 488BE5 MOV RSP, RBP
; A1E: F8 CLC
; A1F: 5D POP RBP
; A20: C3 RET
; A21: L1: BA0FC34F50 MOV EDX, #x504FC30F ; :FOUR
; A26: B902000000 MOV ECX, 2
; A2B: FF7508 PUSH QWORD PTR [RBP+8]
; A2E: B8C2664850 MOV EAX, #x504866C2 ; #<FDEFN PRINT>
; A33: FFE0 JMP RAX
; A35: L2: BADFC24F50 MOV EDX, #x504FC2DF ; :THREE
; A3A: B902000000 MOV ECX, 2
; A3F: FF7508 PUSH QWORD PTR [RBP+8]
; A42: B8C2664850 MOV EAX, #x504866C2 ; #<FDEFN PRINT>
; A47: FFE0 JMP RAX
; A49: L3: BA7FC24F50 MOV EDX, #x504FC27F ; :TWO
; A4E: B902000000 MOV ECX, 2
; A53: FF7508 PUSH QWORD PTR [RBP+8]
; A56: B8C2664850 MOV EAX, #x504866C2 ; #<FDEFN PRINT>
; A5B: FFE0 JMP RAX
; A5D: L4: BA4FC24F50 MOV EDX, #x504FC24F ; :ONE
; A62: B902000000 MOV ECX, 2
; A67: FF7508 PUSH QWORD PTR [RBP+8]
; A6A: B8C2664850 MOV EAX, #x504866C2 ; #<FDEFN PRINT>
; A6F: FFE0 JMP RAX
; A71: CC10 INT3 16 ; Invalid argument count trap
(defun fn (x)
(case x
(1 (print :one))
(2 (print :two))
(:three (print :three))
(4 (print :four))))
; disassembly for FN
; Size: 128 bytes. Origin: #x52D69434 ; FN
; 34: 498B4510 MOV RAX, [R13+16] ; thread.binding-stack-pointer
; 38: 488945F8 MOV [RBP-8], RAX
; 3C: 4883FB02 CMP RBX, 2
; 40: 745C JEQ L3
; 42: 4883FB04 CMP RBX, 4
; 46: 7442 JEQ L2
; 48: 4881FBDFC24F50 CMP RBX, #x504FC2DF ; :THREE
; 4F: 7425 JEQ L1
; 51: 4883FB08 CMP RBX, 8
; 55: 740B JEQ L0
; 57: BA17001050 MOV EDX, #x50100017 ; NIL
; 5C: 488BE5 MOV RSP, RBP
; 5F: F8 CLC
; 60: 5D POP RBP
; 61: C3 RET
; 62: L0: BA0FC34F50 MOV EDX, #x504FC30F ; :FOUR
; 67: B902000000 MOV ECX, 2
; 6C: FF7508 PUSH QWORD PTR [RBP+8]
; 6F: B8C2664850 MOV EAX, #x504866C2 ; #<FDEFN PRINT>
; 74: FFE0 JMP RAX
; 76: L1: BADFC24F50 MOV EDX, #x504FC2DF ; :THREE
; 7B: B902000000 MOV ECX, 2
; 80: FF7508 PUSH QWORD PTR [RBP+8]
; 83: B8C2664850 MOV EAX, #x504866C2 ; #<FDEFN PRINT>
; 88: FFE0 JMP RAX
; 8A: L2: BA7FC24F50 MOV EDX, #x504FC27F ; :TWO
; 8F: B902000000 MOV ECX, 2
; 94: FF7508 PUSH QWORD PTR [RBP+8]
; 97: B8C2664850 MOV EAX, #x504866C2 ; #<FDEFN PRINT>
; 9C: FFE0 JMP RAX
; 9E: L3: BA4FC24F50 MOV EDX, #x504FC24F ; :ONE
; A3: B902000000 MOV ECX, 2
; A8: FF7508 PUSH QWORD PTR [RBP+8]
; AB: B8C2664850 MOV EAX, #x504866C2 ; #<FDEFN PRINT>
; B0: FFE0 JMP RAX
; B2: CC10 INT3 16 ; Invalid argument count trap
;; equivalent code in Trivia pattern matcher does not get compiled into a jump table
(defun fn (x)
(match x
(#\a :a)
(#\b :b)
(#\c :c)
(#\d :d)))
; note: above code expands into
(SYMBOL-MACROLET ((#:ARG1283 X))
(DECLARE)
(LET ((#:WHAT11298 #:ARG1283))
(DECLARE (IGNORABLE #:WHAT11298))
(BLOCK TRIVIA.LEVEL1.IMPL::WHOLE
(BLOCK TRIVIA.LEVEL1.IMPL::CLAUSE ; 1
(LET ((#:IT1284 #:WHAT11298))
(DECLARE (IGNORABLE #:IT1284))
(WHEN (EQL #:IT1284 #\a)
(LOCALLY
(DECLARE (TYPE (EQL #\a) #:IT1284))
(RETURN-FROM TRIVIA.LEVEL1.IMPL::WHOLE
(LOCALLY
(LET ((#:WHAT11308 NIL))
(DECLARE (IGNORABLE #:WHAT11308))
(BLOCK TRIVIA.LEVEL1.IMPL::WHOLE
(BLOCK TRIVIA.LEVEL1.IMPL::CLAUSE
(LET ((#:IT1289 #:WHAT11308))
(DECLARE (IGNORABLE #:IT1289))
(RETURN-FROM TRIVIA.LEVEL1.IMPL::WHOLE (LOCALLY :A))))
(LET ((#:IT1290 #:WHAT11308))
(DECLARE (IGNORABLE #:IT1290))
(RETURN-FROM TRIVIA.LEVEL1.IMPL::WHOLE
(LOCALLY (RETURN-FROM TRIVIA.LEVEL1.IMPL::CLAUSE NIL)))))))))))) ; jumps back to 1
(BLOCK TRIVIA.LEVEL1.IMPL::CLAUSE ; 2
(LET ((#:IT1285 #:WHAT11298))
(DECLARE (IGNORABLE #:IT1285))
(WHEN (EQL #:IT1285 #\b)
(LOCALLY
(DECLARE (TYPE (EQL #\b) #:IT1285))
(RETURN-FROM TRIVIA.LEVEL1.IMPL::WHOLE
(LOCALLY
(LET ((#:WHAT11309 NIL))
(DECLARE (IGNORABLE #:WHAT11309))
(BLOCK TRIVIA.LEVEL1.IMPL::WHOLE
(BLOCK TRIVIA.LEVEL1.IMPL::CLAUSE
(LET ((#:IT1291 #:WHAT11309))
(DECLARE (IGNORABLE #:IT1291))
(RETURN-FROM TRIVIA.LEVEL1.IMPL::WHOLE (LOCALLY :B))))
(LET ((#:IT1292 #:WHAT11309))
(DECLARE (IGNORABLE #:IT1292))
(RETURN-FROM TRIVIA.LEVEL1.IMPL::WHOLE (LOCALLY (RETURN-FROM TRIVIA.LEVEL1.IMPL::CLAUSE NIL)))))))))))) ; jump back to 2
(BLOCK TRIVIA.LEVEL1.IMPL::CLAUSE
(LET ((#:IT1286 #:WHAT11298))
(DECLARE (IGNORABLE #:IT1286))
(WHEN (EQL #:IT1286 #\c)
(LOCALLY
(DECLARE (TYPE (EQL #\c) #:IT1286))
(RETURN-FROM TRIVIA.LEVEL1.IMPL::WHOLE
(LOCALLY
(LET ((#:WHAT11310 NIL))
(DECLARE (IGNORABLE #:WHAT11310))
(BLOCK TRIVIA.LEVEL1.IMPL::WHOLE
(BLOCK TRIVIA.LEVEL1.IMPL::CLAUSE
(LET ((#:IT1293 #:WHAT11310))
(DECLARE (IGNORABLE #:IT1293))
(RETURN-FROM TRIVIA.LEVEL1.IMPL::WHOLE (LOCALLY :C))))
(LET ((#:IT1294 #:WHAT11310))
(DECLARE (IGNORABLE #:IT1294))
(RETURN-FROM TRIVIA.LEVEL1.IMPL::WHOLE (LOCALLY (RETURN-FROM TRIVIA.LEVEL1.IMPL::CLAUSE NIL))))))))))))
(BLOCK TRIVIA.LEVEL1.IMPL::CLAUSE
(LET ((#:IT1287 #:WHAT11298))
(DECLARE (IGNORABLE #:IT1287))
(WHEN (EQL #:IT1287 #\d)
(LOCALLY
(DECLARE (TYPE (EQL #\d) #:IT1287))
(RETURN-FROM TRIVIA.LEVEL1.IMPL::WHOLE
(LOCALLY
(LET ((#:WHAT11311 NIL))
(DECLARE (IGNORABLE #:WHAT11311))
(BLOCK TRIVIA.LEVEL1.IMPL::WHOLE
(BLOCK TRIVIA.LEVEL1.IMPL::CLAUSE
(LET ((#:IT1295 #:WHAT11311))
(DECLARE (IGNORABLE #:IT1295))
(RETURN-FROM TRIVIA.LEVEL1.IMPL::WHOLE (LOCALLY :D))))
(LET ((#:IT1296 #:WHAT11311))
(DECLARE (IGNORABLE #:IT1296))
(RETURN-FROM TRIVIA.LEVEL1.IMPL::WHOLE (LOCALLY (RETURN-FROM TRIVIA.LEVEL1.IMPL::CLAUSE NIL))))))))))))
(LET ((#:IT1288 #:WHAT11298))
(DECLARE (IGNORABLE #:IT1288))
(RETURN-FROM TRIVIA.LEVEL1.IMPL::WHOLE
(LOCALLY
(LET ((#:WHAT11312 NIL))
(DECLARE (IGNORABLE #:WHAT11312))
(BLOCK TRIVIA.LEVEL1.IMPL::WHOLE
(LET ((#:IT1297 #:WHAT11312))
(DECLARE (IGNORABLE #:IT1297))
(RETURN-FROM TRIVIA.LEVEL1.IMPL::WHOLE (LOCALLY NIL)))))))))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment