Fix make-array transforms.
[sbcl.git] / src / compiler / debug-dump.lisp
1 ;;;; stuff that creates debugger information from the compiler's
2 ;;;; internal data structures
3
4 ;;;; This software is part of the SBCL system. See the README file for
5 ;;;; more information.
6 ;;;;
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.
12
13 (in-package "SB!C")
14
15 (deftype byte-buffer () '(vector (unsigned-byte 8)))
16 (defvar *byte-buffer*)
17 (declaim (type byte-buffer *byte-buffer*))
18 \f
19 ;;;; debug blocks
20
21 (deftype location-kind ()
22   '(member :unknown-return :known-return :internal-error :non-local-exit
23            :block-start :call-site :single-value-return :non-local-entry
24            :step-before-vop))
25
26 ;;; The LOCATION-INFO structure holds the information what we need
27 ;;; about locations which code generation decided were "interesting".
28 (defstruct (location-info
29             (:constructor make-location-info (kind label vop))
30             (:copier nil))
31   ;; The kind of location noted.
32   (kind nil :type location-kind)
33   ;; The label pointing to the interesting code location.
34   (label nil :type (or label index null))
35   ;; The VOP that emitted this location (for node, save-set, ir2-block, etc.)
36   (vop nil :type vop))
37
38 ;;; This is called during code generation in places where there is an
39 ;;; "interesting" location: someplace where we are likely to end up
40 ;;; in the debugger, and thus want debug info.
41 (defun note-debug-location (vop label kind)
42   (declare (type vop vop) (type (or label null) label)
43            (type location-kind kind))
44   (let ((location (make-location-info kind label vop)))
45     (setf (ir2-block-locations (vop-block vop))
46           (nconc (ir2-block-locations (vop-block vop))
47                  (list location)))
48     location))
49
50 #!-sb-fluid (declaim (inline ir2-block-physenv))
51 (defun ir2-block-physenv (2block)
52   (declare (type ir2-block 2block))
53   (block-physenv (ir2-block-block 2block)))
54
55 ;;; Given a local conflicts vector and an IR2 block to represent the
56 ;;; set of live TNs, and the VAR-LOCS hash-table representing the
57 ;;; variables dumped, compute a bit-vector representing the set of
58 ;;; live variables. If the TN is environment-live, we only mark it as
59 ;;; live when it is in scope at NODE.
60 (defun compute-live-vars (live node block var-locs vop)
61   (declare (type ir2-block block) (type local-tn-bit-vector live)
62            (type hash-table var-locs) (type node node)
63            (type (or vop null) vop))
64   (let ((res (make-array (logandc2 (+ (hash-table-count var-locs) 7) 7)
65                          :element-type 'bit
66                          :initial-element 0))
67         (spilled (gethash vop
68                           (ir2-component-spilled-vops
69                            (component-info *component-being-compiled*)))))
70     (do-live-tns (tn live block)
71       (let ((leaf (tn-leaf tn)))
72         (when (and (lambda-var-p leaf)
73                    (or (not (member (tn-kind tn)
74                                     '(:environment :debug-environment)))
75                        (rassoc leaf (lexenv-vars (node-lexenv node))))
76                    (or (null spilled)
77                        (not (member tn spilled))))
78           (let ((num (gethash leaf var-locs)))
79             (when num
80               (setf (sbit res num) 1))))))
81     res))
82
83 ;;; The PC for the location most recently dumped.
84 (defvar *previous-location*)
85 (declaim (type index *previous-location*))
86
87 ;;; Dump a compiled debug-location into *BYTE-BUFFER* that describes
88 ;;; the code/source map and live info. If true, VOP is the VOP
89 ;;; associated with this location, for use in determining whether TNs
90 ;;; are spilled.
91 (defun dump-1-location (node block kind tlf-num label live var-locs vop)
92   (declare (type node node) (type ir2-block block)
93            (type (or null local-tn-bit-vector) live)
94            (type (or label index) label)
95            (type location-kind kind) (type (or index null) tlf-num)
96            (type hash-table var-locs) (type (or vop null) vop))
97
98   (vector-push-extend
99    (dpb (position-or-lose kind *compiled-code-location-kinds*)
100         compiled-code-location-kind-byte
101         0)
102    *byte-buffer*)
103
104   (let ((loc (if (fixnump label) label (label-position label))))
105     (write-var-integer (- loc *previous-location*) *byte-buffer*)
106     (setq *previous-location* loc))
107
108   (let ((path (node-source-path node)))
109     (unless tlf-num
110       (write-var-integer (source-path-tlf-number path) *byte-buffer*))
111     (write-var-integer (source-path-form-number path) *byte-buffer*))
112
113   (if live
114       (write-packed-bit-vector (compute-live-vars live node block var-locs vop)
115                                *byte-buffer*)
116       (write-packed-bit-vector
117        (make-array (logandc2 (+ (hash-table-count var-locs) 7) 7)
118                    :initial-element 0
119                    :element-type 'bit)
120        *byte-buffer*))
121
122   (write-var-string (or (and (typep node 'combination)
123                              (combination-step-info node))
124                         "")
125                     *byte-buffer*)
126   (values))
127
128 ;;; Extract context info from a Location-Info structure and use it to
129 ;;; dump a compiled code-location.
130 (defun dump-location-from-info (loc tlf-num var-locs)
131   (declare (type location-info loc) (type (or index null) tlf-num)
132            (type hash-table var-locs))
133   (let ((vop (location-info-vop loc)))
134     (dump-1-location (vop-node vop)
135                      (vop-block vop)
136                      (location-info-kind loc)
137                      tlf-num
138                      (location-info-label loc)
139                      (vop-save-set vop)
140                      var-locs
141                      vop))
142   (values))
143
144 ;;; Scan all the blocks, determining if all locations are in the same
145 ;;; TLF, and returning it or NIL.
146 (defun find-tlf-number (fun)
147   (declare (type clambda fun))
148   (let ((res (source-path-tlf-number (node-source-path (lambda-bind fun)))))
149     (declare (type (or index null) res))
150     (do-physenv-ir2-blocks (2block (lambda-physenv fun))
151       (let ((block (ir2-block-block 2block)))
152         (when (eq (block-info block) 2block)
153           (unless (eql (source-path-tlf-number
154                         (node-source-path
155                          (block-start-node block)))
156                        res)
157             (setq res nil)))
158
159         (dolist (loc (ir2-block-locations 2block))
160           (unless (eql (source-path-tlf-number
161                         (node-source-path
162                          (vop-node (location-info-vop loc))))
163                        res)
164             (setq res nil)))))
165     res))
166
167 ;;; Dump out the number of locations and the locations for Block.
168 (defun dump-block-locations (block locations tlf-num var-locs)
169   (declare (type cblock block) (list locations))
170   (if (and locations
171            (eq (location-info-kind (first locations))
172                :non-local-entry))
173       (write-var-integer (length locations) *byte-buffer*)
174       (let ((2block (block-info block)))
175         (write-var-integer (+ (length locations) 1) *byte-buffer*)
176         (dump-1-location (block-start-node block)
177                          2block :block-start tlf-num
178                          (ir2-block-%label 2block)
179                          (ir2-block-live-out 2block)
180                          var-locs
181                          nil)))
182   (dolist (loc locations)
183     (dump-location-from-info loc tlf-num var-locs))
184   (values))
185
186 ;;; Dump the successors of Block, being careful not to fly into space
187 ;;; on weird successors.
188 (defun dump-block-successors (block physenv)
189   (declare (type cblock block) (type physenv physenv))
190   (let* ((tail (component-tail (block-component block)))
191          (succ (block-succ block))
192          (valid-succ
193           (if (and succ
194                    (or (eq (car succ) tail)
195                        (not (eq (block-physenv (car succ)) physenv))))
196               ()
197               succ)))
198     (vector-push-extend
199      (dpb (length valid-succ) compiled-debug-block-nsucc-byte 0)
200      *byte-buffer*)
201     (let ((base (block-number
202                  (node-block
203                   (lambda-bind (physenv-lambda physenv))))))
204       (dolist (b valid-succ)
205         (write-var-integer
206          (the index (- (block-number b) base))
207          *byte-buffer*))))
208   (values))
209
210 ;;; Return a vector and an integer (or null) suitable for use as the
211 ;;; BLOCKS and TLF-NUMBER in FUN's DEBUG-FUN. This requires two
212 ;;; passes to compute:
213 ;;; -- Scan all blocks, dumping the header and successors followed
214 ;;;    by all the non-elsewhere locations.
215 ;;; -- Dump the elsewhere block header and all the elsewhere
216 ;;;    locations (if any.)
217 (defun compute-debug-blocks (fun var-locs)
218   (declare (type clambda fun) (type hash-table var-locs))
219   (setf (fill-pointer *byte-buffer*) 0)
220   (let ((*previous-location* 0)
221         (tlf-num (find-tlf-number fun))
222         (physenv (lambda-physenv fun))
223         (prev-locs nil)
224         (prev-block nil))
225     (collect ((elsewhere))
226       (do-physenv-ir2-blocks (2block physenv)
227         (let ((block (ir2-block-block 2block)))
228           (when (eq (block-info block) 2block)
229             (when prev-block
230               (dump-block-locations prev-block prev-locs tlf-num var-locs))
231             (setq prev-block block  prev-locs ())
232             (dump-block-successors block physenv)))
233
234         (collect ((here prev-locs))
235           (dolist (loc (ir2-block-locations 2block))
236             (if (label-elsewhere-p (location-info-label loc))
237                 (elsewhere loc)
238                 (here loc)))
239           (setq prev-locs (here))))
240
241       (dump-block-locations prev-block prev-locs tlf-num var-locs)
242
243       (when (elsewhere)
244         (vector-push-extend compiled-debug-block-elsewhere-p *byte-buffer*)
245         (write-var-integer (length (elsewhere)) *byte-buffer*)
246         (dolist (loc (elsewhere))
247           (dump-location-from-info loc tlf-num var-locs))))
248
249     (values (copy-seq *byte-buffer*) tlf-num)))
250 \f
251 ;;; Return DEBUG-SOURCE structure containing information derived from
252 ;;; INFO.
253 (defun debug-source-for-info (info &key function)
254   (declare (type source-info info))
255   (let ((file-info (get-toplevelish-file-info info)))
256     (make-debug-source
257      :compiled (source-info-start-time info)
258
259      :namestring (or *source-namestring*
260                      (make-file-info-namestring
261                       (if (pathnamep (file-info-name file-info))
262                           (file-info-name file-info))
263                       file-info))
264      :created (file-info-write-date file-info)
265      :source-root (file-info-source-root file-info)
266      :start-positions (coerce-to-smallest-eltype
267                        (file-info-positions file-info))
268
269      :form (let ((direct-file-info (source-info-file-info info)))
270              (when (eq :lisp (file-info-name direct-file-info))
271                (elt (file-info-forms direct-file-info) 0)))
272      :function function)))
273
274 ;;; Given an arbitrary sequence, coerce it to an unsigned vector if
275 ;;; possible. Ordinarily we coerce it to the smallest specialized
276 ;;; vector we can. However, we also have a special hack for
277 ;;; cross-compiling at bootstrap time, when arbitrarily-specialized
278 ;;; vectors aren't fully supported: in that case, we coerce it only to
279 ;;; a vector whose element size is an integer multiple of output byte
280 ;;; size.
281 (defun coerce-to-smallest-eltype (seq)
282   (let ((maxoid 0))
283     (flet ((frob (x)
284              (if (typep x 'unsigned-byte)
285                  (when (>= x maxoid)
286                    (setf maxoid x))
287                  (return-from coerce-to-smallest-eltype
288                    (coerce seq 'simple-vector)))))
289       (if (listp seq)
290           (dolist (i seq)
291             (frob i))
292           (dovector (i seq)
293             (frob i)))
294       (let ((specializer `(unsigned-byte
295                            ,(etypecase maxoid
296                               ((unsigned-byte 8) 8)
297                               ((unsigned-byte 16) 16)
298                               ((unsigned-byte 32) 32)))))
299         ;; cross-compilers beware! It would be possible for the
300         ;; upgraded-array-element-type of (UNSIGNED-BYTE 16) to be
301         ;; (SIGNED-BYTE 17) or (UNSIGNED-BYTE 23), and this is
302         ;; completely valid by ANSI.  However, the cross-compiler
303         ;; doesn't know how to dump (in practice) anything but the
304         ;; above three specialized array types, so make it break here
305         ;; if this is violated.
306         #+sb-xc-host
307         (aver
308          ;; not SB!XC:UPGRADED-ARRAY-ELEMENT-TYPE, because we are
309          ;; worried about whether the host's implementation of arrays.
310          (let ((uaet (upgraded-array-element-type specializer)))
311            (dolist (et '((unsigned-byte 8)
312                          (unsigned-byte 16)
313                          (unsigned-byte 32))
314                     nil)
315              (when (and (subtypep et uaet) (subtypep uaet et))
316                (return t)))))
317         (coerce seq `(simple-array ,specializer (*)))))))
318 \f
319 ;;;; variables
320
321 ;;; Return a SC-OFFSET describing TN's location.
322 (defun tn-sc-offset (tn)
323   (declare (type tn tn))
324   (make-sc-offset (sc-number (tn-sc tn))
325                   (tn-offset tn)))
326
327 (defun lambda-ancestor-p (maybe-ancestor maybe-descendant)
328   (declare (type clambda maybe-ancestor)
329            (type (or clambda null) maybe-descendant))
330   (loop
331      (when (eq maybe-ancestor maybe-descendant)
332        (return t))
333      (setf maybe-descendant (lambda-parent maybe-descendant))
334      (when (null maybe-descendant)
335        (return nil))))
336
337 ;;; Dump info to represent VAR's location being TN. ID is an integer
338 ;;; that makes VAR's name unique in the function. BUFFER is the vector
339 ;;; we stick the result in. If MINIMAL, we suppress name dumping, and
340 ;;; set the minimal flag.
341 ;;;
342 ;;; The DEBUG-VAR is only marked as always-live if the TN is
343 ;;; environment live and is an argument. If a :DEBUG-ENVIRONMENT TN,
344 ;;; then we also exclude set variables, since the variable is not
345 ;;; guaranteed to be live everywhere in that case.
346 (defun dump-1-var (fun var tn id minimal buffer)
347   (declare (type lambda-var var) (type (or tn null) tn) (type index id)
348            (type clambda fun))
349   (let* ((name (leaf-debug-name var))
350          (save-tn (and tn (tn-save-tn tn)))
351          (kind (and tn (tn-kind tn)))
352          (flags 0)
353          (info (lambda-var-arg-info var)))
354     (declare (type index flags))
355     (when minimal
356       (setq flags (logior flags compiled-debug-var-minimal-p))
357       (unless (and tn (tn-offset tn))
358         (setq flags (logior flags compiled-debug-var-deleted-p))))
359     (when (and (or (eq kind :environment)
360                    (and (eq kind :debug-environment)
361                         (null (basic-var-sets var))))
362                (not (gethash tn (ir2-component-spilled-tns
363                                  (component-info *component-being-compiled*))))
364                (lambda-ancestor-p (lambda-var-home var) fun))
365       (setq flags (logior flags compiled-debug-var-environment-live)))
366     (when save-tn
367       (setq flags (logior flags compiled-debug-var-save-loc-p)))
368     (unless (or (zerop id) minimal)
369       (setq flags (logior flags compiled-debug-var-id-p)))
370     (when info
371       (case (arg-info-kind info)
372         (:more-context
373          (setq flags (logior flags compiled-debug-var-more-context-p)))
374         (:more-count
375          (setq flags (logior flags compiled-debug-var-more-count-p)))))
376     (vector-push-extend flags buffer)
377     (unless minimal
378       (vector-push-extend name buffer)
379       (unless (zerop id)
380         (vector-push-extend id buffer)))
381     (if (and tn (tn-offset tn))
382         (vector-push-extend (tn-sc-offset tn) buffer)
383         (aver minimal))
384     (when save-tn
385       (vector-push-extend (tn-sc-offset save-tn) buffer)))
386   (values))
387
388 ;;; Return a vector suitable for use as the DEBUG-FUN-VARS
389 ;;; of FUN. LEVEL is the current DEBUG-INFO quality. VAR-LOCS is a
390 ;;; hash table in which we enter the translation from LAMBDA-VARS to
391 ;;; the relative position of that variable's location in the resulting
392 ;;; vector.
393 (defun compute-vars (fun level var-locs)
394   (declare (type clambda fun) (type hash-table var-locs))
395   (collect ((vars))
396     (labels ((frob-leaf (leaf tn gensym-p)
397                (let ((name (leaf-debug-name leaf)))
398                  (when (and name (leaf-refs leaf) (tn-offset tn)
399                             (or gensym-p (symbol-package name)))
400                    (vars (cons leaf tn)))))
401              (frob-lambda (x gensym-p)
402                (dolist (leaf (lambda-vars x))
403                  (frob-leaf leaf (leaf-info leaf) gensym-p))))
404       (frob-lambda fun t)
405       (when (>= level 2)
406         (dolist (x (ir2-physenv-closure (physenv-info (lambda-physenv fun))))
407           (let ((thing (car x)))
408             (when (lambda-var-p thing)
409               (frob-leaf thing (cdr x) (= level 3)))))
410
411         (dolist (let (lambda-lets fun))
412           (frob-lambda let (= level 3)))))
413
414     (let ((sorted (sort (vars) #'string<
415                         :key (lambda (x)
416                                (symbol-name (leaf-debug-name (car x))))))
417           (prev-name nil)
418           (id 0)
419           (i 0)
420           (buffer (make-array 0 :fill-pointer 0 :adjustable t)))
421       (declare (type (or simple-string null) prev-name)
422                (type index id i))
423       (dolist (x sorted)
424         (let* ((var (car x))
425                (name (symbol-name (leaf-debug-name var))))
426           (cond ((and prev-name (string= prev-name name))
427                  (incf id))
428                 (t
429                  (setq id 0  prev-name name)))
430           (dump-1-var fun var (cdr x) id nil buffer)
431           (setf (gethash var var-locs) i)
432           (incf i)))
433       (coerce buffer 'simple-vector))))
434
435 ;;; Return a vector suitable for use as the DEBUG-FUN-VARS of
436 ;;; FUN, representing the arguments to FUN in minimal variable format.
437 (defun compute-minimal-vars (fun)
438   (declare (type clambda fun))
439   (let ((buffer (make-array 0 :fill-pointer 0 :adjustable t)))
440     (dolist (var (lambda-vars fun))
441       (dump-1-var fun var (leaf-info var) 0 t buffer))
442     (coerce buffer 'simple-vector)))
443
444 ;;; Return VAR's relative position in the function's variables (determined
445 ;;; from the VAR-LOCS hashtable).  If VAR is deleted, then return DELETED.
446 (defun debug-location-for (var var-locs)
447   (declare (type lambda-var var) (type hash-table var-locs))
448   (let ((res (gethash var var-locs)))
449     (cond (res)
450           (t
451            (aver (or (null (leaf-refs var))
452                      (not (tn-offset (leaf-info var)))))
453            'deleted))))
454 \f
455 ;;;; arguments/returns
456
457 ;;; Return a vector to be used as the COMPILED-DEBUG-FUN-ARGS for FUN.
458 ;;; If FUN is the MAIN-ENTRY for an optional dispatch, then look at
459 ;;; the ARGLIST to determine the syntax, otherwise pretend all
460 ;;; arguments are fixed.
461 ;;;
462 ;;; ### This assumption breaks down in EPs other than the main-entry,
463 ;;; since they may or may not have supplied-p vars, etc.
464 (defun compute-args (fun var-locs)
465   (declare (type clambda fun) (type hash-table var-locs))
466   (collect ((res))
467     (let ((od (lambda-optional-dispatch fun)))
468       (if (and od (eq (optional-dispatch-main-entry od) fun))
469           (let ((actual-vars (lambda-vars fun))
470                 (saw-optional nil))
471             (labels ((one-arg (arg)
472                        (let ((info (lambda-var-arg-info arg))
473                              (actual (pop actual-vars)))
474                          (cond (info
475                                 (case (arg-info-kind info)
476                                   (:keyword
477                                    (res (arg-info-key info)))
478                                   (:rest
479                                    (let ((more (arg-info-default info)))
480                                      (cond ((and (consp more) (third more))
481                                             (one-arg (first (arg-info-default info)))
482                                             (one-arg (second (arg-info-default info)))
483                                             (return-from one-arg))
484                                            (more
485                                             (setf (arg-info-default info) t)))
486                                      (res 'rest-arg)))
487                                   (:more-context
488                                    (res 'more-arg))
489                                   (:optional
490                                    (unless saw-optional
491                                      (res 'optional-args)
492                                      (setq saw-optional t))))
493                                 (res (debug-location-for actual var-locs))
494                                 (when (arg-info-supplied-p info)
495                                   (res 'supplied-p)
496                                   (res (debug-location-for (pop actual-vars) var-locs))))
497                                 (t
498                                  (res (debug-location-for actual var-locs)))))))
499               (dolist (arg (optional-dispatch-arglist od))
500                 (one-arg arg))))
501           (dolist (var (lambda-vars fun))
502             (res (debug-location-for var var-locs)))))
503
504     (coerce-to-smallest-eltype (res))))
505
506 ;;; Return a vector of SC offsets describing FUN's return locations.
507 ;;; (Must be known values return...)
508 (defun compute-debug-returns (fun)
509   (coerce-to-smallest-eltype
510    (mapcar (lambda (loc)
511              (tn-sc-offset loc))
512            (return-info-locations (tail-set-info (lambda-tail-set fun))))))
513 \f
514 ;;;; debug functions
515
516 ;;; Return a C-D-F structure with all the mandatory slots filled in.
517 (defun dfun-from-fun (fun)
518   (declare (type clambda fun))
519   (let* ((2env (physenv-info (lambda-physenv fun)))
520          (dispatch (lambda-optional-dispatch fun))
521          (main-p (and dispatch
522                       (eq fun (optional-dispatch-main-entry dispatch)))))
523     (make-compiled-debug-fun
524      :name (leaf-debug-name fun)
525      :kind (if main-p nil (functional-kind fun))
526      :return-pc (tn-sc-offset (ir2-physenv-return-pc 2env))
527      :old-fp (tn-sc-offset (ir2-physenv-old-fp 2env))
528      :start-pc (label-position (ir2-physenv-environment-start 2env))
529      :elsewhere-pc (label-position (ir2-physenv-elsewhere-start 2env)))))
530
531 ;;; Return a complete C-D-F structure for FUN. This involves
532 ;;; determining the DEBUG-INFO level and filling in optional slots as
533 ;;; appropriate.
534 (defun compute-1-debug-fun (fun var-locs)
535   (declare (type clambda fun) (type hash-table var-locs))
536   (let* ((dfun (dfun-from-fun fun))
537          (actual-level (policy (lambda-bind fun) compute-debug-fun))
538          (level (if #!+sb-dyncount *collect-dynamic-statistics*
539                     #!-sb-dyncount nil
540                     (max actual-level 2)
541                     actual-level))
542          (toplevel-p (eq :toplevel (compiled-debug-fun-kind dfun))))
543     (cond ((or (zerop level) toplevel-p))
544           ((and (<= level 1)
545                 (let ((od (lambda-optional-dispatch fun)))
546                   (or (not od)
547                       (not (eq (optional-dispatch-main-entry od) fun)))))
548            (setf (compiled-debug-fun-vars dfun)
549                  (compute-minimal-vars fun))
550            (setf (compiled-debug-fun-arguments dfun) :minimal))
551           (t
552            (setf (compiled-debug-fun-vars dfun)
553                  (compute-vars fun level var-locs))
554            (setf (compiled-debug-fun-arguments dfun)
555                  (compute-args fun var-locs))))
556
557     (if (and (>= level 2) (not toplevel-p))
558         (multiple-value-bind (blocks tlf-num)
559             (compute-debug-blocks fun var-locs)
560           (setf (compiled-debug-fun-tlf-number dfun) tlf-num)
561           (setf (compiled-debug-fun-blocks dfun) blocks))
562         (setf (compiled-debug-fun-tlf-number dfun) (find-tlf-number fun)))
563
564     (if (xep-p fun)
565         (setf (compiled-debug-fun-returns dfun) :standard)
566         (let ((info (tail-set-info (lambda-tail-set fun))))
567           (when info
568             (cond ((eq (return-info-kind info) :unknown)
569                    (setf (compiled-debug-fun-returns dfun)
570                          :standard))
571                   ((/= level 0)
572                    (setf (compiled-debug-fun-returns dfun)
573                          (compute-debug-returns fun)))))))
574     dfun))
575 \f
576 ;;;; full component dumping
577
578 ;;; Compute the full form (simple-vector) function map.
579 (defun compute-debug-fun-map (sorted)
580   (declare (list sorted))
581   (let* ((len (1- (* (length sorted) 2)))
582          (funs-vec (make-array len)))
583     (do ((i -1 (+ i 2))
584          (sorted sorted (cdr sorted)))
585         ((= i len))
586       (declare (fixnum i))
587       (let ((dfun (car sorted)))
588         (unless (minusp i)
589           (setf (svref funs-vec i) (car dfun)))
590         (setf (svref funs-vec (1+ i)) (cdr dfun))))
591     funs-vec))
592
593 ;;; Return a DEBUG-INFO structure describing COMPONENT. This has to be
594 ;;; called after assembly so that source map information is available.
595 (defun debug-info-for-component (component)
596   (declare (type component component))
597   (let ((dfuns nil)
598         (var-locs (make-hash-table :test 'eq))
599         (*byte-buffer* (make-array 10
600                                    :element-type '(unsigned-byte 8)
601                                    :fill-pointer 0
602                                    :adjustable t)))
603     (dolist (lambda (component-lambdas component))
604       (clrhash var-locs)
605       (push (cons (label-position (block-label (lambda-block lambda)))
606                   (compute-1-debug-fun lambda var-locs))
607             dfuns))
608     (let* ((sorted (sort dfuns #'< :key #'car))
609            (fun-map (compute-debug-fun-map sorted)))
610       (make-compiled-debug-info :name (component-name component)
611                                 :fun-map fun-map))))
612 \f
613 ;;; Write BITS out to BYTE-BUFFER in backend byte order. The length of
614 ;;; BITS must be evenly divisible by eight.
615 (defun write-packed-bit-vector (bits byte-buffer)
616   (declare (type simple-bit-vector bits) (type byte-buffer byte-buffer))
617
618   ;; Enforce constraint from CMU-CL-era comment.
619   (aver (zerop (mod (length bits) 8)))
620
621   (multiple-value-bind (initial step done)
622       (ecase *backend-byte-order*
623         (:little-endian (values 0  1  8))
624         (:big-endian    (values 7 -1 -1)))
625     (let ((shift initial)
626           (byte 0))
627       (dotimes (i (length bits))
628         (let ((int (aref bits i)))
629           (setf byte (logior byte (ash int shift)))
630           (incf shift step))
631         (when (= shift done)
632           (vector-push-extend byte byte-buffer)
633           (setf shift initial
634                 byte 0)))
635       (unless (= shift initial)
636         (vector-push-extend byte byte-buffer))))
637   (values))