X-Git-Url: http://repo.macrolet.net/gitweb/?a=blobdiff_plain;f=src%2Fcompiler%2Fdebug-dump.lisp;h=af7d67f1fe68366cbeb7e5728d854c0f7d7b0248;hb=079ef9dad558ca07cb8178ef428bf738112174fa;hp=62671b878f2804737c6c925007aee31513eb8afd;hpb=db55ad022ec7cc7a2f251918579fdeba7f17dbe0;p=sbcl.git diff --git a/src/compiler/debug-dump.lisp b/src/compiler/debug-dump.lisp index 62671b8..af7d67f 100644 --- a/src/compiler/debug-dump.lisp +++ b/src/compiler/debug-dump.lisp @@ -71,7 +71,7 @@ (when (and (lambda-var-p leaf) (or (not (member (tn-kind tn) '(:environment :debug-environment))) - (rassoc leaf (lexenv-variables (node-lexenv node)))) + (rassoc leaf (lexenv-vars (node-lexenv node)))) (or (null spilled) (not (member tn spilled)))) (let ((num (gethash leaf var-locs))) @@ -141,11 +141,10 @@ (when (eq (block-info block) 2block) (unless (eql (source-path-tlf-number (node-source-path - (continuation-next - (block-start block)))) + (block-start-node block))) res) (setq res nil))) - + (dolist (loc (ir2-block-locations 2block)) (unless (eql (source-path-tlf-number (node-source-path @@ -163,7 +162,7 @@ (write-var-integer (length locations) *byte-buffer*) (let ((2block (block-info block))) (write-var-integer (+ (length locations) 1) *byte-buffer*) - (dump-1-location (continuation-next (block-start block)) + (dump-1-location (block-start-node block) 2block :block-start tlf-num (ir2-block-%label 2block) (ir2-block-live-out 2block) @@ -175,14 +174,14 @@ ;;; Dump the successors of Block, being careful not to fly into space ;;; on weird successors. -(defun dump-block-successors (block env) - (declare (type cblock block) (type physenv env)) +(defun dump-block-successors (block physenv) + (declare (type cblock block) (type physenv physenv)) (let* ((tail (component-tail (block-component block))) (succ (block-succ block)) (valid-succ (if (and succ (or (eq (car succ) tail) - (not (eq (block-physenv (car succ)) env)))) + (not (eq (block-physenv (car succ)) physenv)))) () succ))) (vector-push-extend @@ -190,7 +189,7 @@ *byte-buffer*) (let ((base (block-number (node-block - (lambda-bind (physenv-function env)))))) + (lambda-bind (physenv-lambda physenv)))))) (dolist (b valid-succ) (write-var-integer (the index (- (block-number b) base)) @@ -209,17 +208,17 @@ (setf (fill-pointer *byte-buffer*) 0) (let ((*previous-location* 0) (tlf-num (find-tlf-number fun)) - (env (lambda-physenv fun)) + (physenv (lambda-physenv fun)) (prev-locs nil) (prev-block nil)) (collect ((elsewhere)) - (do-physenv-ir2-blocks (2block env) + (do-physenv-ir2-blocks (2block physenv) (let ((block (ir2-block-block 2block))) (when (eq (block-info block) 2block) (when prev-block (dump-block-locations prev-block prev-locs tlf-num var-locs)) (setq prev-block block prev-locs ()) - (dump-block-successors block env))) + (dump-block-successors block physenv))) (collect ((here prev-locs)) (dolist (loc (ir2-block-locations 2block)) @@ -240,7 +239,7 @@ ;;; Return a list of DEBUG-SOURCE structures containing information ;;; derived from INFO. Unless :BYTE-COMPILE T was specified, we always -;;; dump the Start-Positions, since it is too hard figure out whether +;;; dump the START-POSITIONS, since it is too hard figure out whether ;;; we need them or not. (defun debug-source-for-info (info) (declare (type source-info info)) @@ -262,13 +261,20 @@ (let* ((untruename (file-info-untruename file-info)) (dir (pathname-directory untruename))) (setf (debug-source-name res) + #+sb-xc-host + (let ((src (position "src" dir :test #'string= :from-end t))) + (if src + (format nil "SYS:~{~:@(~A~);~}~:@(~A~).LISP" + (subseq dir src) (pathname-name untruename)) + ;; FIXME: just output/stuff-groveled-from-headers.lisp + (namestring untruename))) + #-sb-xc-host (namestring (if (and dir (eq (first dir) :absolute)) untruename name)))))) (list res))) - ;;; Given an arbitrary sequence, coerce it to an unsigned vector if ;;; possible. Ordinarily we coerce it to the smallest specialized ;;; vector we can. However, we also have a special hack for @@ -277,12 +283,7 @@ ;;; a vector whose element size is an integer multiple of output byte ;;; size. (defun coerce-to-smallest-eltype (seq) - (let ((maxoid #-sb-xc-host 0 - ;; An initial value of 255 prevents us from - ;; specializing the array to anything smaller than - ;; (UNSIGNED-BYTE 8), which keeps the cross-compiler's - ;; portable specialized array output functions happy. - #+sb-xc-host 255)) + (let ((maxoid 0)) (flet ((frob (x) (if (typep x 'unsigned-byte) (when (>= x maxoid) @@ -294,7 +295,30 @@ (frob i)) (dovector (i seq) (frob i))) - (coerce seq `(simple-array (integer 0 ,maxoid) (*)))))) + (let ((specializer `(unsigned-byte + ,(etypecase maxoid + ((unsigned-byte 8) 8) + ((unsigned-byte 16) 16) + ((unsigned-byte 32) 32))))) + ;; cross-compilers beware! It would be possible for the + ;; upgraded-array-element-type of (UNSIGNED-BYTE 16) to be + ;; (SIGNED-BYTE 17) or (UNSIGNED-BYTE 23), and this is + ;; completely valid by ANSI. However, the cross-compiler + ;; doesn't know how to dump (in practice) anything but the + ;; above three specialized array types, so make it break here + ;; if this is violated. + #+sb-xc-host + (aver + ;; not SB!XC:UPGRADED-ARRAY-ELEMENT-TYPE, because we are + ;; worried about whether the host's implementation of arrays. + (let ((uaet (upgraded-array-element-type specializer))) + (dolist (et '((unsigned-byte 8) + (unsigned-byte 16) + (unsigned-byte 32)) + nil) + (when (and (subtypep et uaet) (subtypep uaet et)) + (return t))))) + (coerce seq `(simple-array ,specializer (*))))))) ;;;; variables @@ -304,19 +328,19 @@ (make-sc-offset (sc-number (tn-sc tn)) (tn-offset tn))) -;;; Dump info to represent Var's location being TN. ID is an integer -;;; that makes Var's name unique in the function. Buffer is the vector -;;; we stick the result in. If Minimal is true, we suppress name -;;; dumping, and set the minimal flag. +;;; Dump info to represent VAR's location being TN. ID is an integer +;;; that makes VAR's name unique in the function. BUFFER is the vector +;;; we stick the result in. If MINIMAL, we suppress name dumping, and +;;; set the minimal flag. ;;; -;;; The debug-var is only marked as always-live if the TN is -;;; environment live and is an argument. If a :debug-environment TN, +;;; The DEBUG-VAR is only marked as always-live if the TN is +;;; environment live and is an argument. If a :DEBUG-ENVIRONMENT TN, ;;; then we also exclude set variables, since the variable is not ;;; guaranteed to be live everywhere in that case. -(defun dump-1-variable (fun var tn id minimal buffer) +(defun dump-1-var (fun var tn id minimal buffer) (declare (type lambda-var var) (type (or tn null) tn) (type index id) (type clambda fun)) - (let* ((name (leaf-name var)) + (let* ((name (leaf-debug-name var)) (save-tn (and tn (tn-save-tn tn))) (kind (and tn (tn-kind tn))) (flags 0)) @@ -348,16 +372,16 @@ (vector-push-extend (tn-sc-offset save-tn) buffer))) (values)) -;;; Return a vector suitable for use as the DEBUG-FUN-VARIABLES +;;; Return a vector suitable for use as the DEBUG-FUN-VARS ;;; of FUN. LEVEL is the current DEBUG-INFO quality. VAR-LOCS is a -;;; hashtable in which we enter the translation from LAMBDA-VARS to +;;; hash table in which we enter the translation from LAMBDA-VARS to ;;; the relative position of that variable's location in the resulting ;;; vector. -(defun compute-variables (fun level var-locs) +(defun compute-vars (fun level var-locs) (declare (type clambda fun) (type hash-table var-locs)) (collect ((vars)) (labels ((frob-leaf (leaf tn gensym-p) - (let ((name (leaf-name leaf))) + (let ((name (leaf-debug-name leaf))) (when (and name (leaf-refs leaf) (tn-offset tn) (or gensym-p (symbol-package name))) (vars (cons leaf tn))))) @@ -366,8 +390,7 @@ (frob-leaf leaf (leaf-info leaf) gensym-p)))) (frob-lambda fun t) (when (>= level 2) - (dolist (x (ir2-physenv-environment - (physenv-info (lambda-physenv fun)))) + (dolist (x (ir2-physenv-closure (physenv-info (lambda-physenv fun)))) (let ((thing (car x))) (when (lambda-var-p thing) (frob-leaf thing (cdr x) (= level 3))))) @@ -376,8 +399,8 @@ (frob-lambda let (= level 3))))) (let ((sorted (sort (vars) #'string< - :key #'(lambda (x) - (symbol-name (leaf-name (car x)))))) + :key (lambda (x) + (symbol-name (leaf-debug-name (car x)))))) (prev-name nil) (id 0) (i 0) @@ -386,27 +409,27 @@ (type index id i)) (dolist (x sorted) (let* ((var (car x)) - (name (symbol-name (leaf-name var)))) + (name (symbol-name (leaf-debug-name var)))) (cond ((and prev-name (string= prev-name name)) (incf id)) (t (setq id 0 prev-name name))) - (dump-1-variable fun var (cdr x) id nil buffer) + (dump-1-var fun var (cdr x) id nil buffer) (setf (gethash var var-locs) i)) (incf i)) (coerce buffer 'simple-vector)))) -;;; Return a vector suitable for use as the DEBUG-FUN-VARIABLES of +;;; Return a vector suitable for use as the DEBUG-FUN-VARS of ;;; FUN, representing the arguments to FUN in minimal variable format. -(defun compute-minimal-variables (fun) +(defun compute-minimal-vars (fun) (declare (type clambda fun)) (let ((buffer (make-array 0 :fill-pointer 0 :adjustable t))) (dolist (var (lambda-vars fun)) - (dump-1-variable fun var (leaf-info var) 0 t buffer)) + (dump-1-var fun var (leaf-info var) 0 t buffer)) (coerce buffer 'simple-vector))) -;;; Return Var's relative position in the function's variables (determined -;;; from the Var-Locs hashtable.) If Var is deleted, then return DELETED. +;;; Return VAR's relative position in the function's variables (determined +;;; from the VAR-LOCS hashtable). If VAR is deleted, then return DELETED. (defun debug-location-for (var var-locs) (declare (type lambda-var var) (type hash-table var-locs)) (let ((res (gethash var var-locs))) @@ -418,14 +441,14 @@ ;;;; arguments/returns -;;; Return a vector to be used as the -;;; COMPILED-DEBUG-FUN-ARGUMENTS for Fun. If fun is the -;;; MAIN-ENTRY for an optional dispatch, then look at the ARGLIST to -;;; determine the syntax, otherwise pretend all arguments are fixed. +;;; Return a vector to be used as the COMPILED-DEBUG-FUN-ARGS for FUN. +;;; If FUN is the MAIN-ENTRY for an optional dispatch, then look at +;;; the ARGLIST to determine the syntax, otherwise pretend all +;;; arguments are fixed. ;;; ;;; ### This assumption breaks down in EPs other than the main-entry, ;;; since they may or may not have supplied-p vars, etc. -(defun compute-arguments (fun var-locs) +(defun compute-args (fun var-locs) (declare (type clambda fun) (type hash-table var-locs)) (collect ((res)) (let ((od (lambda-optional-dispatch fun))) @@ -462,8 +485,8 @@ ;;; (Must be known values return...) (defun compute-debug-returns (fun) (coerce-to-smallest-eltype - (mapcar #'(lambda (loc) - (tn-sc-offset loc)) + (mapcar (lambda (loc) + (tn-sc-offset loc)) (return-info-locations (tail-set-info (lambda-tail-set fun)))))) ;;;; debug functions @@ -476,13 +499,7 @@ (main-p (and dispatch (eq fun (optional-dispatch-main-entry dispatch))))) (make-compiled-debug-fun - :name (cond ((leaf-name fun)) - ((let ((ef (functional-entry-function fun))) - (and ef (leaf-name ef)))) - ((and main-p (leaf-name dispatch))) - (t - (component-name - (block-component (node-block (lambda-bind fun)))))) + :name (leaf-debug-name fun) :kind (if main-p nil (functional-kind fun)) :return-pc (tn-sc-offset (ir2-physenv-return-pc 2env)) :old-fp (tn-sc-offset (ir2-physenv-old-fp 2env)) @@ -505,21 +522,23 @@ (let ((od (lambda-optional-dispatch fun))) (or (not od) (not (eq (optional-dispatch-main-entry od) fun))))) - (setf (compiled-debug-fun-variables dfun) - (compute-minimal-variables fun)) + (setf (compiled-debug-fun-vars dfun) + (compute-minimal-vars fun)) (setf (compiled-debug-fun-arguments dfun) :minimal)) (t - (setf (compiled-debug-fun-variables dfun) - (compute-variables fun level var-locs)) + (setf (compiled-debug-fun-vars dfun) + (compute-vars fun level var-locs)) (setf (compiled-debug-fun-arguments dfun) - (compute-arguments fun var-locs)))) + (compute-args fun var-locs)))) - (when (>= level 2) - (multiple-value-bind (blocks tlf-num) (compute-debug-blocks fun var-locs) - (setf (compiled-debug-fun-tlf-number dfun) tlf-num) - (setf (compiled-debug-fun-blocks dfun) blocks))) + (if (>= level 2) + (multiple-value-bind (blocks tlf-num) + (compute-debug-blocks fun var-locs) + (setf (compiled-debug-fun-tlf-number dfun) tlf-num) + (setf (compiled-debug-fun-blocks dfun) blocks)) + (setf (compiled-debug-fun-tlf-number dfun) (find-tlf-number fun))) - (if (external-entry-point-p fun) + (if (xep-p fun) (setf (compiled-debug-fun-returns dfun) :standard) (let ((info (tail-set-info (lambda-tail-set fun)))) (when info @@ -531,107 +550,6 @@ (compute-debug-returns fun))))))) dfun)) -;;;; MINIMAL-DEBUG-FUNs - -;;; Return true if DFUN can be represented as a MINIMAL-DEBUG-FUN. -;;; DFUN is a cons ( . C-D-F). -(defun debug-fun-minimal-p (dfun) - (declare (type cons dfun)) - (let ((dfun (cdr dfun))) - (and (member (compiled-debug-fun-arguments dfun) '(:minimal nil)) - (null (compiled-debug-fun-blocks dfun))))) - -;;; Dump a packed binary representation of a DFUN into *BYTE-BUFFER*. -;;; PREV-START and START are the byte offsets in the code where the -;;; previous function started and where this one starts. -;;; PREV-ELSEWHERE is the previous function's elsewhere PC. -(defun dump-1-minimal-dfun (dfun prev-start start prev-elsewhere) - (declare (type compiled-debug-fun dfun) - (type index prev-start start prev-elsewhere)) - (let* ((name (compiled-debug-fun-name dfun)) - (setf-p (and (consp name) (eq (car name) 'setf) - (consp (cdr name)) (symbolp (cadr name)))) - (base-name (if setf-p (cadr name) name)) - (pkg (when (symbolp base-name) - (symbol-package base-name))) - (name-rep - (cond ((stringp base-name) - minimal-debug-fun-name-component) - ((not pkg) - minimal-debug-fun-name-uninterned) - ((eq pkg (sane-package)) - minimal-debug-fun-name-symbol) - (t - minimal-debug-fun-name-packaged)))) - (aver (or (atom name) setf-p)) - (let ((options 0)) - (setf (ldb minimal-debug-fun-name-style-byte options) name-rep) - (setf (ldb minimal-debug-fun-kind-byte options) - (position-or-lose (compiled-debug-fun-kind dfun) - *minimal-debug-fun-kinds*)) - (setf (ldb minimal-debug-fun-returns-byte options) - (etypecase (compiled-debug-fun-returns dfun) - ((member :standard) minimal-debug-fun-returns-standard) - ((member :fixed) minimal-debug-fun-returns-fixed) - (vector minimal-debug-fun-returns-specified))) - (vector-push-extend options *byte-buffer*)) - - (let ((flags 0)) - (when setf-p - (setq flags (logior flags minimal-debug-fun-setf-bit))) - (when (compiled-debug-fun-nfp dfun) - (setq flags (logior flags minimal-debug-fun-nfp-bit))) - (when (compiled-debug-fun-variables dfun) - (setq flags (logior flags minimal-debug-fun-variables-bit))) - (vector-push-extend flags *byte-buffer*)) - - (when (eql name-rep minimal-debug-fun-name-packaged) - (write-var-string (package-name pkg) *byte-buffer*)) - (unless (stringp base-name) - (write-var-string (symbol-name base-name) *byte-buffer*)) - - (let ((vars (compiled-debug-fun-variables dfun))) - (when vars - (let ((len (length vars))) - (write-var-integer len *byte-buffer*) - (dotimes (i len) - (vector-push-extend (aref vars i) *byte-buffer*))))) - - (let ((returns (compiled-debug-fun-returns dfun))) - (when (vectorp returns) - (let ((len (length returns))) - (write-var-integer len *byte-buffer*) - (dotimes (i len) - (write-var-integer (aref returns i) *byte-buffer*))))) - - (write-var-integer (compiled-debug-fun-return-pc dfun) - *byte-buffer*) - (write-var-integer (compiled-debug-fun-old-fp dfun) - *byte-buffer*) - (when (compiled-debug-fun-nfp dfun) - (write-var-integer (compiled-debug-fun-nfp dfun) - *byte-buffer*)) - (write-var-integer (- start prev-start) *byte-buffer*) - (write-var-integer (- (compiled-debug-fun-start-pc dfun) start) - *byte-buffer*) - (write-var-integer (- (compiled-debug-fun-elsewhere-pc dfun) - prev-elsewhere) - *byte-buffer*))) - -;;; Return a byte-vector holding all the debug functions for a -;;; component in the packed binary MINIMAL-DEBUG-FUN format. -(defun compute-minimal-debug-funs (dfuns) - (declare (list dfuns)) - (setf (fill-pointer *byte-buffer*) 0) - (let ((prev-start 0) - (prev-elsewhere 0)) - (dolist (dfun dfuns) - (let ((start (car dfun)) - (elsewhere (compiled-debug-fun-elsewhere-pc (cdr dfun)))) - (dump-1-minimal-dfun (cdr dfun) prev-start start prev-elsewhere) - (setq prev-start start prev-elsewhere elsewhere)))) - (copy-seq *byte-buffer*)) - ;;;; full component dumping ;;; Compute the full form (simple-vector) function map. @@ -653,39 +571,30 @@ ;;; called after assembly so that source map information is available. (defun debug-info-for-component (component) (declare (type component component)) - (collect ((dfuns)) - (let ((var-locs (make-hash-table :test 'eq)) - ;; FIXME: What is *BYTE-BUFFER* for? Has it become dead code - ;; now that we no longer use MINIMAL-DEBUG-FUN - ;; representation? - (*byte-buffer* (make-array 10 - :element-type '(unsigned-byte 8) - :fill-pointer 0 - :adjustable t))) - (dolist (fun (component-lambdas component)) - (clrhash var-locs) - (dfuns (cons (label-position - (block-label (node-block (lambda-bind fun)))) - (compute-1-debug-fun fun var-locs)))) - (let* ((sorted (sort (dfuns) #'< :key #'car)) - ;; FIXME: CMU CL had - ;; (IF (EVERY #'DEBUG-FUN-MINIMAL-P SORTED) - ;; (COMPUTE-MINIMAL-DEBUG-FUNS SORTED) - ;; (COMPUTE-DEBUG-FUN-MAP SORTED)) - ;; here. We've gotten rid of the MINIMAL-DEBUG-FUN - ;; case in SBCL because the minimal representation - ;; couldn't be made to transform properly under package - ;; renaming. Now that that case is gone, a lot of code is - ;; dead, and once everything is known to work, the dead - ;; code should be deleted. - (function-map (compute-debug-fun-map sorted))) - (make-compiled-debug-info :name (component-name component) - :function-map function-map))))) + (let ((dfuns nil) + (var-locs (make-hash-table :test 'eq)) + (*byte-buffer* (make-array 10 + :element-type '(unsigned-byte 8) + :fill-pointer 0 + :adjustable t))) + (dolist (lambda (component-lambdas component)) + (clrhash var-locs) + (push (cons (label-position (block-label (lambda-block lambda))) + (compute-1-debug-fun lambda var-locs)) + dfuns)) + (let* ((sorted (sort dfuns #'< :key #'car)) + (fun-map (compute-debug-fun-map sorted))) + (make-compiled-debug-info :name (component-name component) + :fun-map fun-map)))) ;;; Write BITS out to BYTE-BUFFER in backend byte order. The length of ;;; BITS must be evenly divisible by eight. (defun write-packed-bit-vector (bits byte-buffer) (declare (type simple-bit-vector bits) (type byte-buffer byte-buffer)) + + ;; Enforce constraint from CMU-CL-era comment. + (aver (zerop (mod (length bits) 8))) + (multiple-value-bind (initial step done) (ecase *backend-byte-order* (:little-endian (values 0 1 8))