;-*- cold-load:t; Mode:Common-Lisp; Package:SYSTEM-INTERNALS; Base:10; Fonts:(CPTFONT CPTFONTB) -*- 1;;; RESTRICTED RIGHTS LEGEND ;;;Use, duplication, or disclosure by the Government is subject to ;;;restrictions as set forth in subdivision (c)(1)(ii) of the Rights in ;;;Technical Data and Computer Software clause at 52.227-7013. ;;; ;;; TEXAS INSTRUMENTS INCORPORATED. ;;; P.O. BOX 2909 ;;; AUSTIN, TEXAS 78769 ;;; MS 2151 ;;;* ;1;; Copyright (C) 1986-1989 Texas Instruments Incorporated. All rights reserved.* 1;;; THE DEBUG-INFO-STRUCT ;;; FOR EACH fef, there is a structure DEBUG-INFO-STRUCT which contains additional ;;; information regarding the fef. The information includes the following: ;;; :NAME - the name of the compiled function ;;; :ARGLIST - the function's argument list as typed by its author ;;; :INTERPRETED-DEFINITION - if the function defines a SUBST or is proclaimed ;;; INLINE, this stores the interpreted definition for subsequent inline expansions. ;;; :LOCAL-MAP - describes the layout of local variables used by the function, i.e., ;;; it indicates how local variables are assigned to slots in the function's local ;;; block. The n'th element of the map is the local that lives there. ;;; :PLIST - a plist for other information not needed in a time-critical fashion. ;;; The plist will often contain some of the following: ;;; :MACROS-EXPANDED - a list of macros which were expanded when the function ;;; was compiled. ;;; :DOCUMENTATION - the function's documentation string ;;; :DESCRIPTIVE-ARGLIST - the argument list for the function as defined by ;;; (declare (arglist...)) ;;; As this arglist need not have anything to do with reality, it is not used by ;;; the compiler or the interpreter. ;;; :VALUES - the return-list of values as defined by (DECLARE (VALUES...)) ;;; :INTERNAL-FEF-OFFSETS -- describes the addresses within the fef of the function ;;; cells for internal functions of the fef. ;;; :INTERNAL-FEF-NAMES -- a list of the names of the internal functions of the fef. ;;; :FUNCTION-PARENT ;;; gives the name of a definition whose source code includes this function. This) ;;; is for functions defined automatically generated by Defstruct, Defflavor, etc. ;;; *SYS:1ENCAPSULATED-DEFINITION ;;; This means that this function was made to encapsulate an inner definition. ;;; *SYS:1RENAMINGS ;;; This item is used together with (encapsulated-definition ... :rename-within) ;;; and specifies what renamings are to be done to the original definition. Each ;;; element of the alist has the form ( ). ;;; :SELF-FLAVOR ;;; It is a good idea to view a DEBUG-INFO-STRUCT as an plist. That it is not a plist is ;;; due to the fact certain utilities, such as the Error Handler, Compiler and the Interpreter ;;; need to access some fields in a time-critical manner and a plist search can be expensive. ;;; ;;; NOTE *MOST1 FIELDS ARE *DENOTED1 BY KEYWORDS.* (proclaim '(inline DEBUG-INFO-STRUCT-P)) ; work-around SPR 7434 -- DNG 4/19/89 (Defstruct (DEBUG-INFO-STRUCT :NAMED-ARRAY (:CONSTRUCTOR INTERNAL-MAKE-DEBUG-STRUCT) (:CALLABLE-CONSTRUCTORS nil) (:COPIER nil) (:PRINT-FUNCTION (LAMBDA (dbi stream depth) (DECLARE (ignore depth)) (SI:PRINTING-RANDOM-OBJECT (dbi stream) (PRINC "Debug-Info " stream) (PRIN1 (DBIS-NAME dbi) stream)))) (:PREDICATE DEBUG-INFO-STRUCT-P) (:CONC-NAME dbis-)) NAME ARGLIST INTERPRETED-DEFINITION LOCAL-MAP PLIST) 1;;; MAKING a DEBUG-INFO-STRUCT ;;; The following procedure is used to create a debug-struct . See also PUT-DEBUG-INFO-FIELD below.* (PROCLAIM '(SPECIAL *KEYWORD-PACKAGE*)) (Defun MAKE-DEBUG-INFO-STRUCT(&REST properties-and-values) (LET* ((sys:%inhibit-read-only t) (dbi (INTERNAL-MAKE-DEBUG-STRUCT))) (UNLESS (EVENP (LENGTH properties-and-values)) (FERROR nil "the list of properties and values has odd length ~d" (LENGTH properties-and-values))) (DO ((rest properties-and-values (CDDR rest)) key-field) ((ATOM rest) dbi) (CASE (SETQ key-field (CAR rest)) (:name (SETF (DBIS-NAME dbi) (CADR rest))) (:arglist (WHEN (MEMBER '"e (CADR rest) :test #'eq) (SETF (GETF (DBIS-PLIST dbi) :quote-degree) (COMPUTE-QUOTE-DEGREE (CADR rest)))) (SETF (DBIS-ARGLIST dbi) (CADR rest))) (:interpreted-definition (SETF (DBIS-INTERPRETED-DEFINITION dbi) (CADR rest))) (:local-map (SETF (DBIS-LOCAL-MAP dbi) (CADR rest))) (:plist (SETF (DBIS-PLIST dbi) (CADR rest))) ;; this can screw anything done in the following line (t (SETF (GETF (DBIS-PLIST dbi) key-field) (CADR rest))))))) ;;; EXTRACTING data from a DEBUG-INFO-STRUCT 1;;; ;;; GET-DEBUG-INFO-STRUCT is the function used to extract a field from a debug-info-structure. ;;; Except for the Compiler,the Interpreter and the Error handler, this function should be used ;;; if upward compatibility with future releases is desired. ;;; Examples: (let denote a debug-info-struct) ;;; 1) to extract the argument list, use ;;; (get-debug-info-field :arglist) ;;; 2) to extract the documentation, use ;;; (get-debug-info-field :documentation)* ;;PHD 4/2/87 Fixed get-debug-info-field default arg was missing from the last call to getf. (Defun GET-DEBUG-INFO-FIELD (dbi field &optional default) (COND ((LISTP dbi) ;; takes care of interpreted debug plists (contained in named-lambda ) (GETF dbi field default)) ((DEBUG-INFO-STRUCT-P dbi) (CASE field (:name (DBIS-NAME dbi)) (:arglist (DBIS-ARGLIST dbi)) (:interpreted-definition (DBIS-INTERPRETED-DEFINITION dbi)) (:local-map (DBIS-LOCAL-MAP dbi)) (:plist (DBIS-PLIST dbi)) (t (GETF (DBIS-PLIST dbi) field default)))) (t (FERROR nil "~s is not a DEBUG-INFO-STRUCT" dbi)))) 1;;; PLACING data into a DEBUG-INFO-STRUCT ;;; ;;; PUT-DEBUG-INFO-FIELD is the function used to insert data into a debug-info field. Use of this ;;; function by anyone other than the Compiler is unwise. ;;; Examples: (let denote a debug-info-struct) ;;; 1) to put local-map into the structure, the following calls suffice ;;; (PUT-DEBUG-INFO-FIELD :local-map )* ;1;; better: (setf (get-debug-info-field :local-map) ) ;;; Note: any field other than those described in the structure definition are placed on the plist ;;; and the property name, e.g. internal-fef-offset, ought be a keyword.* (Defun PUT-DEBUG-INFO-FIELD (dbi field value) (COND ((DEBUG-INFO-STRUCT-P dbi) (CASE field (:name (SETF (DBIS-NAME dbi) value))1 ;; maybe this should be an error* (:arglist (WHEN (MEMBER '"e value :test #'eq) (SETF (GETF (DBIS-PLIST dbi) :quote-degree) (COMPUTE-QUOTE-DEGREE value))) (SETF (DBIS-ARGLIST dbi) value)) (:interpreted-definition (SETF (DBIS-INTERPRETED-DEFINITION dbi) value)) (:local-map (SETF (DBIS-LOCAL-MAP dbi) value)) (:plist (SETF (DBIS-PLIST dbi) value))1 ;;; this sets the entire plist to * (t (SETF (GETF (DBIS-PLIST dbi) field) value)))) ((CONSP dbi) (SETF (GETF dbi field) value)) (t (FERROR nil "~s is not a DEBUG-INFO-STRUCT" dbi)))) (Defsetf GET-DEBUG-INFO-FIELD (dbi field) (value)`(PUT-DEBUG-INFO-FIELD ,dbi ,field ,value)) 1;;; the following are procedures used to access the explicit fields of a debug-info-structure. ;;; they ASSUME their argument is a debug-info-struct. Please do not clutter them up by inserting ;;; type-checking. They are meant for the Compiler and the Interpreter. Other users should appeal ;;; to GET-DEBUG-INFO-FIELD. They are currently DEFUNS -- until the structure is well-defined and ;;; not the subject of experimentation.* (Defsubst DBI-NAME (dbi) (DBIS-NAME dbi)) (Defsubst DBI-ARGLIST (dbi) (DBIS-ARGLIST dbi)) (Defsubst DBI-LOCAL-MAP (dbi) (DBIS-LOCAL-MAP dbi)) (Defsubst DBI-INTERPRETED-DEFINITION (dbi) (DBIS-INTERPRETED-DEFINITION dbi)) (Defsubst DBI-PLIST (dbi) (DBIS-PLIST dbi)) ;;; GETTING THE DEBUG-INFO-STRUCT pointer from the fef. (Defsubst EXTRACT-DEBUG-INFO-STRUCT-FROM-FEF (FEF) (AND (TYPEP FEF 'COMPILED-FUNCTION) (%P-CONTENTS-OFFSET FEF %FEF-DEBUGGING-INFO-WORD))) ;;AB 7/30/87. Make sure we don't go past the active part of the micro-code-entry-debug-info-area. [SPR 6133] ;;RJF 8/20/87 Changed 7/30/87 fix to use array-total-size instead of length since Genasys leaves ;; the wrong fill pointer in the array. (Defsubst EXTRACT-DEBUG-INFO-STRUCT-FROM-UCODE (uentry) (AND (TYPEP uentry 'microcode-function) (< (%POINTER uentry) (Array-Total-Size #'MICRO-CODE-ENTRY-DEBUG-INFO-AREA)) (AREF #'MICRO-CODE-ENTRY-DEBUG-INFO-AREA (%POINTER uentry)))) 1;;; GETTING THE DEBUG-INFO-STRUCT from an arbitrary function object. ;;; The following function is a replacement for DEBUGGING-INFO which is obsolete. Given a function spec or ;;; a function object, this moves through symbols, DEFF'S, CLOSURE's , FEF's and interpreted-functions to ;;; find and return the DEBUG-INFO-STRUCT. By turning the optional argument on, i.e. non-nil, ;;; this procedure will even find the DEBUG-INFO-STRUCT of an encapsulated function. ;;; Warning: certain named-lambdas may have DEBUG-INFO associated with them. This, however, will be an ALIST.* ;;PAD 1/20/87 Also handle closure-named-lambda ;;PHD added support for unencapsulated argument on interpreted functions. ;;03/16/89 clm - Integrated CLOS changes into Kernel. (Defun GET-DEBUG-INFO-STRUCT (function-object &OPTIONAL unencapsulated) (TYPECASE function-object (SYMBOL (GET-DEBUG-INFO-STRUCT (if unencapsulated (unencapsulate-function-spec function-object) (SYMBOL-FUNCTION function-object)))) (COMPILED-FUNCTION (let* ((struct(EXTRACT-DEBUG-INFO-STRUCT-FROM-FEF function-object)) (info (and unencapsulated (get-debug-info-field struct 'encapsulated-definition)))) (if info (GET-DEBUG-INFO-STRUCT (car info) unencapsulated ) struct))) (MICROCODE-FUNCTION (EXTRACT-DEBUG-INFO-STRUCT-FROM-UCODE function-object)) (CLOSURE (GET-DEBUG-INFO-STRUCT (CLOSURE-FUNCTION function-object))) (LIST ;; handle macros and named-lambdas and named-substs ;; Note: a named-lambda can have a debug-info ALIST and will have the form ;; (named-lambda (foo . debugging-info) (x y z..) "doc-string" . body) ;; for instance, encapsulations made by TRACE, are defined this way. (COND ((EQ (CAR function-object) 'MACRO) (GET-DEBUG-INFO-STRUCT (CDR function-object) unencapsulated)) ;; tail-recursive call ((MEMBER (CAR function-object) '(NAMED-LAMBDA NAMED-SUBST closure-named-lambda GLOBAL:NAMED-LAMBDA GLOBAL:NAMED-SUBST) :TEST #'EQ) (and (CONSP (CADR function-object)) (let* ((struct (CADADR function-object)) (info (and unencapsulated (get-debug-info-field struct 'encapsulated-definition)))) (if info (GET-DEBUG-INFO-STRUCT (car info) unencapsulated ) struct)))) ((MEMBER (CAR function-object) '(LAMBDA SUBST ZLC:LAMBDA ZLC:SUBST) :TEST #'EQ) nil) (t (GET-DEBUG-INFO-STRUCT (fdefinition (if unencapsulated (unencapsulate-function-spec function-object) function-object)) nil)))) (T nil))) ;;; the two procedures below check bits in the fef-header of a compiled function (Defsubst COMPILED-SPECIAL-FORM? (fef) (AND (TYPEP fef 'compiled-function) (PLUSP (%P-LDB %%FEF-HEADER-Special-Form fef)))) (Defsubst COMPILED-SUBST? (fef) (AND (TYPEP fef 'compiled-function) (PLUSP (%P-LDB %%FEF-HEADER-Subst fef)))) (Defun COMPUTE-QUOTE-DEGREE (arglist) ;;; evaluation of a "special form" usually rests of interpreting each of its formal arguments ;;; to determine which are to be evalauted and which are quoted. This process can be made more ;;; efficient by recognizing that "most" special forms either take a single (quoted) &rest argument ;;; or at least quote all of their arguments. The following procedure computes a "quote-degree" ;;; for a special form and is called whenever the formal argument list contains "e. The quote-degree ;;; is defined as follows: ;;; -1 -- if some arguments are to be evaluated and some quoted ;;; 0 -- a quoted &rest argument or all quoted arguments ;;; This is made the :quote-degree property stored on the debug-info-struct's plist for the function. ;;; See *eval. (IF (MEMBER '&eval arglist :test #'eq) -1 (DO ((rst arglist (CDR rst)) (quote-seen nil) (rest-seen nil)) ((ENDP rst) -1) ;; if we exit here, then there is a malformed lambda list (IF (MEMBER (CAR rst) lambda-list-keywords :test #'eq) (COND ((EQ (CAR rst) '"e) (SETQ quote-seen t)) ((EQ (CAR rst) '&rest) (SETQ rest-seen t))) ;; else return since (CAR rst) is a formal parameter (RETURN (COND ((AND rest-seen quote-seen) 0) (quote-seen 0) (t -1))))))) ;; DNG 3/12/87 Declare POSITION arg to be a LIST for efficiency. (Defun ALL-ARGLIST-BEFORE-&AUX (arglist) ;; return a copy of the arglist up to but excluding &aux (LET ((pos (POSITION '&aux (the list arglist) ))) (IF pos (FIRSTN pos arglist) arglist))) ;;PAD 2/10/87 If not real-flag try to get descriptive arglist for interpreted function ;; Second value for a macro returns a list ;;PHD-PAD 3/21/87 use default value to return null descriptive arglists. ;;DNG 4/19/89 Accept NIL as a valid value for the ARGLIST symbol property. ;; This is needed for things like %POP and NEXT-METHOD-P. [SPR 8644] (Defun ARGLIST (function &OPTIONAL real-flag) "-Return the argument list of , and its value-list. - may be a function object or a function spec. -If is not nil, then the actual argument list is returned. Otherwise, if there was an explicit (DECLARE (ARGLIST ...)) in the defintiion of , then this list will be returned. -The second value returned is the value-list, useful only as documentation. -The third value is NIL, SUBST or MACRO." (DECLARE (VALUES ARGLIST VALUES TYPE)) (eTYPECASE function (symbol (IF (FBOUNDP function) (ARGLIST (fdefinition (unencapsulate-function-spec function)) real-flag) (LET ((arglist-property (GET function 'arglist ':default))) ;; for things like %call,%push, etc. (IF (listp arglist-property) arglist-property (FERROR NIL "~S is neither a function nor a function spec" function))))) (compiled-function (LET ((debug-info (GET-DEBUG-INFO-STRUCT function))) (IF real-flag (VALUES (GET-DEBUG-INFO-FIELD debug-info :ARGLIST) ; first value -- the argument list ()) ; second value - the return-list nil (values ;;arglist connot be a non null symbol so it is safe to use a symbol as ;;an empty marker. (let ((val (GET-DEBUG-INFO-FIELD debug-info :DESCRIPTIVE-ARGLIST 'empty))) (if (eq 'empty val) (GET-DEBUG-INFO-FIELD debug-info :ARGLIST) val)) (GET-DEBUG-INFO-FIELD debug-info :VALUES))))) ;; second value - the return-list (cons (CASE (CAR function) ((CLI:LAMBDA GLOBAL:LAMBDA) (ALL-ARGLIST-BEFORE-&AUX (CADR function))) ((CLI:SUBST GLOBAL:SUBST) (VALUES (CADR function) NIL 'SUBST)) ((NAMED-SUBST NAMED-LAMBDA CLOSURE-NAMED-LAMBDA GLOBAL:NAMED-SUBST GLOBAL:NAMED-LAMBDA) (LET ((debug-info (GET-DEBUG-INFO-STRUCT function))) ;; this is meaningful for encapsulations ;; remember here that debug-info for interpreted functions is a list (IF real-flag (values (ALL-ARGLIST-BEFORE-&AUX (CADDR function)) ()) (values (let ((val (GET-DEBUG-INFO-FIELD debug-info :DESCRIPTIVE-ARGLIST 'empty))) (if (eq 'empty val) (let ((val (getf debug-info :ARGLIST 'empty))) (if (eq 'empty val) (ALL-ARGLIST-BEFORE-&AUX (CADDR function)) val)) val)) (getf debug-info :VALUES))))) (MACRO (LET ((macro-function (CDR function))) (multiple-value-bind (argl values) (ARGLIST macro-function real-flag) (values argl values 'macro)))) (T (IF (VALIDATE-FUNCTION-SPEC function) (ARGLIST (FDEFINITION (unencapsulate-function-spec function)) real-flag) (FERROR NIL "~S not a recognized function" function))) )) (stack-group '(STACK-GROUP-ARG)) (array (DO ((I (%P-LDB %%ARRAY-NUMBER-DIMENSIONS function) (1- I)) (L NIL)) ((<= I 0) L) (SETQ L (CONS (INTERN (FORMAT NIL "DIM-~D" I) PKG-SYSTEM-INTERNALS-PACKAGE) L)))) ((OR closure lexical-closure) (ARGLIST (CLOSURE-FUNCTION function) real-flag)) (instance '(OP &REST METHOD-ARGS-VARY)) ;; Can't tell arglist, shouldn't give error though (microcode-function (GET-DEBUG-INFO-FIELD (EXTRACT-DEBUG-INFO-STRUCT-FROM-UCODE function) :ARGLIST)))) ;; 7/10/87 DNG - Fixed for named-structures [SPR 5238], instances and stack-groups. [SPR 5469] (Defun ARGS-DESC (function-object) 1 "given a function spec or object, this procedure returns five values: 1) the minimum number of args expected by the function 2) the maximum number of args expected by the function 3) a flag indicating the presence or absence of a rest arg 4) a flag indicating the presence or absence of quoted arguments *51) the call type of the function"* (DECLARE (VALUES MINIMUM-ARGS MAXIMUM-ARGS REST-ARG-FLAG QUOTED-ARG-FLAG CALL-TYPE)) (eTYPECASE function-object (SYMBOL (ARGS-DESC (SYMBOL-FUNCTION function-object))) (COMPILED-FUNCTION ;1; get the information from the fef header* 1(SETQ function-object (FOLLOW-STRUCTURE-FORWARDING function-object))* (LET ((call-type (%P-LDB %%FEF-HEADER-CALL-TYPE function-object))) (IF (= call-type SI:%FEF-CALL-LONG) (LET ((args-info-word (%P-CONTENTS-OFFSET function-object %FEF-FIRST-OPTIONAL-WORD))) (VALUES (LDB %%FEF-LONG-ARGS-MIN-ARGS args-info-word) (LDB %%FEF-LONG-ARGS-MAX-ARGS args-info-word) (NOT (ZEROP (LDB %%FEF-LONG-ARGS-REST-ARG args-info-word))) (PLUSP (%P-LDB %%FEF-HEADER-Special-Form function-object)) call-type)) (LET ((nargs (%P-LDB %%FEF-HEADER-NUMBER-ARGS function-object))) (VALUES nargs (+ nargs (%P-LDB %%FEF-HEADER-NUMBER-OPTIONAL-ARGS function-object)) (OR (= call-type SI:%FEF-CALL-REST) (= call-type SI:%FEF-CALL-OPTIONALS-AND-REST)) (PLUSP (%P-LDB %%FEF-HEADER-Special-Form function-object)) call-type))))) (MICROCODE-FUNCTION ;1; get the information by hacking the lambda list* (ARGS-DESC-USING-LAMBDA-LIST (GET-DEBUG-INFO-FIELD (GET-DEBUG-INFO-STRUCT function-object) :ARGLIST))) (LIST ;1; get the information by hacking the lambda list* (CASE (CAR function-object) (MACRO (ARGS-DESC (CDR function-object))) ((NAMED-LAMBDA NAMED-SUBST CLOSURE-NAMED-LAMBDA GLOBAL:NAMED-LAMBDA GLOBAL:NAMED-SUBST) (ARGS-DESC-USING-LAMBDA-LIST (THIRD function-object))) ((CLI:LAMBDA GLOBAL:LAMBDA) (ARGS-DESC-USING-LAMBDA-LIST (SECOND function-object))) (T (FERROR t "2invalid list ~s supplied to args-desc"* function-object)))) ((OR CLOSURE LEXICAL-CLOSURE) (ARGS-DESC (CLOSURE-FUNCTION function-object))) (ARRAY (IF (NAMED-STRUCTURE-P function-object) (VALUES 1 1 T NIL SI:%FEF-CALL-LONG) (LET ((n (ARRAY-RANK function-object))) (VALUES n n nil nil SI:%FEF-CALL-LONG)))) (INSTANCE (VALUES 1 1 T NIL SI:%FEF-CALL-LONG)) (STACK-GROUP (VALUES 1 1 NIL NIL SI:%FEF-CALL-LONG)) )) (Defun ARGS-DESC-USING-LAMBDA-LIST (lamlist) (LET ((nmin 0) (nmax 0) rest-arg quoting optional-arg) (DOLIST (x lamlist) (CASE x (&OPTIONAL (SETQ nmax nmin optional-arg t)) (&AUX (RETURN)) ("E (SETQ quoting t)) ((&KEY &REST) (SETQ rest-arg t) (RETURN)) (T (UNLESS (OR (MEMBER x LAMBDA-LIST-KEYWORDS :test #'eq) rest-arg) (IF optional-arg (INCF nmax) (INCF nmin)))))) (VALUES nmin (MAX nmax nmin) rest-arg quoting SI:%FEF-CALL-LONG)))