| Allegro CL version 10.0 New since the initial 10.0 release. |
Arguments: function &optional reachable (ordering t)trace
Source level debug info is propagated from the source all the way through the compilation of a function, and depending on the compexity of the function this information can become garbled along the way, due to reorderings, optimizations, implementation strategies, or simply high function complexity.
This function returns the number of problems seen after analyzing the source-level-debug info for function. If trace is given and true, progress will be printed verbosely whenever searching for a path from one program counter in the function to another. Program counters are always relative to the start of the function, beginning with 0. Function can be a function or closure object, or it can be any fboundp function spec.
The current validation styles available currently
are reachable
and ordering. Note
that ordering defaults to true,
and reachable defaults
to nil
. It is much more likely that a
function will have problems with reachablity than with ordering, so a
quick test for gross errors would be something like
(validate-lisp-source 'foo)
If you want to validate only reachable problems, use
(validate-lisp-source 'foo t nil)
and if you want all validations, use
(validate-lisp-source 'foo t)
validate-lisp-source is
highly compute-intensive. You can demonstrate this by calling with
the trace argument
non-nil
.
A Lisp source record is identified by its index, and it contains a number of fields which are important to validation and which can be seen by using print-function-meta-info:
nil
in this field
means that there is no special consideration for this record. A
non-exhaustive list of entry-types is:
:ref
- A variable is being referenced.
:call
- A call to a function is about to occur;
arguments have already been placed.
:early
- A call to a function is being considered,
but arguments have not yet been placed.
:clone
- assembler code has split off into two or
more branches in implementing this form, and this record is a copy of
a previous record.
:init
- This record represents the storing of an
initialization form into a variable being bound by a let form.
:setq
- A variable is about to be setq'd.
:bcc
- Branch on Condition Code: A decision will be
made whether to branch or not. A next and branch field will always be
present.
:jmp
- branch unconditionally: Usually the
branch/branch-pc fields will point to the target record/pc, and there
will be no next/next-pc fields.
:call
- A call to a function. The function is
determined by what is in the function name register, and a decision
about whether to break at the beginning of that function is determined
by the step type. The next fields will be filled in with the next
record after the call, unless it is a tail-call.
:ret
- This record is a return record; there are no
next or branch fields.
:case
- This record represents a table-calculated
jump, which may have next fields but always has multiple branch
fields.
:noreturn
- This record represents dead code, which
will not be returned to (e.g. by a tail call).
The current validations are:
Condsider the following scenario with a function #'bas on some imaginary architecture:
Record: 23 ... next: 24 ... pc: 120 next-pc: 95 form: (foo x) Record: 24 ... next: 25 ... pc: 95 ... form: (bar (foo x))
Record 23 has been placed after record 24, so it has a higher pc value.
If we intersperse source and assembler records (a truncated version of
what (print-function-meta-info 'bas :mixed t)
would
print), then we might have something like this:
Record 24: pc: 95 ... form: (bar (foo x)) 95: call bar 98: ... Record 10: pc: 112 ... form: (/ z 0) 112: load r1, z-in-memory 117: jmp 128 Record 23: pc: 120 ... form: (foo x) 120: call foo 125: jmp 95 128: div 0 133: ... Record 40...
If for some reason (such as a divide by 0) an error occurs at the instruction at 128, then the :zoom command would look at the pc at 128 and (incorrectly) associated it with record 23, instead of associating it with record 10 as it should. This is because the segment of code between 128 and 133 is not assocated with the source record it should be, and thus the instructions ar 128 and 133 are "not reachable" by record 23. Note the jump at 125 which is a good indicator of such a problem - a jump instruction without a source record immediately following will always result in a reachable failure.
The message in the example situation above will be
Record 23 at pc: 120: (foo x) pc 133 doesn't follow record.
Copyright (c) 1998-2019, Franz Inc. Oakland, CA., USA. All rights reserved.
This page is new in the 10.0 release.
Created 2019.8.20.
| Allegro CL version 10.0 New since the initial 10.0 release. |