1 ;;;; stuff that creates debugger information from the compiler's
2 ;;;; internal data structures
4 ;;;; This software is part of the SBCL system. See the README file for
7 ;;;; This software is derived from the CMU CL system, which was
8 ;;;; written at Carnegie Mellon University and released into the
9 ;;;; public domain. The software is in the public domain and is
10 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
11 ;;;; files for more information.
15 (deftype byte-buffer
() '(vector (unsigned-byte 8)))
16 (defvar *byte-buffer
*)
17 (declaim (type byte-buffer
*byte-buffer
*))
19 (declaim (type (vector t
) *contexts
*))
24 (deftype location-kind
()
25 '(member :unknown-return
:known-return
:internal-error
:non-local-exit
26 :block-start
:call-site
:single-value-return
:non-local-entry
29 ;;; The LOCATION-INFO structure holds the information what we need
30 ;;; about locations which code generation decided were "interesting".
31 (defstruct (location-info
32 (:constructor make-location-info
(kind label vop context
))
34 ;; The kind of location noted.
35 (kind nil
:type location-kind
)
37 ;; The label pointing to the interesting code location.
38 (label nil
:type
(or label index null
))
39 ;; The VOP that emitted this location (for node, save-set, ir2-block, etc.)
42 (def!struct
(restart-location
43 (:constructor make-restart-location
(&optional label tn
))
45 (label nil
:type
(or null label
))
46 (tn nil
:type
(or null tn
) :read-only t
))
47 (!set-load-form-method restart-location
(:xc
:target
) :ignore-it
)
49 ;;; This is called during code generation in places where there is an
50 ;;; "interesting" location: someplace where we are likely to end up
51 ;;; in the debugger, and thus want debug info.
52 (defun note-debug-location (vop label kind
&optional context
)
53 (declare (type vop vop
) (type (or label null
) label
)
54 (type location-kind kind
))
55 (let ((location (make-location-info kind label vop context
)))
56 (setf (ir2-block-locations (vop-block vop
))
57 (nconc (ir2-block-locations (vop-block vop
))
61 #!-sb-fluid
(declaim (inline ir2-block-physenv
))
62 (defun ir2-block-physenv (2block)
63 (declare (type ir2-block
2block
))
64 (block-physenv (ir2-block-block 2block
)))
66 (defun make-lexenv-var-cache (lexenv)
67 (or (lexenv-var-cache lexenv
)
68 (let ((cache (make-hash-table :test
#'eq
)))
69 (labels ((populate (lexenv)
70 (loop for
(nil . var
) in
(lexenv-vars lexenv
)
71 when
(lambda-var-p var
)
72 do
(setf (gethash var cache
) t
))
73 (let* ((lambda (lexenv-lambda lexenv
))
74 (call-lexenv (and lambda
75 (lambda-call-lexenv lambda
))))
76 (cond ((not call-lexenv
))
77 ((lexenv-var-cache call-lexenv
)
78 (loop for var being each hash-key of
(lexenv-var-cache call-lexenv
)
79 do
(setf (gethash var cache
) t
)))
81 (populate call-lexenv
))))))
83 (setf (lexenv-var-cache lexenv
) cache
))))
85 (defun leaf-visible-to-debugger-p (leaf node
)
86 (gethash leaf
(make-lexenv-var-cache (node-lexenv node
))))
88 ;;; Given a local conflicts vector and an IR2 block to represent the
89 ;;; set of live TNs, and the VAR-LOCS hash-table representing the
90 ;;; variables dumped, compute a bit-vector representing the set of
91 ;;; live variables. If the TN is environment-live, we only mark it as
92 ;;; live when it is in scope at NODE.
93 (defun compute-live-vars (live node block var-locs vop
)
94 (declare (type ir2-block block
) (type local-tn-bit-vector live
)
95 (type hash-table var-locs
) (type node node
)
96 (type (or vop null
) vop
))
97 (let ((res (make-array (logandc2 (+ (hash-table-count var-locs
) 7) 7)
100 (spilled (gethash vop
101 (ir2-component-spilled-vops
102 (component-info *component-being-compiled
*)))))
103 (do-live-tns (tn live block
)
104 (let ((leaf (tn-leaf tn
)))
105 (when (and (lambda-var-p leaf
)
106 (or (not (member (tn-kind tn
)
107 '(:environment
:debug-environment
)))
108 (leaf-visible-to-debugger-p leaf node
))
110 (not (member tn spilled
))))
111 (let ((num (gethash leaf var-locs
)))
113 (setf (sbit res num
) 1))))))
116 ;;; The PC for the location most recently dumped.
117 (defvar *previous-location
*)
118 (declaim (type index
*previous-location
*))
120 (defun encode-restart-location (location x
)
123 (let ((offset (- (label-position (restart-location-label x
))
125 (tn (restart-location-tn x
))
126 (registers-size #.
(integer-length (sb-size (sb-or-lose 'sb
!vm
::registers
)))))
128 (the fixnum
(logior (ash offset registers-size
)
134 (defun decode-restart-location (x)
136 (let ((registers-size #.
(integer-length (sb-size (sb-or-lose 'sb
!vm
::registers
)))))
137 (values (make-sc-offset
138 (sc-number-or-lose 'sb
!vm
::descriptor-reg
)
139 (ldb (byte registers-size
0) x
))
140 (ash x
(- registers-size
)))))
142 ;;; Dump a compiled debug-location into *BYTE-BUFFER* that describes
143 ;;; the code/source map and live info. If true, VOP is the VOP
144 ;;; associated with this location, for use in determining whether TNs
146 (defun dump-1-location (node block kind label live var-locs vop
148 (declare (type node node
) (type ir2-block block
)
149 (type (or null local-tn-bit-vector
) live
)
150 (type (or label index
) label
)
151 (type location-kind kind
)
152 (type hash-table var-locs
) (type (or vop null
) vop
))
154 (let* ((byte-buffer *byte-buffer
*)
155 (stepping (and (combination-p node
)
156 (combination-step-info node
)))
158 (compute-live-vars live node block var-locs vop
)))
159 (anything-alive (and live
161 (path (node-source-path node
))
162 (loc (if (fixnump label
) label
(label-position label
))))
166 compiled-code-location-context
169 compiled-code-location-stepping
172 compiled-code-location-live
174 (if (zerop (source-path-form-number path
))
175 compiled-code-location-zero-form-number
177 (position-or-lose kind
+compiled-code-location-kinds
+))
180 (write-var-integer (- loc
*previous-location
*) byte-buffer
)
181 (setq *previous-location
* loc
)
183 (unless (zerop (source-path-form-number path
))
184 (write-var-integer (source-path-form-number path
) byte-buffer
))
187 (write-packed-bit-vector live byte-buffer
))
189 (write-var-string stepping byte-buffer
))
191 (let ((context (encode-restart-location loc context
)))
192 (write-var-integer (or (position context
*contexts
* :test
#'equal
)
193 (vector-push-extend context
*contexts
*))
197 ;;; Extract context info from a Location-Info structure and use it to
198 ;;; dump a compiled code-location.
199 (defun dump-location-from-info (loc var-locs
)
200 (declare (type location-info loc
)
201 (type hash-table var-locs
))
202 (let ((vop (location-info-vop loc
)))
203 (dump-1-location (vop-node vop
)
205 (location-info-kind loc
)
206 (location-info-label loc
)
210 (location-info-context loc
)))
213 ;;; Dump out the number of locations and the locations for Block.
214 (defun dump-block-locations (block locations var-locs
)
215 (declare (type cblock block
) (list locations
))
216 (unless (and locations
217 (eq (location-info-kind (first locations
))
219 (let ((2block (block-info block
)))
220 (dump-1-location (block-start-node block
)
222 (ir2-block-%label
2block
)
223 (ir2-block-live-out 2block
)
226 (dolist (loc locations
)
227 (dump-location-from-info loc var-locs
))
230 ;;; Return a vector and an integer (or null) suitable for use as the
231 ;;; BLOCKS and TLF-NUMBER in FUN's DEBUG-FUN.
232 (defun compute-debug-blocks (fun var-locs
)
233 (declare (type clambda fun
) (type hash-table var-locs
))
234 (let ((*previous-location
* 0)
235 (physenv (lambda-physenv fun
))
236 (byte-buffer *byte-buffer
*)
240 (setf (fill-pointer byte-buffer
) 0)
241 (do-physenv-ir2-blocks (2block physenv
)
242 (let ((block (ir2-block-block 2block
)))
243 (when (eq (block-info block
) 2block
)
245 (dump-block-locations prev-block
(nreverse (shiftf locations nil
))
247 (setf prev-block block
)))
248 (dolist (loc (ir2-block-locations 2block
))
249 (if (label-elsewhere-p (location-info-label loc
)
250 (location-info-kind loc
))
251 (push loc elsewhere-locations
)
252 (push loc locations
))))
254 (dump-block-locations prev-block
(nreverse locations
) var-locs
)
256 (when elsewhere-locations
257 (dolist (loc (nreverse elsewhere-locations
))
258 (dump-location-from-info loc var-locs
)))
260 (lz-compress (coerce byte-buffer
261 '(simple-array (unsigned-byte 8) (*))))))
262 (logically-readonlyize
263 (!make-specialized-array
(length compressed
) '(unsigned-byte 8)
266 ;;; Return DEBUG-SOURCE structure containing information derived from
268 (defun debug-source-for-info (info &key function
)
269 (declare (type source-info info
))
270 (let ((file-info (get-toplevelish-file-info info
)))
272 :compiled
(source-info-start-time info
)
274 :namestring
(or *source-namestring
*
275 (make-file-info-namestring
276 (if (pathnamep (file-info-name file-info
))
277 (file-info-name file-info
))
279 :created
(file-info-write-date file-info
)
281 (let ((direct-file-info (source-info-file-info info
)))
282 (when (eq :lisp
(file-info-name direct-file-info
))
283 (elt (file-info-forms direct-file-info
) 0))))
284 :function function
)))
286 (defun smallest-element-type (integer negative
)
287 (let ((bits (max (+ (integer-length integer
)
293 (if (= (logcount bits
) 1) ;; power of two?
296 (ash 1 (integer-length bits
))))))
298 ;;; Given an arbitrary sequence, coerce it to an unsigned vector if
299 ;;; possible. Ordinarily we coerce it to the smallest specialized
301 ;;; During cross-compilation the in-memory representation is opaque -
302 ;;; we don't care how it looks, but can recover the intended specialization.
303 (defun coerce-to-smallest-eltype (seq)
304 (let ((max-positive 0)
310 (when (>= x max-positive
)
311 (setf max-positive x
)))
314 (when (>= abs max-negative
)
315 (setf max-negative abs
))))
317 (return-from coerce-to-smallest-eltype
318 (logically-readonlyize
319 (coerce seq
'simple-vector
)))))))
322 (incf length
) ; so not to traverse again to compute it
324 (dovector (i seq
(setq length
(length seq
)))
328 (logically-readonlyize
329 (!make-specialized-array length
330 (smallest-element-type (max max-positive
332 (plusp max-negative
))
335 (defun compact-vector (sequence)
336 (cond ((and (= (length sequence
) 1)
337 (not (vectorp (elt sequence
0))))
340 (coerce-to-smallest-eltype sequence
))))
344 ;;; Return a SC-OFFSET describing TN's location.
345 (defun tn-sc-offset (tn)
346 (declare (type tn tn
))
347 (make-sc-offset (sc-number (tn-sc tn
))
350 (defun lambda-ancestor-p (maybe-ancestor maybe-descendant
)
351 (declare (type clambda maybe-ancestor
)
352 (type (or clambda null
) maybe-descendant
))
354 (when (eq maybe-ancestor maybe-descendant
)
356 (setf maybe-descendant
(lambda-parent maybe-descendant
))
357 (when (null maybe-descendant
)
360 ;;; Dump info to represent VAR's location being TN. ID is an integer
361 ;;; that makes VAR's name unique in the function. BUFFER is the vector
362 ;;; we stick the result in. If MINIMAL, we suppress name dumping, and
363 ;;; set the minimal flag.
365 ;;; The DEBUG-VAR is only marked as always-live if the TN is
366 ;;; environment live and is an argument. If a :DEBUG-ENVIRONMENT TN,
367 ;;; then we also exclude set variables, since the variable is not
368 ;;; guaranteed to be live everywhere in that case.
369 (defun dump-1-var (fun var tn minimal buffer
&optional same-name-p
)
370 (declare (type lambda-var var
) (type (or tn null
) tn
)
372 (let* ((name (leaf-debug-name var
))
373 (save-tn (and tn
(tn-save-tn tn
)))
374 (kind (and tn
(tn-kind tn
)))
376 (info (lambda-var-arg-info var
))
377 (indirect (and (lambda-var-indirect var
)
378 (not (lambda-var-explicit-value-cell var
))
379 (neq (lambda-physenv fun
)
380 (lambda-physenv (lambda-var-home var
)))))
382 (declare (type index flags
))
384 (setq flags
(logior flags compiled-debug-var-minimal-p
))
385 (unless (and tn
(tn-offset tn
))
386 (setq flags
(logior flags compiled-debug-var-deleted-p
))))
387 (when (and (or (eq kind
:environment
)
388 (and (eq kind
:debug-environment
)
389 (null (basic-var-sets var
))))
390 (not (gethash tn
(ir2-component-spilled-tns
391 (component-info *component-being-compiled
*))))
392 (lambda-ancestor-p (lambda-var-home var
) fun
))
393 (setq flags
(logior flags compiled-debug-var-environment-live
)))
395 (setq flags
(logior flags compiled-debug-var-save-loc-p
)))
397 (setq flags
(logior flags compiled-debug-var-indirect-p
)))
399 (case (arg-info-kind info
)
401 (setq flags
(logior flags compiled-debug-var-more-context-p
)
404 (setq flags
(logior flags compiled-debug-var-more-count-p
)
406 (when (and same-name-p
407 (not (or more minimal
)))
408 (setf flags
(logior flags compiled-debug-var-same-name-p
)))
411 (setf (ldb (byte 27 8) flags
) (tn-sc-offset tn
))
413 (setf (ldb (byte 27 35) flags
) (tn-sc-offset save-tn
))))
415 (if (and tn
(tn-offset tn
))
416 (setf (ldb (byte 27 8) flags
) (tn-sc-offset tn
))
419 (setf (ldb (byte 27 35) flags
) (tn-sc-offset save-tn
)))))
420 (vector-push-extend flags buffer
)
423 more
) ;; &more vars need no name
424 ;; Dumping uninterned symbols as debug var names is kinda silly.
425 ;; Reconstruction of the name on fasl load produces a new gensym anyway.
426 ;; So rather than waste symbol space, just dump such symbols as strings,
427 ;; and PARSE-COMPILED-DEBUG-VARS can create the interned symbol.
428 ;; This reduces core size by omitting zillions of symbols whose names
429 ;; are spelled the same.
430 (vector-push-extend (if (symbol-package name
) name
(string name
)) buffer
))
433 ;; Indirect variables live in the parent frame, and are
434 ;; accessed through a saved frame pointer.
435 ;; The first one/two sc-offsets are for the frame pointer,
436 ;; the third is for the stack offset.
438 (vector-push-extend (tn-sc-offset tn
) buffer
)
441 (vector-push-extend (tn-sc-offset save-tn
) buffer
))
442 (vector-push-extend (tn-sc-offset (leaf-info var
)) buffer
))
445 (if (and tn
(tn-offset tn
))
446 (vector-push-extend (tn-sc-offset tn
) buffer
)
449 (vector-push-extend (tn-sc-offset save-tn
) buffer
)))))
452 ;;; Return a vector suitable for use as the DEBUG-FUN-VARS
453 ;;; of FUN. LEVEL is the current DEBUG-INFO quality. VAR-LOCS is a
454 ;;; hash table in which we enter the translation from LAMBDA-VARS to
455 ;;; the relative position of that variable's location in the resulting
457 (defun compute-vars (fun level var-locs
)
458 (declare (type clambda fun
) (type hash-table var-locs
))
460 (labels ((frob-leaf (leaf tn gensym-p
)
461 (let ((name (leaf-debug-name leaf
)))
462 (when (and name
(leaf-refs leaf
) (tn-offset tn
)
463 (or gensym-p
(symbol-package name
)))
464 (vars (cons leaf tn
)))))
465 (frob-lambda (x gensym-p
)
466 (dolist (leaf (lambda-vars x
))
467 (frob-leaf leaf
(leaf-info leaf
) gensym-p
))))
470 (dolist (x (ir2-physenv-closure (physenv-info (lambda-physenv fun
))))
471 (let ((thing (car x
)))
472 (when (lambda-var-p thing
)
473 (frob-leaf thing
(cdr x
) (>= level
2)))))
475 (dolist (let (lambda-lets fun
))
476 (frob-lambda let
(>= level
2)))))
478 (let ((sorted (sort (vars) #'string
<
480 (symbol-name (leaf-debug-name (car x
))))))
483 (buffer (make-array 0 :fill-pointer
0 :adjustable t
))
484 ;; XEPs don't have any useful variables
485 (minimal (eq (functional-kind fun
) :external
)))
486 (declare (type index i
))
489 (name (leaf-debug-name var
)))
490 (dump-1-var fun var
(cdr x
) minimal buffer
491 (and prev-name
(eq prev-name name
)))
492 (setf prev-name name
)
493 (setf (gethash var var-locs
) i
)
495 (compact-vector buffer
))))
497 ;;; Return a vector suitable for use as the DEBUG-FUN-VARS of
498 ;;; FUN, representing the arguments to FUN in minimal variable format.
499 (defun compute-minimal-vars (fun)
500 (declare (type clambda fun
))
501 (let ((buffer (make-array 0 :fill-pointer
0 :adjustable t
)))
502 (dolist (var (lambda-vars fun
))
503 (dump-1-var fun var
(leaf-info var
) t buffer
))
504 (compact-vector buffer
)))
506 ;;; Return VAR's relative position in the function's variables (determined
507 ;;; from the VAR-LOCS hashtable). If VAR is deleted, then return DEBUG-INFO-VAR-DELETED.
508 (defun debug-location-for (var var-locs
)
509 (declare (type lambda-var var
) (type hash-table var-locs
))
510 (let ((res (gethash var var-locs
)))
513 (aver (or (null (leaf-refs var
))
514 (not (tn-offset (leaf-info var
)))))
515 debug-info-var-deleted
))))
517 ;;;; arguments/returns
519 ;;; Return a vector to be used as the COMPILED-DEBUG-FUN-ARGS for FUN.
520 ;;; If FUN is the MAIN-ENTRY for an optional dispatch, then look at
521 ;;; the ARGLIST to determine the syntax, otherwise pretend all
522 ;;; arguments are fixed.
524 ;;; ### This assumption breaks down in EPs other than the main-entry,
525 ;;; since they may or may not have supplied-p vars, etc.
526 (defun compute-args (fun var-locs
)
527 (declare (type clambda fun
) (type hash-table var-locs
))
529 (let ((od (lambda-optional-dispatch fun
)))
530 (if (and od
(eq (optional-dispatch-main-entry od
) fun
))
531 (let ((actual-vars (lambda-vars fun
))
533 (labels ((one-arg (arg)
534 (let ((info (lambda-var-arg-info arg
))
535 (actual (pop actual-vars
)))
537 (case (arg-info-kind info
)
539 (res (arg-info-key info
)))
541 (let ((more (arg-info-default info
)))
542 (cond ((and (consp more
) (third more
))
543 (one-arg (first (arg-info-default info
)))
544 (one-arg (second (arg-info-default info
)))
545 (return-from one-arg
))
547 (setf (arg-info-default info
) t
)))
548 (res debug-info-var-rest
)))
550 (res debug-info-var-more
))
553 (res debug-info-var-optional
)
554 (setq saw-optional t
))))
555 (res (debug-location-for actual var-locs
))
556 (when (arg-info-supplied-p info
)
557 (res debug-info-var-supplied-p
)
558 (res (debug-location-for (pop actual-vars
) var-locs
))))
560 (res (debug-location-for actual var-locs
)))))))
561 (dolist (arg (optional-dispatch-arglist od
))
563 (dolist (var (lambda-vars fun
))
564 (res (debug-location-for var var-locs
)))))
566 (compact-vector (res))))
568 ;;; Return a vector of SC offsets describing FUN's return locations.
569 ;;; (Must be known values return...)
570 (defun compute-debug-returns (fun)
571 (coerce-to-smallest-eltype
572 (mapcar #'tn-sc-offset
573 (return-info-locations (tail-set-info (lambda-tail-set fun
))))))
577 ;;; Return a C-D-F structure with all the mandatory slots filled in.
578 (defun dfun-from-fun (fun)
579 (declare (type clambda fun
))
580 (let* ((2env (physenv-info (lambda-physenv fun
)))
581 (dispatch (lambda-optional-dispatch fun
))
582 (main-p (and dispatch
583 (eq fun
(optional-dispatch-main-entry dispatch
))))
584 (kind (if main-p nil
(functional-kind fun
)))
585 (name (leaf-debug-name fun
))
586 (name (if (consp name
)
589 (assert (eq kind
:external
))
592 (setf kind
:optional
)
600 (funcall (compiled-debug-fun-ctor kind
)
602 #!-fp-and-pc-standard-save
:return-pc
603 #!-fp-and-pc-standard-save
(tn-sc-offset (ir2-physenv-return-pc 2env
))
604 #!-fp-and-pc-standard-save
:old-fp
605 #!-fp-and-pc-standard-save
(tn-sc-offset (ir2-physenv-old-fp 2env
))
608 (label-position (ir2-physenv-environment-start 2env
))
609 (label-position (ir2-physenv-elsewhere-start 2env
))
610 (when (ir2-physenv-closure-save-tn 2env
)
611 (tn-sc-offset (ir2-physenv-closure-save-tn 2env
)))
612 #!+unwind-to-frame-and-call-vop
613 (when (ir2-physenv-bsp-save-tn 2env
)
614 (tn-sc-offset (ir2-physenv-bsp-save-tn 2env
)))))))
616 ;;; Return a complete C-D-F structure for FUN. This involves
617 ;;; determining the DEBUG-INFO level and filling in optional slots as
619 (defun compute-1-debug-fun (fun var-locs
)
620 (declare (type clambda fun
) (type hash-table var-locs
))
621 (let* ((dfun (dfun-from-fun fun
))
622 (actual-level (policy (lambda-bind fun
) compute-debug-fun
))
623 (level (cond #!+sb-dyncount
624 (*collect-dynamic-statistics
*
625 (max actual-level
2))
627 (cond ((or (and (zerop level
)
628 (let ((od (lambda-optional-dispatch fun
)))
630 (not (eq (optional-dispatch-main-entry od
) fun
)))))
631 (eq (compiled-debug-fun-kind dfun
) :more
))
632 (setf (compiled-debug-fun-vars dfun
)
633 (compute-minimal-vars fun
))
634 (setf (compiled-debug-fun-arguments dfun
) :minimal
))
636 (setf (compiled-debug-fun-vars dfun
)
637 (compute-vars fun level var-locs
))
638 (setf (compiled-debug-fun-arguments dfun
)
639 (compute-args fun var-locs
))))
640 (setf (compiled-debug-fun-form-number dfun
)
641 (source-path-form-number (node-source-path (lambda-bind fun
))))
643 (setf (compiled-debug-fun-blocks dfun
)
644 (compute-debug-blocks fun var-locs
)))
646 (setf (compiled-debug-fun-returns dfun
) :standard
)
647 (let ((info (tail-set-info (lambda-tail-set fun
))))
649 (cond ((eq (return-info-kind info
) :unknown
)
650 (setf (compiled-debug-fun-returns dfun
)
653 (setf (compiled-debug-fun-returns dfun
)
654 (compute-debug-returns fun
)))))))
657 ;;;; full component dumping
659 ;;; Compute the full form (simple-vector) function map.
660 (defun compute-debug-fun-map (sorted)
661 (declare (list sorted
))
662 (let* ((len (1- (* (length sorted
) 2)))
663 (funs-vec (make-array len
)))
665 (sorted sorted
(cdr sorted
)))
668 (let ((dfun (car sorted
)))
670 (setf (svref funs-vec i
) (car dfun
)))
671 (setf (svref funs-vec
(1+ i
)) (cdr dfun
))))
674 ;;; Return a DEBUG-INFO structure describing COMPONENT. This has to be
675 ;;; called after assembly so that source map information is available.
676 (defun debug-info-for-component (component)
677 (declare (type component component
))
679 (var-locs (make-hash-table :test
'eq
))
680 (*byte-buffer
* (make-array 10
681 :element-type
'(unsigned-byte 8)
684 (*contexts
* (make-array 10
688 (dolist (lambda (component-lambdas component
))
690 (let ((tlf-num (source-path-tlf-number
691 (node-source-path (lambda-bind lambda
)))))
692 (if component-tlf-num
693 (aver (= component-tlf-num tlf-num
))
694 (setf component-tlf-num tlf-num
))
695 (push (cons (label-position (block-label (lambda-block lambda
)))
696 (compute-1-debug-fun lambda var-locs
))
698 (let* ((sorted (sort dfuns
#'< :key
#'car
))
699 (fun-map (compute-debug-fun-map sorted
)))
700 (make-compiled-debug-info
701 ;; COMPONENT-NAME is often not useful, and sometimes completely fubar.
702 ;; Function names, on the other hand, are seldom unhelpful,
703 ;; so if there's only one function, pick that as the component name.
704 ;; Otherwise preserve whatever crummy name was already assigned.
705 :name
(let* ((2comp (component-info component
))
706 (entries (sb!c
::ir2-component-entries
2comp
)))
707 (or (and (not (cdr entries
))
708 (sb!c
::entry-info-name
(car entries
)))
709 (component-name component
)))
711 :tlf-number component-tlf-num
713 (and component-tlf-num
714 (aref (file-info-positions
715 (source-info-file-info *source-info
*))
717 :contexts
(compact-vector *contexts
*)))))
719 ;;; Write BITS out to BYTE-BUFFER in backend byte order. The length of
720 ;;; BITS must be evenly divisible by eight.
721 (defun write-packed-bit-vector (bits byte-buffer
)
722 (declare (type simple-bit-vector bits
) (type byte-buffer byte-buffer
))
724 ;; Enforce constraint from CMU-CL-era comment.
725 (aver (zerop (mod (length bits
) 8)))
727 (multiple-value-bind (initial step done
)
728 (ecase *backend-byte-order
*
729 (:little-endian
(values 0 1 8))
730 (:big-endian
(values 7 -
1 -
1)))
731 (let ((shift initial
)
733 (dotimes (i (length bits
))
734 (let ((int (aref bits i
)))
735 (setf byte
(logior byte
(ash int shift
)))
738 (vector-push-extend byte byte-buffer
)
741 (unless (= shift initial
)
742 (vector-push-extend byte byte-buffer
))))