mirror of
git://git.code.sf.net/p/sbcl/sbcl
synced 2026-09-10 07:26:40 -04:00
1015 lines
36 KiB
Plaintext
1015 lines
36 KiB
Plaintext
@c Generated by the sb-manual contrib. Do not edit.
|
|
|
|
@node compiler
|
|
@chapter Compiler
|
|
|
|
@menu
|
|
* Diagnostic Messages: diagnostic messages.
|
|
* Handling of Types: handling of types.
|
|
* Compiler Policy: compiler policy.
|
|
* Compiler Errors: compiler errors.
|
|
* Open Coding and Inline Expansion: open coding and inline expansion.
|
|
* Interpreter: interpreter.
|
|
* Advanced Compiler Use and Efficiency Hints: advanced compiler use and efficiency hints.
|
|
@end menu
|
|
|
|
This chapter will discuss most compiler issues other than efficiency,
|
|
including compiler error messages, the SBCL compiler's unusual
|
|
approach to type safety in the presence of type declarations, the
|
|
effects of various compiler optimization policies, and the way that
|
|
inlining and open coding may cause optimized code to differ from a
|
|
naive translation. Efficiency issues are sufficiently varied and
|
|
separate that they have their own chapter, @ref{efficiency}.
|
|
|
|
@node diagnostic messages
|
|
@cindex compiler messsage
|
|
@cindex messsage, compiler
|
|
@section Diagnostic Messages
|
|
|
|
@menu
|
|
* Controlling Verbosity: controlling verbosity.
|
|
* Diagnostic Severity: diagnostic severity.
|
|
* Understanding Compiler Diagnostics: understanding compiler diagnostics.
|
|
@end menu
|
|
|
|
@node controlling verbosity
|
|
@cindex compiler messsage verbosity
|
|
@cindex verbosity of compiler messsages
|
|
@subsection Controlling Verbosity
|
|
|
|
The compiler can be quite verbose in its diagnostic reporting, rather
|
|
more then some users would prefer -- the amount of noise emitted can
|
|
be controlled, however.
|
|
|
|
To control emission of compiler diagnostics (of any severity other
|
|
than @code{error}: @ref{diagnostic severity}) use the @code{sb-ext:muffle-conditions}
|
|
and @code{sb-ext:unmuffle-conditions} declarations, specifying the type of
|
|
condition that is to be muffled (the muffling is done using an
|
|
associated @code{muffle-warning} restart).
|
|
|
|
Global control:
|
|
|
|
@example
|
|
;;; Muffle compiler-notes globally
|
|
(declaim (sb-ext:muffle-conditions sb-ext:compiler-note))
|
|
@end example
|
|
|
|
Local control:
|
|
|
|
@example
|
|
;;; Muffle compiler-notes based on lexical scope
|
|
(defun foo (x)
|
|
(declare (optimize speed) (fixnum x)
|
|
(sb-ext:muffle-conditions sb-ext:compiler-note))
|
|
(values (* x 5) ; no compiler note from this
|
|
(locally
|
|
(declare (sb-ext:unmuffle-conditions sb-ext:compiler-note))
|
|
;; this one gives a compiler note
|
|
(* x -5))))
|
|
@end example
|
|
|
|
@anchor{Declaration sb-ext muffle-conditions}
|
|
@ddindex @sortas{muffle-conditions sb-ext} muffle-conditions [sb-ext]
|
|
@deffn{Declaration} sb-ext:muffle-conditions
|
|
Syntax: @code{(sb-ext:muffle-conditions &rest types)}.
|
|
|
|
Muffle the diagnostic messages that would be caused by compile-time
|
|
signals of @code{types}.
|
|
@end deffn
|
|
@anchor{Declaration sb-ext unmuffle-conditions}
|
|
@ddindex @sortas{unmuffle-conditions sb-ext} unmuffle-conditions [sb-ext]
|
|
@deffn{Declaration} sb-ext:unmuffle-conditions
|
|
Syntax: @code{(sb-ext:muffle-conditions &rest types)}.
|
|
|
|
Cancel the effect of a previous @code{sb-ext:muffle-conditions} declaration.
|
|
@end deffn
|
|
Various details of @emph{how} the compiler messages are printed can be
|
|
controlled via the alist @code{sb-ext:*compiler-print-variable-alist*}.
|
|
|
|
@anchor{Variable sb-ext *compiler-print-variable-alist*}
|
|
@vvindex @sortas{compiler-print-variable-alist* sb-ext} *compiler-print-variable-alist* [sb-ext]
|
|
@deffn{Variable} sb-ext:*compiler-print-variable-alist*
|
|
An association list describing new bindings for special variables
|
|
to be used by the compiler for error-reporting, etc.
|
|
E.g. ((@code{*print-length*} . 10) (@code{*print-level*} . 6) (@code{*print-pretty*} .
|
|
@code{nil})).
|
|
|
|
The variables in the @code{car} positions are bound to the values in the @code{cdr}
|
|
during the execution of some debug commands. When evaluating arbitrary
|
|
expressions in the debugger, the normal values of the printer control
|
|
variables are in effect.
|
|
|
|
Initially empty, @code{*compiler-print-variable-alist*} is typically used
|
|
to specify bindings for printer control variables.
|
|
@end deffn
|
|
For information about muffling warnings signaled outside of the
|
|
compiler, see @ref{customization hooks for users}.
|
|
|
|
@node diagnostic severity
|
|
@cindex compiler message severity
|
|
@cindex severity of compiler message
|
|
@subsection Diagnostic Severity
|
|
|
|
There are four levels of compiler diagnostic severity:
|
|
|
|
@itemize
|
|
@item error
|
|
@item warning
|
|
@item style warning
|
|
@item note
|
|
@end itemize
|
|
|
|
The first three levels correspond to condition classes which are
|
|
defined in the ANSI standard for Common Lisp and which have special
|
|
significance to the @code{compile} and @code{compile-file} functions. These levels
|
|
of compiler error severity occur when the compiler handles
|
|
conditions of these classes.
|
|
|
|
The fourth level of compiler error severity, @emph{note}, corresponds to
|
|
the @code{sb-ext:compiler-note}, and is used for problems which are too
|
|
mild for the standard condition classes, typically hints about how
|
|
efficiency might be improved. The @code{sb-ext:code-deletion-note}, a
|
|
subtype of @code{sb-ext:compiler-note}, is signalled when the compiler
|
|
deletes user-supplied code after proving that the code in question
|
|
is unreachable.
|
|
|
|
Future work for SBCL includes expanding this hierarchy of types to
|
|
allow more fine-grained control over emission of diagnostic
|
|
messages.
|
|
|
|
@anchor{Condition sb-ext compiler-note}
|
|
@ttindex @sortas{compiler-note sb-ext} compiler-note [sb-ext]
|
|
@deffn{Condition} sb-ext:compiler-note
|
|
Root of the hierarchy of conditions representing information discovered
|
|
by the compiler that the user might wish to know, but which does not merit
|
|
a @code{style-warning} (or any more serious condition).
|
|
@end deffn
|
|
@anchor{Condition sb-ext code-deletion-note}
|
|
@ttindex @sortas{code-deletion-note sb-ext} code-deletion-note [sb-ext]
|
|
@deffn{Condition} sb-ext:code-deletion-note
|
|
A condition type signalled when the compiler deletes code that the user
|
|
has written, having proved that it is unreachable.
|
|
@end deffn
|
|
@node understanding compiler diagnostics
|
|
@subsection Understanding Compiler Diagnostics
|
|
|
|
@menu
|
|
* Parts of a Compiler Diagnostic: parts of a compiler diagnostic.
|
|
* Original and Actual Source: original and actual source.
|
|
* Processing Paths: processing paths.
|
|
@end menu
|
|
|
|
The messages emitted by the compiler contain a lot of detail in a
|
|
terse format, so they may be confusing at first. The messages will be
|
|
illustrated using this example program:
|
|
|
|
@example
|
|
(defmacro zoq (x)
|
|
`(roq (ploq (+ ,x 3))))
|
|
|
|
(defun foo (y)
|
|
(declare (symbol y))
|
|
(zoq y))
|
|
@end example
|
|
|
|
The main problem with this program is that it is trying to add @code{3}
|
|
to a symbol. Note also that the functions @code{roq} and @code{ploq} aren't
|
|
defined anywhere.
|
|
|
|
@node parts of a compiler diagnostic
|
|
@subsubsection Parts of a Compiler Diagnostic
|
|
|
|
When processing this program, the compiler will produce this warning:
|
|
|
|
@example
|
|
; file: /tmp/foo.lisp
|
|
; in: DEFUN FOO
|
|
; (ZOQ Y)
|
|
; --> ROQ PLOQ
|
|
; ==>
|
|
; (+ Y 3)
|
|
;
|
|
; caught WARNING:
|
|
; Asserted type NUMBER conflicts with derived type (VALUES SYMBOL &OPTIONAL).
|
|
@end example
|
|
|
|
In this example we see each of the six possible parts of a compiler
|
|
diagnostic:
|
|
|
|
@cindex original source
|
|
@cindex source, original
|
|
@cindex processing path
|
|
@cindex actual source
|
|
@cindex source, actual
|
|
@itemize
|
|
@item @code{file: /tmp/foo.lisp} is the name of the file that the compiler
|
|
read the relevant code from. The file name is displayed because it
|
|
may not be immediately obvious when there is an error during
|
|
compilation of a large system, especially when
|
|
@code{with-compilation-unit} is used to delay undefined warnings.
|
|
|
|
@item @code{in: DEFUN FOO} is the definition top level form responsible for
|
|
the diagnostic. It is obtained by taking the first two elements of
|
|
the enclosing form whose first element is a symbol beginning with
|
|
@code{def}. If there is no such enclosing @code{def} form, then the
|
|
outermost form is used. If there are multiple @code{def} forms, then
|
|
they are all printed from the outside in, separated by @code{=>}s. In
|
|
this example, the problem was in the @code{defun} for @code{foo}.
|
|
|
|
@item @code{(zoq y)} is the @emph{original source} form responsible for the
|
|
diagnostic. Original source means that the form directly appeared
|
|
in the original input to the compiler, i.e. in the lambda passed
|
|
to @code{compile} or in the top level form read from the source file. In
|
|
this example, the expansion of the @code{zoq} macro was responsible for
|
|
the message.
|
|
|
|
@item @code{--> roq ploq} This is the @emph{processing path} that the compiler
|
|
used to produce the code that caused the message to be emitted.
|
|
The processing path is a representation of the evaluated forms
|
|
enclosing the actual source that the compiler encountered when
|
|
processing the original source. The path is the first element of
|
|
each form, or the form itself if the form is not a list. These
|
|
forms result from the expansion of macros or source-to-source
|
|
transformation done by the compiler. In this example, the
|
|
enclosing evaluated forms are the calls to @code{roq} and @code{ploq}. These
|
|
calls resulted from the expansion of the @code{zoq} macro.
|
|
|
|
@item @code{==> (+ y 3)} is the @emph{actual source} responsible for the
|
|
diagnostic. If the actual source appears in the explanation, then
|
|
we print the next enclosing evaluated form, instead of printing
|
|
the actual source twice. (This is the form that would otherwise
|
|
have been the last form of the processing path.) In this example,
|
|
the problem is with the evaluation of the reference to the
|
|
variable @code{y}.
|
|
|
|
@item @code{caught WARNING: Asserted type NUMBER conflicts with derived type
|
|
(VALUES SYMBOL &OPTIONAL).} is the @emph{explanation} of the problem.
|
|
In this example, the problem is that, while the call to @code{+}
|
|
requires that its arguments are all of type @code{number}, the compiler
|
|
has derived that Y will evaluate to a @code{symbol}. Note that
|
|
@code{(values symbol &optional)} expresses that @code{y} evaluates to
|
|
precisely one value.
|
|
@end itemize
|
|
|
|
Note that each part of the message is distinctively marked:
|
|
|
|
@itemize
|
|
@item @code{file:} and @code{in:} mark the file and definition, respectively.
|
|
|
|
@item The original source is an indented form with no prefix.
|
|
|
|
@item Each line of the processing path is prefixed with @code{-->}.
|
|
|
|
@item The actual source form is indented like the original source, but
|
|
is marked by a preceding @code{==>} line. (FIXME: no it isn't.)
|
|
|
|
@item The explanation is prefixed with the diagnostic severity, which
|
|
can be @code{caught ERROR:}, @code{caught WARNING:}, @code{caught
|
|
STYLE-WARNING:}, or @code{note:}.
|
|
@end itemize
|
|
|
|
Each part of the message is more specific than the preceding one. If
|
|
consecutive messages are for nearby locations, then the front part
|
|
of the messages would be the same. In this case, the compiler omits
|
|
as much of the second message as in common with the first. For
|
|
example:
|
|
|
|
@example
|
|
; file: /tmp/foo.lisp
|
|
; in: DEFUN FOO
|
|
; (ZOQ Y)
|
|
; --> ROQ
|
|
; ==>
|
|
; (PLOQ (+ Y 3))
|
|
;
|
|
; caught STYLE-WARNING:
|
|
; undefined function: PLOQ
|
|
|
|
; ==>
|
|
; (ROQ (PLOQ (+ Y 3)))
|
|
;
|
|
; caught STYLE-WARNING:
|
|
; undefined function: ROQ
|
|
@end example
|
|
|
|
In this example, the file, definition and original source are
|
|
identical for the two messages, so the compiler omits them in the
|
|
second message. If consecutive messages are entirely identical, then
|
|
the compiler prints only the first message, followed by: @code{[Last
|
|
message occurs <repeats> times]} where @code{<repeats>} is the number of
|
|
times the message was given.
|
|
|
|
If the source was not from a file, then no file line is printed. If
|
|
the actual source is the same as the original source, then the
|
|
processing path and actual source will be omitted. If no forms
|
|
intervene between the original source and the actual source, then
|
|
the processing path will also be omitted.
|
|
|
|
@node original and actual source
|
|
@cindex original source
|
|
@cindex source, original
|
|
@cindex actual source
|
|
@cindex source, actual
|
|
@subsubsection Original and Actual Source
|
|
|
|
The @emph{original source} displayed will almost always be a list. If
|
|
the actual source for an message is a symbol, the original source will
|
|
be the immediately enclosing evaluated list form. So even if the
|
|
offending symbol does appear in the original source, the compiler will
|
|
print the enclosing list and then print the symbol as the actual
|
|
source (as though the symbol were introduced by a macro.)
|
|
|
|
When the @emph{actual source} is displayed (and is not a symbol), it will
|
|
always be code that resulted from the expansion of a macro or a
|
|
source-to-source compiler optimization. This is code that did not
|
|
appear in the original source program; it was introduced by the
|
|
compiler.
|
|
|
|
Keep in mind that when the compiler displays a source form in an
|
|
diagnostic message, it always displays the most specific (innermost)
|
|
responsible form. For example, compiling this function
|
|
|
|
@example
|
|
(defun bar (x)
|
|
(let (a)
|
|
(declare (fixnum a))
|
|
(setq a (foo x))
|
|
a))
|
|
@end example
|
|
|
|
gives this error message
|
|
|
|
@example
|
|
; file: /tmp/foo.lisp
|
|
; in: DEFUN BAR
|
|
; (LET (A)
|
|
; (DECLARE (FIXNUM A))
|
|
; (SETQ A (FOO X))
|
|
; A)
|
|
;
|
|
; caught WARNING:
|
|
; Asserted type FIXNUM conflicts with derived type (VALUES NULL &OPTIONAL).
|
|
@end example
|
|
|
|
This message is not saying that there is a problem somewhere in this
|
|
@code{let} -- it is saying that there is a problem with the @code{let} itself. In
|
|
this example, the problem is that @code{a}'s @code{nil} initial value is not a
|
|
@code{fixnum}.
|
|
|
|
@node processing paths
|
|
@cindex processing path
|
|
@subsubsection Processing Paths
|
|
|
|
The processing path is mainly useful for debugging macros, so if you
|
|
don't write macros, you can probably ignore it. Consider this example:
|
|
|
|
@example
|
|
(defun foo (n)
|
|
(dotimes (i n *undefined*)))
|
|
@end example
|
|
|
|
Compiling results in this error message:
|
|
|
|
@example
|
|
; in: DEFUN FOO
|
|
; (DOTIMES (I N *UNDEFINED*))
|
|
; --> DO BLOCK LET TAGBODY RETURN-FROM
|
|
; ==>
|
|
; (PROGN *UNDEFINED*)
|
|
;
|
|
; caught WARNING:
|
|
; undefined variable: *UNDEFINED*
|
|
@end example
|
|
|
|
Note that @code{do} appears in the processing path. This is because
|
|
@code{dotimes} expands into:
|
|
|
|
@example
|
|
(do ((i 0 (1+ i)) (#:g1 n))
|
|
((>= i #:g1) *undefined*)
|
|
(declare (type unsigned-byte i)))
|
|
@end example
|
|
|
|
@cindex macroexpansion
|
|
@cindex source transform
|
|
The rest of the processing path results from the macroexpansion of
|
|
@code{do}:
|
|
|
|
@example
|
|
(block nil
|
|
(let ((i 0) (#:g1 n))
|
|
(declare (type unsigned-byte i))
|
|
(tagbody (go #:g3)
|
|
#:g2 (psetq i (1+ i))
|
|
#:g3 (unless (>= i #:g1) (go #:g2))
|
|
(return-from nil (progn *undefined*)))))
|
|
@end example
|
|
|
|
In this example, the compiler descended into the @code{block}, @code{let}, @code{tagbody}
|
|
and @code{return-from} to reach the @code{progn} printed as the actual source.
|
|
This is a place where the "actual source appears in explanation"
|
|
rule was applied. The innermost actual source form was the symbol
|
|
@emph{undefined} itself, but that also appeared in the explanation, so
|
|
the compiler backed out one level.
|
|
|
|
@node handling of types
|
|
@section Handling of Types
|
|
|
|
@menu
|
|
* Declarations as Assertions: declarations as assertions.
|
|
* Precise Type Checking: precise type checking.
|
|
* Getting Existing Programs to Run: getting existing programs to run.
|
|
* Implementation Limitations: implementation limitations.
|
|
@end menu
|
|
|
|
One of the most important features of the SBCL compiler (similar to
|
|
the original CMUCL compiler, also known as @emph{Python}) is its fairly
|
|
sophisticated understanding of the Common Lisp type system and its
|
|
conservative approach to the implementation of type declarations.
|
|
|
|
These two features reward the use of type declarations throughout
|
|
development, even when high performance is not a concern. Also, as
|
|
discussed in the chapter on performance (see @ref{efficiency}), the use
|
|
of appropriate type declarations can be very important for
|
|
performance as well.
|
|
|
|
The SBCL compiler also has a greater knowledge of the Common Lisp
|
|
type system than other compilers. Support is incomplete only for
|
|
types involving the @code{satisfies} type specifier.
|
|
|
|
@node declarations as assertions
|
|
@subsection Declarations as Assertions
|
|
|
|
The SBCL compiler treats type declarations differently from most other
|
|
Lisp compilers. Under default compilation policy the compiler doesn't
|
|
blindly believe type declarations, but considers them assertions about
|
|
the program that should be checked: all type declarations that have
|
|
not been proven to always hold are asserted at runtime.
|
|
|
|
@emph{Remaining bugs in the compiler's handling of types unfortunately
|
|
provide some exceptions to this rule, see
|
|
@ref{implementation limitations}.}
|
|
|
|
@cindex safety, optimization quality
|
|
@cindex optimization quality safety
|
|
CLOS slot types form a notable exception. Types declared using the
|
|
@code{:type} slot option in @code{defclass} are asserted if and only if the class
|
|
was defined in @emph{safe code} and the slot access location is
|
|
in @emph{safe code} as well. This laxness does not pose any internal
|
|
consistency issues, as the CLOS slot types are not available for the
|
|
type inferencer, nor do CLOS slot types provide any efficiency
|
|
benefits.
|
|
|
|
There are three type checking policies available in SBCL, selectable
|
|
via @code{optimize} declarations.
|
|
|
|
@itemize
|
|
@item @strong{Full Type Checks}
|
|
|
|
All declarations are considered assertions to be checked at
|
|
runtime, and all type checks are precise. The default
|
|
compilation policy provides full type checks.
|
|
|
|
Used when @code{(or (>= safety 2) (>= safety speed 1))}.
|
|
|
|
@item @strong{Weak Type Checks}
|
|
|
|
Declared types may be simplified into faster to check
|
|
supertypes: for example, @code{(or (integer -17 -7) (integer 7 17))}
|
|
is simplified into @code{(integer -17 17)}.
|
|
|
|
@quotation
|
|
@strong{Warning}: It is relatively easy to corrupt the heap when
|
|
weak type checks are used if the program contains type-errors.
|
|
@end quotation
|
|
|
|
Used when @code{(and (< safety 2) (< safety speed))}.
|
|
|
|
@item @strong{No Type Checks}
|
|
|
|
All declarations are believed without assertions. Also disables
|
|
argument count and array bounds checking.
|
|
|
|
@quotation
|
|
@strong{Warning}: Any type errors in code where type checks are not
|
|
performed are liable to corrupt the heap.
|
|
@end quotation
|
|
|
|
Used when @code{(= safety 0)}.
|
|
@end itemize
|
|
|
|
@node precise type checking
|
|
@cindex type checking, precise
|
|
@cindex precise type checking
|
|
@subsection Precise Type Checking
|
|
|
|
Precise checking means that the check is done as though @code{typep}
|
|
had been called with the exact type specifier that appeared in the
|
|
declaration.
|
|
|
|
If a variable is declared to be @code{(integer 3 17)}, then its value
|
|
must always be an integer between @code{3} and @code{17}. If multiple type
|
|
declarations apply to a single variable, then all the declarations
|
|
must be correct; it is as though all the types were intersected
|
|
producing a single @code{and} type specifier.
|
|
|
|
To gain maximum benefit from the compiler's type checking, you
|
|
should always declare the types of function arguments and structure
|
|
slots as precisely as possible. This often involves the use of @code{or},
|
|
@code{member}, and other list-style type specifiers.
|
|
|
|
@node getting existing programs to run
|
|
@cindex existing programs, getting them to run
|
|
@cindex types, portability
|
|
@cindex compatibility with other Lisps
|
|
@subsection Getting Existing Programs to Run
|
|
|
|
Since SBCL's compiler does much more comprehensive type checking than
|
|
most Lisp compilers, SBCL may detect type errors in programs that have
|
|
been debugged using other compilers. These errors are mostly incorrect
|
|
declarations, although compile-time type errors can find actual bugs
|
|
if parts of the program have never been tested.
|
|
|
|
@cindex safety, optimization quality
|
|
@cindex optimization quality safety
|
|
Some incorrect declarations can only be detected by run-time type
|
|
checking. It is very important to initially compile a program with
|
|
full type checks (high safety optimization) and then test this safe
|
|
version. After the checking version has been tested, then you can
|
|
consider weakening or eliminating type checks. @emph{This applies even to
|
|
previously debugged programs} because the SBCL compiler does much
|
|
more type inference than other Common Lisp compilers, so an
|
|
incorrect declaration can do more damage.
|
|
|
|
The most common problem is with variables whose constant initial
|
|
value doesn't match the type declaration. Incorrect constant initial
|
|
values will always be flagged by a compile-time type error, and they
|
|
are simple to fix once located. Consider this code fragment:
|
|
|
|
@example
|
|
(prog (foo)
|
|
(declare (fixnum foo))
|
|
(setq foo ...)
|
|
...)
|
|
@end example
|
|
|
|
Here @code{foo} is given an initial value of @code{nil} but is declared to be a
|
|
@code{fixnum}. Even if it is never read, the initial value of a variable
|
|
must match the declared type. There are two ways to fix this
|
|
problem. Change the declaration
|
|
|
|
@example
|
|
(prog (foo)
|
|
(declare (type (or fixnum null) foo))
|
|
(setq foo ...)
|
|
...)
|
|
@end example
|
|
|
|
or change the initial value
|
|
|
|
@example
|
|
(prog ((foo 0))
|
|
(declare (fixnum foo))
|
|
(setq foo ...)
|
|
...)
|
|
@end example
|
|
|
|
It is generally preferable to change to a legal initial value rather
|
|
than to weaken the declaration, but sometimes it is simpler to
|
|
weaken the declaration than to try to make an initial value of the
|
|
appropriate type.
|
|
|
|
Another declaration problem occasionally encountered is incorrect
|
|
declarations on @code{defmacro} arguments. This can happen when a function
|
|
is converted into a macro. Consider this macro:
|
|
|
|
@example
|
|
(defmacro my-1+ (x)
|
|
(declare (fixnum x))
|
|
`(the fixnum (1+ ,x)))
|
|
@end example
|
|
|
|
Although legal and well-defined Common Lisp code, this meaning of
|
|
this definition is almost certainly not what the writer intended.
|
|
For example, this call is illegal:
|
|
|
|
@example
|
|
(my-1+ (+ 4 5))
|
|
@end example
|
|
|
|
This call is illegal because the argument to the macro is @code{(+ 4 5)},
|
|
which is a @code{list}, not a @code{fixnum}. Because of macro semantics, it is
|
|
hardly ever useful to declare the types of macro arguments. If you
|
|
really want to assert something about the type of the result of
|
|
evaluating a macro argument, then put a @code{the} in the expansion:
|
|
|
|
@example
|
|
(defmacro my-1+ (x)
|
|
`(the fixnum (1+ (the fixnum ,x))))
|
|
@end example
|
|
|
|
|
|
In this case, it would be stylistically preferable to change this
|
|
macro back to a function and declare it inline.
|
|
|
|
Some more subtle problems are caused by incorrect declarations that
|
|
can't be detected at compile time. Consider this code:
|
|
|
|
@example
|
|
(do ((pos 0 (position #a string :start (1+ pos))))
|
|
((null pos))
|
|
(declare (fixnum pos))
|
|
...)
|
|
@end example
|
|
|
|
Although @code{pos} is almost always a @code{fixnum}, it is @code{nil} at the end of
|
|
the loop. If this example is compiled with full type checks (the
|
|
default), then running it will signal a type error at the end of the
|
|
loop. If compiled without type checks, the program will go into an
|
|
infinite loop (or perhaps @code{position} will complain because @code{(1+ nil)}
|
|
isn't a sensible start.) Why? Because if you compile without type
|
|
checks, the compiler just quietly believes the type declaration.
|
|
Since the compiler believes that @code{pos} is always a @code{fixnum}, it
|
|
believes that @code{pos} is never @code{nil}, so @code{(null pos)} is never true, and
|
|
the loop exit test is optimized away. Such errors are sometimes
|
|
flagged by unreachable code notes, but it is still important to
|
|
initially compile and test any system with full type checks, even if
|
|
the system works fine when compiled using other compilers.
|
|
|
|
In this case, the fix is to weaken the type declaration to @code{(or
|
|
fixnum null)}. (Actually, this declaration is unnecessary in SBCL,
|
|
since it already knows that @code{position} returns a non-negative @code{fixnum}
|
|
or @code{nil}.)
|
|
|
|
Note that there is usually little performance penalty for weakening
|
|
a declaration in this way. Any numeric operations in the body can
|
|
still assume that the variable is a @code{fixnum}, since @code{nil} is not a legal
|
|
numeric argument. Another possible fix would be to say:
|
|
|
|
@example
|
|
(do ((pos 0 (position #a string :start (1+ pos))))
|
|
((null pos))
|
|
(let ((pos pos))
|
|
(declare (fixnum pos))
|
|
...))
|
|
@end example
|
|
|
|
This would be preferable in some circumstances, since it would allow
|
|
a non-standard representation to be used for the local @code{pos}
|
|
variable in the loop body.
|
|
|
|
@node implementation limitations
|
|
@subsection Implementation Limitations
|
|
|
|
If an @code{ftype} is placed after the function definition the function won't
|
|
perform any type checks, and the calls to the function will blindly
|
|
trust the declared types.
|
|
(@code{optimize} (@code{debug} 3)) will not trust any @code{ftype} declarations.
|
|
|
|
@node compiler policy
|
|
@section Compiler Policy
|
|
|
|
Compiler policy is controlled by the @code{optimize} declaration,
|
|
supporting all ANSI optimization qualities (@code{debug}, safety, space,
|
|
and speed). (A deprecated extension @code{sb-ext:inhibit-warnings} is still
|
|
supported but liable to go away at any time.)
|
|
|
|
For effects of various optimization qualities on type-safety and
|
|
debuggability see @ref{declarations as assertions} and
|
|
@ref{debugger policy control}.
|
|
|
|
Ordinarily, when the speed quality is high, the compiler emits notes
|
|
to notify the programmer about its inability to apply various
|
|
optimizations. For selective muffling of these notes, see
|
|
@ref{controlling verbosity}.
|
|
|
|
The value of space mostly influences the compiler's decision whether
|
|
to inline operations, which tend to increase the size of programs.
|
|
Use the value @code{0} with caution, since it can cause the compiler to
|
|
inline operations so indiscriminately that the net effect is to slow
|
|
the program by causing cache misses or even swapping.
|
|
|
|
@anchor{Function sb-ext describe-compiler-policy}
|
|
@ffindex @sortas{describe-compiler-policy sb-ext} describe-compiler-policy [sb-ext]
|
|
@deffn{Function} sb-ext:describe-compiler-policy &optional spec
|
|
Print all global optimization settings, augmented by @code{spec}.
|
|
@end deffn
|
|
@anchor{Function sb-ext restrict-compiler-policy}
|
|
@ffindex @sortas{restrict-compiler-policy sb-ext} restrict-compiler-policy [sb-ext]
|
|
@deffn{Function} sb-ext:restrict-compiler-policy &optional quality min max
|
|
Assign a minimum value to an optimization quality. @code{quality} is the name of
|
|
the optimization quality to restrict, @code{min} (defaulting to zero) is the
|
|
minimum allowed value, and @code{max} (defaults to 3) is the maximum.
|
|
|
|
Returns the alist describing the current policy restrictions.
|
|
|
|
If @code{quality} is @code{nil} or not given, nothing is done.
|
|
|
|
Otherwise, if @code{min} is zero or @code{max} is 3 or neither are given, any
|
|
existing restrictions of @code{quality} are removed.
|
|
|
|
See also @code{:policy} option in @code{with-compilation-unit}.
|
|
@end deffn
|
|
@anchor{Macro common-lisp with-compilation-unit}
|
|
@ffindex @sortas{with-compilation-unit common-lisp} with-compilation-unit [common-lisp]
|
|
@deffn{Macro} with-compilation-unit options &body body
|
|
Affects compilations that take place within its dynamic extent. It is
|
|
intended to be eg. wrapped around the compilation of all files in the same system.
|
|
|
|
Following options are defined:
|
|
|
|
@itemize
|
|
@item @code{:override} @code{<boolean-form>}
|
|
|
|
One of the effects of this form is to delay undefined warnings
|
|
until the end of the form, instead of giving them at the end of
|
|
each compilation. If @code{override} is @code{nil} (the default), then the
|
|
outermost @code{with-compilation-unit} form grabs the undefined warnings.
|
|
Specifying @code{:override} true causes that form to grab any enclosed
|
|
warnings, even if it is enclosed by another @code{with-compilation-unit}.
|
|
|
|
@item @code{:policy} @code{<optimize-declaration-form>}
|
|
|
|
Provides dynamic scoping for global compiler optimization
|
|
qualities and restrictions, limiting effects of subsequent
|
|
@code{optimize} proclamations and calls to
|
|
@code{sb-ext:restrict-compiler-policy} to the dynamic scope of @code{body}.
|
|
|
|
If @code{:override} is false, the specified @code{:policy} is merged with
|
|
current global policy. If @code{:override} is true, current global
|
|
policy, including any restrictions, is discarded in favor of the
|
|
specified
|
|
@code{:policy}.
|
|
|
|
Supplying @code{:policy} @code{nil} is equivalent to the option not being
|
|
supplied at all, i.e. dynamic scoping of policy does not take
|
|
place.
|
|
|
|
This option is an SBCL-specific experimental extension: Interface
|
|
subject to change.
|
|
|
|
@item @code{:source-namestring} @code{<namestring-form>}
|
|
|
|
Attaches the value returned by the @code{<namestring-form>} to the
|
|
internal debug-source information as the namestring of the source
|
|
file. Normally the namestring of the input-file for @code{compile-file}
|
|
is used: this option can be used to provide source-file
|
|
information for functions compiled using @code{compile}, or to override
|
|
the input-file of @code{compile-file}.
|
|
|
|
If both an outer and an inner @code{with-compilation-unit} provide a
|
|
@code{:source-namestring}, the inner one takes precedence. Unaffected by
|
|
@code{:override}.
|
|
|
|
This is an SBCL-specific extension.
|
|
|
|
@item @code{:source-plist} @code{<plist-form>}
|
|
|
|
Attaches the value returned by the @code{<plist-form>} to internal
|
|
debug-source information of functions compiled in within the
|
|
dynamic extent of @code{body}.
|
|
|
|
Primarily for use by development environments, in order to eg.
|
|
associate function definitions with editor-buffers. Can be
|
|
accessed using @code{sb-introspect:definition-source-plist}.
|
|
|
|
If an outer @code{with-compilation-unit} form also provide a
|
|
@code{source-plist}, it is appended to the end of the provided
|
|
@code{source-plist}. Unaffected by @code{:override}.
|
|
|
|
This is an SBCL-specific extension.
|
|
@end itemize
|
|
|
|
Examples:
|
|
|
|
@example
|
|
;; Prevent proclamations from the file leaking, and restrict
|
|
;; SAFETY to 3 -- otherwise uses the current global policy.
|
|
(with-compilation-unit (:policy '(optimize))
|
|
(restrict-compiler-policy 'safety 3)
|
|
(load "foo.lisp"))
|
|
@end example
|
|
|
|
@example
|
|
;; Using default policy instead of the current global one,
|
|
;; except for DEBUG 3.
|
|
(with-compilation-unit (:policy '(optimize debug)
|
|
:override t)
|
|
(load "foo.lisp"))
|
|
@end example
|
|
|
|
@example
|
|
;; Same as if :POLICY had not been specified at all: SAFETY 3
|
|
;; proclamation leaks out from WITH-COMPILATION-UNIT.
|
|
(with-compilation-unit (:policy nil)
|
|
(declaim (optimize safety))
|
|
(load "foo.lisp"))
|
|
@end example
|
|
@end deffn
|
|
@node compiler errors
|
|
@section Compiler Errors
|
|
|
|
@menu
|
|
* Type Errors at Compile Time: type errors at compile time.
|
|
* Errors During Macroexpansion: errors during macroexpansion.
|
|
* Read Errors: read errors.
|
|
@end menu
|
|
|
|
@node type errors at compile time
|
|
@cindex compile-time type error
|
|
@cindex type error, compile-time
|
|
@subsection Type Errors at Compile Time
|
|
|
|
If the compiler can prove at compile time that some portion of the
|
|
program cannot be executed without a type error, then it will give a
|
|
warning at compile time.
|
|
|
|
It is possible that the offending code would never actually be
|
|
executed at run-time due to some higher level consistency constraint
|
|
unknown to the compiler, so a type warning doesn't always indicate an
|
|
incorrect program.
|
|
|
|
For example, consider this code fragment:
|
|
|
|
@example
|
|
(defun raz (foo)
|
|
(let ((x (case foo
|
|
(:this 13)
|
|
(:that 9)
|
|
(:the-other 42))))
|
|
(declare (fixnum x))
|
|
(foo x)))
|
|
@end example
|
|
|
|
Compilation produces this warning:
|
|
|
|
@example
|
|
; in: DEFUN RAZ
|
|
; (CASE FOO (:THIS 13) (:THAT 9) (:THE-OTHER 42))
|
|
; --> LET COND IF COND IF COND IF
|
|
; ==>
|
|
; (COND)
|
|
;
|
|
; caught WARNING:
|
|
; This is not a FIXNUM:
|
|
; NIL
|
|
@end example
|
|
|
|
In this case, the warning means that if @code{foo} isn't any of @code{:this},
|
|
@code{:that} or @code{:the-other}, then @code{x} will be initialized to @code{nil}, which
|
|
the @code{fixnum} declaration makes illegal. The warning will go away if
|
|
@code{ecase} is used instead of @code{case}, or if @code{:the-other} is changed to @code{t}.
|
|
|
|
This sort of spurious type warning happens moderately often in the
|
|
expansion of complex macros and in inline functions. In such cases,
|
|
there may be dead code that is impossible to correctly execute. The
|
|
compiler can't always prove this code is dead (could never be
|
|
executed), so it compiles the erroneous code (which will always signal
|
|
an error if it is executed) and gives a warning.
|
|
|
|
@node errors during macroexpansion
|
|
@cindex macroexpansion, errors during
|
|
@subsection Errors During Macroexpansion
|
|
|
|
The compiler handles errors that happen during macroexpansion, turning
|
|
them into compiler errors. If you want to debug the error (to debug
|
|
a macro), you can set @code{*break-on-signals*} to @code{error}. For example, this
|
|
definition:
|
|
|
|
@example
|
|
(defun foo (e l)
|
|
(do ((current l (cdr current))
|
|
((atom current) nil))
|
|
(when (eq (car current) e) (return current))))
|
|
@end example
|
|
|
|
gives this error:
|
|
|
|
@example
|
|
; in: DEFUN FOO
|
|
; (DO ((CURRENT L (CDR CURRENT))
|
|
; ((ATOM CURRENT) NIL))
|
|
; (WHEN (EQ (CAR CURRENT) E) (RETURN CURRENT)))
|
|
;
|
|
; caught ERROR:
|
|
; (in macroexpansion of (DO # #))
|
|
; (hint: For more precise location, try *BREAK-ON-SIGNALS*.)
|
|
; DO step variable is not a symbol: (ATOM CURRENT)
|
|
@end example
|
|
|
|
@node read errors
|
|
@cindex compiler read error
|
|
@cindex read error, compiler
|
|
@subsection Read Errors
|
|
|
|
SBCL's compiler does not attempt to recover from read errors when
|
|
reading a source file, but instead just reports the offending
|
|
character position and gives up on the entire source file.
|
|
|
|
@node open coding and inline expansion
|
|
@cindex open-coding
|
|
@cindex inline expansion
|
|
@cindex static functions
|
|
@section Open Coding and Inline Expansion
|
|
|
|
Since Common Lisp forbids the redefinition of standard functions, the
|
|
compiler can have special knowledge of these standard functions
|
|
embedded in it. This special knowledge is used in various ways (open
|
|
coding, inline expansion, source transformation), but the implications
|
|
to the user are basically the same:
|
|
|
|
@itemize
|
|
@item Attempts to redefine standard functions may be frustrated, since
|
|
the function may never be called. Although it is technically
|
|
illegal to redefine standard functions, users sometimes want to
|
|
implicitly redefine these functions when they are debugging using
|
|
the @code{trace} macro. Special-casing of standard functions can be
|
|
inhibited using the @code{notinline} declaration, but even then some
|
|
phases of analysis such as type inferencing are applied by the
|
|
compiler.
|
|
|
|
@item The compiler can have multiple alternate implementations of
|
|
standard functions that implement different trade-offs of speed,
|
|
space and safety. This selection is based on the @ref{compiler policy}.
|
|
@end itemize
|
|
|
|
When a function call is @emph{open coded}, inline code whose effect is
|
|
equivalent to the function call is substituted for that function
|
|
call. When a function call is @emph{closed coded}, it is usually left as
|
|
is, although it might be turned into a call to a different function
|
|
with different arguments. As an example, if @code{nthcdr} were to be open
|
|
coded, then
|
|
|
|
@example
|
|
(nthcdr 4 foobar)
|
|
@end example
|
|
|
|
might turn into
|
|
|
|
@example
|
|
(cdr (cdr (cdr (cdr foobar))))
|
|
@end example
|
|
|
|
or even
|
|
|
|
@example
|
|
(do ((i 0 (1+ i))
|
|
(list foobar (cdr foobar)))
|
|
((= i 4) list))
|
|
@end example
|
|
|
|
If @code{nth} is closed coded, then
|
|
|
|
@example
|
|
(nth x l)
|
|
@end example
|
|
|
|
might stay the same, or turn into something like
|
|
|
|
@example
|
|
(car (nthcdr x l))
|
|
@end example
|
|
|
|
In general, open coding sacrifices space for speed, but some functions
|
|
(such as @code{car}) are so simple that they are always open-coded. Even
|
|
when not open-coded, a call to a standard function may be
|
|
transformed into a different function call (as in the last example)
|
|
or compiled as @emph{static call}. Static function call uses a more
|
|
efficient calling convention that forbids redefinition.
|
|
|
|
@node interpreter
|
|
@cindex interpreter
|
|
@section Interpreter
|
|
|
|
By default SBCL implements @code{eval} by calling the native code
|
|
compiler.
|
|
|
|
SBCL also includes an interpreter for use in special cases where
|
|
using the compiler is undesirable, for example due to compilation
|
|
overhead. Unlike in some other Lisp implementations, in SBCL
|
|
interpreted code is not safer or more debuggable than compiled code.
|
|
|
|
@anchor{Variable sb-ext *evaluator-mode*}
|
|
@vvindex @sortas{evaluator-mode* sb-ext} *evaluator-mode* [sb-ext]
|
|
@deffn{Variable} sb-ext:*evaluator-mode*
|
|
Toggle between different evaluator implementations. If set to @code{:compile},
|
|
an implementation of @code{eval} that calls the compiler will be used. If set
|
|
to @code{:interpret}, an interpreter will be used.
|
|
@end deffn
|
|
@node advanced compiler use and efficiency hints
|
|
@section Advanced Compiler Use and Efficiency Hints
|
|
|
|
For more advanced usages of the compiler, please see the chapter of the
|
|
same name in the CMUCL manual. Many aspects of the compiler have stayed
|
|
exactly the same, and there is a much more detailed explanation of the
|
|
compiler's behavior and how to maximally optimize code in their
|
|
manual. In particular, while SBCL no longer supports byte-code
|
|
compilation, it does support CMUCL's block compilation facility allowing
|
|
whole program optimization and increased use of the local call
|
|
convention.
|
|
|
|
Unlike CMUCL, SBCL is able to open-code forward-referenced type
|
|
tests while block compiling. This helps for mutually referential
|
|
@code{defstruct}s in particular.
|
|
|