incomplete disassembly?

Bug #1959535 reported by Robert Brown
10
This bug affects 2 people
Affects Status Importance Assigned to Milestone
SBCL
Invalid
Undecided
Unassigned

Bug Description

When I compile and load the following function

(defun doit2 (x)
  (declare (type fixnum x)
           (optimize (speed 3) (safety 0)))
  (labels ((even (x)
             (declare (type fixnum x))
             (if (zerop x)
                 t
                 (odd (- x 1))))
           (odd (x)
             (declare (type fixnum x))
             (if (zerop x)
                 nil
                 (even (- x 1)))))
    (list (even x) (odd x))))

then execute (disassemble 'doit2), the output includes "JMP L4" but there's no line of assembly code with an L4 label. Maybe the disassembly is truncated?

Revision history for this message
Stas Boukarev (stassats) wrote :

It's showing only the current function, if you want to see everything you need to use sb-disassem:disassemble-code-component.

Changed in sbcl:
status: New → Invalid
Revision history for this message
Robert Brown (robert-brown) wrote :

Thanks very much. Also, sb-c:dis seems output what I was expecting.

Revision history for this message
Fedorov Alexander (gleefre) wrote (last edit ):

I believe that it is a valid bug -- such "undefined" labels don't make any sense.

A bit of context:

Local functions are not shown by DISASSEMBLE since sbcl-2.2.1; or more exactly after this commit: https://github.com/sbcl/sbcl/commit/be5c6d037ba032717638f21d515444cf255e4cbd. As mentioned in its message:
> This makes previously visible local functions disappear, but they were not consistently included either.

I think that the next sentence could've been a FIXME instead:
> A different mechanism is needed to decide whether a local function is called by the target function.

A fuller example:

* (defun foo ()
    (labels ((rec (l) (and l (cons l (rec (cdr l))))))
      (rec '(1 2 3))))
FOO
* (disassemble 'foo)
; disassembly for FOO
; Size: 20 bytes. Origin: #x54E1025F ; FOO
; 5F: 498B4510 MOV RAX, [R13+16] ; thread.binding-stack-pointer
; 63: 488945F8 MOV [RBP-8], RAX
; 67: 488B35C2FFFFFF MOV RSI, [RIP-62] ; '(1 2 3)
; 6E: EB03 JMP L0 ; <----------- here!
; 70: 8F4508 POP QWORD PTR [RBP+8]

It can also be shown in a note -- when a function is compiled by a file compiler and then loaded:

;;;; foo.lisp
(defun foo ()
  (labels ((rec (x)
             (if (= x 0)
                 0
                 (1+ (rec (1- x))))))
    #'rec))

* (compile-file "foo")
; ...
* (load "foo")
T
* (disassemble 'foo)
; disassembly for FOO
; Size: 17 bytes. Origin: #x5515C08F ; FOO
; 8F: 498B4510 MOV RAX, [R13+16] ; thread.binding-stack-pointer
; 93: 488945F8 MOV [RBP-8], RAX
; 97: 8D150E000000 LEA EDX, [RIP+14] ; = L0 ; <----------- here!
; 9D: C9 LEAVE
; 9E: F8 CLC
; 9F: C3 RET
NIL

I tested this on both sbcl-master & sbcl-2.4.0; linux, x86-64.

uname -a:
Linux grolter-T16 6.2.0-39-generic #40-Ubuntu SMP PREEMPT_DYNAMIC Tue Nov 14 14:18:00 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux

To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.