(1+ (fee)))
uses generic arithmetic with INLINE and fixnum without.
+
+306: "Imprecise unions of array types"
+ a.(defun foo (x)
+ (declare (optimize speed)
+ (type (or (array cons) (array vector)) x))
+ (elt (aref x 0) 0))
+ (foo #((0))) => TYPE-ERROR
+
+ relatedly,
+
+ b.(subtypep
+ 'array
+ `(or
+ ,@(loop for x across sb-vm:*specialized-array-element-type-properties*
+ collect `(array ,(sb-vm:saetp-specifier x)))))
+ => NIL, T (when it should be T, T)
He showed how to convince the GNU toolchain to build SBCL in a way
which supports callbacks from C code into SBCL.
+Rudi Schlatte:
+ He ported Paul Foley's simple-streams implementation from cmucl,
+ converted the sbcl manual to Texinfo and wrote a documentation
+ string extractor that keeps function documentation in the manual
+ current.
+
Nikodemus Siivola:
He provided build fixes, in particular to tame the SunOS toolchain,
and has fixed many (stream-related and other) bugs besides.
src/runtime/sbcl
and
output/sbcl.core
+In addition, there are a number of modules that extend the basic sbcl
+functionality, in
+ contrib/
sbcl is a standard executable, built by compiling and linking an
ordinary C program. It provides the runtime environment for the
sbcl.core:
1. by default, in /usr/lib/sbcl/sbcl.core or /usr/local/lib/sbcl/sbcl.core
+ (depending on the SBCL_HOME C preproccessor #define at compile-time)
2. by environment variable:
- $ export SBCL_HOME=/foo/bar/
+ $ export SBCL_HOME=/foo/bar/lib/sbcl
$ sbcl
3. by command line option:
$ sbcl --core /foo/bar/sbcl.core"
-The usual, recommended approach is method #1. Method #2 is useful if
-you're installing SBCL on a system in your user account, instead of
-installing SBCL on an entire system. Method #3 is mostly useful for
-testing or other special cases.
+
+The usual, recommended approach is method #1. Method #2 is useful if
+you're installing SBCL on a system in a non-standard location (e.g. in
+your user account), instead of installing SBCL on an entire system.
+Method #3 is mostly useful for testing or other special cases.
So: the standard installation procedure is
1. Copy sbcl.core to /usr/lib or /usr/local/lib.
install.sh: e.g.
# INSTALL_ROOT=/usr/local sh install.sh
-
or
-
$ INSTALL_ROOT=/home/me/sbcl sh install.sh
+(if your INSTALL_ROOT is XYZ, SBCL_HOME should be set to
+XYZ/lib/sbcl).
IF YOU HAVE A SOURCE DISTRIBUTION:
the readtable currently in effect.
changes in sbcl-0.8.10 relative to sbcl-0.8.9:
+ * Support for the forthcoming 2.0 version of the NetBSD kernel
+ running on x86 hardware has been added. (thanks to Perry
+ E. Metzger most immediately, and others for their past work)
+ * [placeholder for DX summary]
+ ** user code with &REST lists declared dynamic-extent, under high
+ speed or space and low safety and debug optimization policy.
+ * The manual has been converted to Texinfo format and the debugger
+ chapter from the cmucl manual has been added.
+ * A facility has been added to extract documentation strings from
+ sbcl and store them as Texinfo-formatted snippets for inclusion in
+ the manual (via Texinfo's @include directive)
* bug fix: compiler emitted division in optimized DEREF. (thanks for
the test case to Dave Roberts)
* bug fix: multidimensional simple arrays loaded from FASLs had fill
pointers. (reported by Sean Ross)
+ * bug fix: PROFILE output is printed nicely even for large numerical
+ values. (thanks to Zach Beane)
planned incompatible changes in 0.8.x:
* (not done yet, but planned:) When the profiling interface settles
Others not so much, but in sbcl-0.7.0 I put some effort into
making them more consistent.
ARG argument
+ DX dynamic-extent
FUN function
GC garbage collect(ion)
N new: number, as in e.g. N-PASSES or N-WORD-BITS
;; for various constants e.g. SB!XC:MOST-POSITIVE-FIXNUM and
;; SB!VM:N-LOWTAG-BITS, needed by "early-objdef" and others
+ ("src/compiler/target/parms")
("src/compiler/generic/early-vm")
("src/compiler/generic/early-objdef")
- ("src/compiler/target/parms")
("src/code/early-array") ; needs "early-vm" numbers
("src/code/early-extensions") ; on host for COLLECT, SYMBOLICATE, etc.
#!+sparc ("src/code/sparc-vm" :not-host)
#!+hppa ("src/code/hppa-vm" :not-host)
#!+x86 ("src/code/x86-vm" :not-host)
+ #!+x86-64("src/code/x86-64-vm" :not-host)
#!+ppc ("src/code/ppc-vm" :not-host)
#!+alpha ("src/code/alpha-vm" :not-host)
#!+mips ("src/code/mips-vm" :not-host)
(defun function-arglist (function)
"Describe the lambda list for the function designator FUNCTION.
-Works for macros, simple functions and generic functions. Signals error
-if not found"
+Works for special-operators, macros, simple functions and generic
+functions. Signals error if not found"
(cond ((valid-function-name-p function)
(function-arglist
(or (macro-function function) (fdefinition function))))
(assert (equal (function-arglist 'cl-user::one)
'(cl-user::a cl-user::b cl-user::c)))
+(assert (equal (function-arglist 'the)
+ '(type sb-c::value)))
(defun matchp (object form-number)
(let ((ds (sb-introspect:find-definition-source object)))
--- /dev/null
+
+DOCFILES:=$(shell echo *.texinfo)
+ROOTFILE:=sbcl.texinfo
+TMPFILES:=sbcl.aux sbcl.cp sbcl.fn sbcl.ky sbcl.log sbcl.pg sbcl.toc sbcl.tp sbcl.vr
+
+PSFILE=sbcl.ps
+PDFFILE=sbcl.pdf
+DVIFILE=sbcl.dvi
+INFOFILE=sbcl.info
+HTMLDIR=$(basename $(ROOTFILE))
+# The value of DOCSTRINGDIR has to end with a slash or you lose (it's
+# passed to Lisp's `pathname' function).
+DOCSTRINGDIR="docstrings/"
+
+
+ifeq ($(MAKEINFO),)
+ MAKEINFO:=makeinfo
+endif
+
+ifeq ($(TEXI2PDF),)
+ TEXI2PDF:=texi2pdf
+endif
+
+ifeq ($(DVIPS),)
+ DVIPS:=dvips
+endif
+
+.PHONY: all
+all: ps pdf info html
+
+.PHONY: dist
+dist: html pdf
+
+
+
+# html documentation; output in $(HTMLDIR)
+.PHONY: html
+html: html-stamp
+
+html-stamp: $(DOCFILES) docstrings
+ @rm -rf $(HTMLDIR)
+ $(MAKEINFO) -I $(DOCSTRINGDIR) --html $(ROOTFILE)
+ touch html-stamp
+
+# Postscript documentation
+.PHONY: ps
+ps: $(PSFILE)
+
+$(PSFILE): $(DVIFILE)
+ dvips -o $@ $<
+
+$(DVIFILE): $(DOCFILES) docstrings
+ texi2dvi -I $(DOCSTRINGDIR) $(ROOTFILE)
+
+# PDF documentation
+.PHONY: pdf
+pdf: $(PDFFILE)
+
+$(PDFFILE): $(DOCFILES) docstrings
+ texi2pdf -I $(DOCSTRINGDIR) $(ROOTFILE)
+
+# info docfiles
+.PHONY: info
+info: $(INFOFILE)
+
+$(INFOFILE): $(DOCFILES) docstrings
+ $(MAKEINFO) -I $(DOCSTRINGDIR) $(ROOTFILE)
+
+# Texinfo docstring snippets; output hardcoded in docstrings/ for now.
+.PHONY: docstrings
+docstrings: docstrings-stamp
+
+docstrings-stamp:
+ DOCSTRINGDIR=$(DOCSTRINGDIR) sh docstrings.sh
+ touch docstrings-stamp
+
+
+
+.PHONY: clean
+clean:
+ rm -f *~ *.bak *.orig \#*\# .\#* texput.log
+ rm -rf $(HTMLDIR) $(DOCSTRINGDIR)
+ rm -f $(PSFILE) $(PDFFILE) $(DVIFILE) html-stamp docstrings-stamp
+ rm -f $(TMPFILES)
+ rm -f sbcl.info sbcl.info-*
+
+.PHONY: distclean
+distclean: clean
--- /dev/null
+@node Function Index, Concept Index, The Foreign Function Interface, Top
+@comment node-name, next, previous, up
+@appendix Function Index
+
+@printindex fn
+
+@node Concept Index, Colophon, Function Index, Top
+@comment node-name, next, previous, up
+@appendix Concept Index
+
+@printindex cp
+
+@node Colophon, , Concept Index, Top
+@comment node-name, next, previous, up
+@unnumbered Colophon
+
+This manual is maintained in Texinfo, and automatically translated
+into other forms (e.g. HTML or pdf). If you're @emph{reading} this
+manual in one of these non-Texinfo translated forms, that's fine, but
+if you want to @emph{modify} this manual, you are strongly advised to
+seek out a Texinfo version and modify that instead of modifying a
+translated version. Even better might be to seek out @emph{the}
+Texinfo version (maintained at the time of this writing as part of the
+SBCL project at @uref{http://sbcl.sourceforge.net/}) and submit a
+patch.
--- /dev/null
+@node Beyond The ANSI Standard, The Foreign Function Interface, Efficiency, Top
+@comment node-name, next, previous, up
+@chapter Beyond The ANSI Standard
+
+SBCL is mostly an implementation of the ANSI standard for
+Common Lisp. However, there's some important behavior which extends
+or clarifies the standard, and various behavior which outright
+violates the standard.
+
+
+@menu
+* Non-Conformance With The ANSI Standard::
+* Idiosyncrasies::
+* Extensions::
+@end menu
+
+@node Non-Conformance With The ANSI Standard, Idiosyncrasies, Beyond The ANSI Standard, Beyond The ANSI Standard
+@comment node-name, next, previous, up
+@section Non-Conformance With The ANSI Standard
+
+Essentially every type of non-conformance is considered a bug. (The
+exceptions involve internal inconsistencies in the standard.) In SBCL
+0.7.6, the master record of known bugs is in the @file{BUGS} file in
+the distribution. Some highlight information about bugs may also be
+found in the manual page. The recommended way to report bugs is
+through the sbcl-help or sbcl-devel mailings lists. For mailing list
+addresses, @ref{More SBCL Information}.
+
+
+@node Idiosyncrasies, Extensions, Non-Conformance With The ANSI Standard, Beyond The ANSI Standard
+@comment node-name, next, previous, up
+@section Idiosyncrasies
+
+The information in this section describes some of the ways that SBCL
+deals with choices that the ANSI standard leaves to the
+implementation.
+
+Declarations are generally treated as assertions. This general
+principle, and its implications, and the bugs which still keep the
+compiler from quite satisfying this principle, are discussed in the
+chapter on the compiler, @ref{The Compiler}.
+
+SBCL is essentially a compiler-only implementation of Common
+Lisp. That is, for all but a few special cases, @code{eval} creates a
+lambda expression, calls @code{compile} on the lambda expression to
+create a compiled function, and then calls @code{funcall} on the
+resulting function object. This is explicitly allowed by the ANSI
+standard, but leads to some oddities, e.g. collapsing @code{functionp}
+and @code{compiled-function-p} into the same predicate.
+
+SBCL is quite strict about ANSI's definition of
+@code{defconstant}. ANSI says that doing @code{defconstant} of the
+same symbol more than once is undefined unless the new value is
+@code{eql} to the old value. Conforming to this specification is a
+nuisance when the ``constant'' value is only constant under some
+weaker test like @code{string=} or @code{equal}. It's especially
+annoying because, in SBCL, @code{defconstant} takes effect not only at
+load time but also at compile time, so that just compiling and loading
+reasonable code like
+
+@lisp
+(defconstant +foobyte+ '(1 4))
+@end lisp
+
+runs into this undefined behavior. Many implementations of Common Lisp
+try to help the programmer around this annoyance by silently accepting
+the undefined code and trying to do what the programmer probably
+meant. SBCL instead treats the undefined behavior as an error. Often
+such code can be rewritten in portable ANSI Common Lisp which has the
+desired behavior. E.g., the code above can be given an exactly
+defined meaning by replacing @code{defconstant} either with
+@code{defparameter} or with a customized macro which does the right
+thing, possibly along the lines of the @code{defconstant-eqx} macro
+used internally in the implementation of SBCL itself. In
+circumstances where this is not appropriate, the programmer can handle
+the condition type @code{sb-ext:defconstant-uneql}, and choose either
+the @command{continue} or @command{abort} restart as appropriate.
+
+SBCL gives style warnings about various kinds of perfectly legal code,
+e.g.
+
+@itemize
+
+@item
+@code{defmethod} without @code{defgeneric}
+
+@item
+multiple @code{defun}s of the same symbol
+
+@item
+special variables not named in the conventional @code{*foo*} style,
+and lexical variables unconventionally named in the @code{*foo*} style
+
+@end itemize
+
+This causes friction with people who point out that other ways of
+organizing code (especially avoiding the use of @code{defgeneric}) are
+just as aesthetically stylish. However, these warnings should be read
+not as ``warning, bad aesthetics detected, you have no style'' but
+``warning, this style keeps the compiler from understanding the code
+as well as you might like.'' That is, unless the compiler warns about
+such conditions, there's no way for the compiler to warn about some
+programming errors which would otherwise be easy to overlook. (Related
+bug: The warning about multiple @code{defun}s is pointlessly annoying
+when you compile and then load a function containing @code{defun}
+wrapped in @code{eval-when}, and ideally should be suppressed in that
+case, but still isn't as of SBCL 0.7.6.)
+
+
+@node Extensions, , Idiosyncrasies, Beyond The ANSI Standard
+@comment node-name, next, previous, up
+@section Extensions
+
+SBCL is derived from CMUCL, which implements many extensions to the
+ANSI standard. SBCL doesn't support as many extensions as CMUCL, but
+it still has quite a few.
+
+
+@menu
+* Things Which Might Be In The Next ANSI Standard::
+* Threading::
+* Support For Unix::
+* Customization Hooks for Users::
+* Tools To Help Developers::
+* Interface To Low-Level SBCL Implementation::
+* Efficiency Hacks::
+@end menu
+
+@node Things Which Might Be In The Next ANSI Standard, Threading, Extensions, Extensions
+@comment node-name, next, previous, up
+@subsection Things Which Might Be In The Next ANSI Standard
+
+SBCL provides extensive support for calling external C code, @ref{The
+Foreign Function Interface}.
+
+SBCL provides additional garbage collection functionality not
+specified by ANSI. Weak pointers allow references to objects to be
+maintained without keeping them from being GCed (garbage
+collected). And ``finalization'' hooks are available to cause code to
+be executed when an object has been GCed.
+@c <!-- FIXME: Actually documenting these would be good.:-| -->
+
+SBCL supports @dfn{Gray streams}, user-overloadable CLOS classes whose
+instances can be used as Lisp streams (e.g. passed as the first
+argument to @code{format}). Additionally, the bundled contrib module
+@dfn{sb-simple-streams} implements a subset of the Franz Allegro
+simple-streams proposal.
+
+SBCL supports a MetaObject Protocol which is intended to be compatible
+with AMOP; present exceptions to this (as distinct from current bugs)
+are:
+
+@itemize
+
+@item
+the abstract @code{metaobject} class is not present in the class
+hierarchy;
+
+@item
+the @code{standard-object} and @code{funcallable-standard-object}
+classes are disjoint;
+
+@item
+@code{compute-effective-method} only returns one value, not two;
+
+@item
+the system-supplied @code{:around} method for @code{compute-slots}
+specialized on @code{funcallable-standard-class} does not respect the
+requested order from a user-supplied primary method.
+
+@end itemize
+
+
+@node Threading, Support For Unix, Things Which Might Be In The Next ANSI Standard, Extensions
+@comment node-name, next, previous, up
+@subsection Threading (a.k.a Multiprocessing)
+
+SBCL (as of version 0.8.3, on Linux x86 only) supports a fairly
+low-level threading interface that maps onto the host operating
+system's concept of threads or lightweight processes.
+
+@subsubsection Lisp-level view
+
+A rudimentary interface to creating and managing multiple threads can
+be found in the @dfn{sb-thread} package. This is intended for public
+consumption, so look at the exported symbols and their documentation
+strings.
+
+Dynamic bindings to symbols are per-thread. Signal handlers are
+per-thread.
+
+Mutexes and condition variables are available for managing access to
+shared data: see
+
+@itemize
+
+@item
+@code{(apropos "mutex" :sb-thread)}
+
+@item
+@code{(apropos "condition" :sb-thread)}
+
+@item
+and the @code{waitqueue} structure
+
+@end itemize
+
+and poke around in their documentation strings.
+
+@subsubsection Sessions
+
+If the user has multiple views onto the same Lisp image (for example,
+using multiple terminals, or a windowing system, or network access)
+they are typically set up as multiple @dfn{sessions} such that each
+view has its own collection of foreground/background/stopped threads.
+A thread which wishes to create a new session can use
+@code{sb-thread:with-new-session} to remove itself from the current
+session (which it shares with its parent and siblings) and create a
+fresh one. See also @code{sb-thread:make-listener-thread}.
+
+Within a single session, threads arbitrate between themselves for the
+user's attention. A thread may be in one of three notional states:
+foreground, background, or stopped. When a background process
+attempts to print a repl prompt or to enter the debugger, it will stop
+and print a message saying that it has stopped. The user at his
+leisure may switch to that thread to find out what it needs. If a
+background thread enters the debugger, selecting any restart will put
+it back into the background before it resumes. Arbitration for the
+input stream is managed by calls to @code{sb-thread:get-foreground}
+(which may block) and @code{sb-thread:release-foreground}.
+
+@code{sb-ext:quit} terminates all threads in the current session, but
+leaves other sessions running.
+
+
+@subsubsection Implementation (Linux x86)
+
+On Linux x86, threading is implemented using @code{clone()} and does
+not involve pthreads. This is not because there is anything wrong
+with pthreads @emph{per se}, but there is plenty wrong (from our
+perspective) with LinuxThreads. SBCL threads are mapped 1:1 onto
+Linux tasks which share a VM but nothing else - each has its own
+process id and can be seen in e.g. @command{ps} output.
+
+Per-thread local bindings for special variables is achieved using the
+%fs segment register to point to a per-thread storage area. This may
+cause interesting results if you link to foreign code that expects
+threading or creates new threads, and the thread library in question
+uses %fs in an incompatible way.
+
+There are two implementation mechanisms for queueing. If SBCL was
+built on an NPTL-capable Linux system (2.6 or some vendor 2.4 ports)
+with the @code{:SB-FUTEX} feature, queuing will be done using the
+@code{sys_futex()} system call if it's available at runtime.
+Otherwise it will fall back to using @code{sigtimedwait()} to sleep
+and a signal (@code{SIG_DEQUEUE}, one of the POSIX RT signals) to
+wake.
+
+Garbage collection is done with the existing Conservative Generational
+GC. Allocation is done in small (typically 8k) regions: each thread
+has its own region so this involves no stopping. However, when a
+region fills, a lock must be obtained while another is allocated, and
+when a collection is required, all processes are stopped. This is
+achieved by sending them signals, which may make for interesting
+behaviour if they are interrupted in system calls. The streams
+interface is believed to handle the required system call restarting
+correctly, but this may be a consideration when making other blocking
+calls e.g. from foreign library code.
+
+Large amounts of the SBCL library have not been inspected for
+thread-safety. Some of the obviously unsafe areas have large locks
+around them, so compilation and fasl loading, for example, cannot be
+parallelized. Work is ongoing in this area.
+
+A new thread by default is created in the same POSIX process group and
+session as the thread it was created by. This has an impact on
+keyboard interrupt handling: pressing your terminal's intr key
+(typically @kbd{Control-C}) will interrupt all processes in the
+foreground process group, including Lisp threads that SBCL considers
+to be notionally `background'. This is undesirable, so background
+threads are set to ignore the SIGINT signal.
+
+@code{sb-thread:make-listener-thread} in addition to creating a new
+Lisp session makes a new POSIX session, so that pressing
+@kbd{Control-C} in one window will not interrupt another listener -
+this has been found to be embarrassing.
+
+
+@node Support For Unix, Customization Hooks for Users, Threading, Extensions
+@comment node-name, next, previous, up
+@subsection Support For Unix
+
+The UNIX command line can be read from the variable
+@code{sb-ext:*posix-argv*}. The UNIX environment can be queried with
+the @code{sb-ext:posix-getenv} function.
+
+@include fun-sb-ext-posix-getenv.texinfo
+
+The SBCL system can be terminated with @code{sb-ext:quit}, (but see
+notes in @ref{Threading} about the interaction between this feature and
+sessions) optionally returning a specified numeric value to the
+calling Unix process. The normal Unix idiom of terminating on end of
+file on input is also supported.
+
+@include fun-sb-ext-quit.texinfo
+
+@node Customization Hooks for Users, Tools To Help Developers, Support For Unix, Extensions
+@comment node-name, next, previous, up
+@subsection Customization Hooks for Users
+
+The behaviour of @code{require} when called with only one argument is
+implementation-defined. In SBCL it calls functions on the
+user-settable list @code{sb-ext:*module-provider-functions*} - see the
+@code{require} documentation string for details.
+
+The toplevel repl prompt may be customized, and the function
+that reads user input may be replaced completely.
+@c <!-- FIXME but I don't currently remember how -->
+
+
+@node Tools To Help Developers, Interface To Low-Level SBCL Implementation, Customization Hooks for Users, Extensions
+@comment node-name, next, previous, up
+@subsection Tools To Help Developers
+
+SBCL provides a profiler and other extensions to the ANSI
+@code{trace} facility. See the online function documentation for
+@code{trace} for more information.
+
+The debugger supports a number of options. Its documentation is
+accessed by typing @kbd{help} at the debugger prompt.
+@c <!-- FIXME:
+@c A true debugger section in the manual would be good. Start
+@c with CMU CL's debugger section, but remember:
+@c * no QUIT command (TOPLEVEL restart instead)
+@c * no GO command (CONTINUE restart instead)
+@c * Limitations of the x86 port of the debugger should be
+@c documented or fixed where possible.
+@c * Discuss TRACE and its unification with PROFILE. -->
+
+Documentation for @code{inspect} is accessed by typing @kbd{help} at
+the @code{inspect} prompt.
+
+
+@node Interface To Low-Level SBCL Implementation, Efficiency Hacks, Tools To Help Developers, Extensions
+@comment node-name, next, previous, up
+@subsection Interface To Low-Level SBCL Implementation
+
+SBCL has the ability to save its state as a file for later
+execution. This functionality is important for its bootstrapping
+process, and is also provided as an extension to the user. See the
+documentation string for @code{sb-ext:save-lisp-and-die} for more
+information.
+
+@quotation
+Note: SBCL has inherited from CMUCL various hooks to allow the user to
+tweak and monitor the garbage collection process. These are somewhat
+stale code, and their interface might need to be cleaned up. If you
+have urgent need of them, look at the code in @file{src/code/gc.lisp}
+and bring it up on the developers' mailing list.
+@end quotation
+
+@quotation
+Note: SBCL has various hooks inherited from CMUCL, like
+@code{sb-ext:float-denormalized-p}, to allow a program to take
+advantage of IEEE floating point arithmetic properties which aren't
+conveniently or efficiently expressible using the ANSI standard. These
+look good, and their interface looks good, but IEEE support is
+slightly broken due to a stupid decision to remove some support for
+infinities (because it wasn't in the ANSI spec and it didn't occur to
+me that it was in the IEEE spec). If you need this stuff, take a look
+at the code and bring it up on the developers' mailing
+list.
+@end quotation
+
+
+@node Efficiency Hacks, , Interface To Low-Level SBCL Implementation, Extensions
+@comment node-name, next, previous, up
+@subsection Efficiency Hacks
+
+The @code{sb-ext:purify} function causes SBCL first to collect all
+garbage, then to mark all uncollected objects as permanent, never
+again attempting to collect them as garbage. This can cause a large
+increase in efficiency when using a primitive garbage collector, or a
+more moderate increase in efficiency when using a more sophisticated
+garbage collector which is well suited to the program's memory usage
+pattern. It also allows permanent code to be frozen at fixed
+addresses, a precondition for using copy-on-write to share code
+between multiple Lisp processes. it is less important with modern
+generational garbage collectors.
+
+@include fun-sb-ext-purify.texinfo
+
+@code{sb-ext:truly-the} special form declares the type of the result
+of the operations, producing its argument; the declaration is not
+checked. In short: don't use it.
+
+@include special-operator-sb-ext-truly-the.texinfo
+
+The @code{sb-ext:freeze-type} declaration declares that a
+type will never change, which can make type testing
+(@code{typep}, etc.) more efficient for structure types.
+
+The @code{sb-ext:constant-function} declaration specifies
+that a function will always return the same value for the same
+arguments, which may allow the compiler to optimize calls
+to it. This is appropriate for functions like @code{sqrt}, but
+is @emph{not} appropriate for functions like @code{aref},
+which can change their return values when the underlying data are
+changed.
+@c <!-- FIXME: This declaration does not seem to be supported in the
+@c current compiler. -->
--- /dev/null
+@node The Compiler, The Debugger, Introduction, Top
+@comment node-name, next, previous, up
+@chapter The Compiler
+
+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}.
+
+@menu
+* Error Messages::
+* Handling of Types::
+* Compiler Policy::
+* Open Coding and Inline Expansion::
+@end menu
+
+@node Error Messages, Handling of Types, The Compiler, The Compiler
+@comment node-name, next, previous, up
+@section Error Messages
+@cindex Error messages, Compiler
+@cindex Compiler error messages
+
+The compiler supplies a large amount of source location information in
+error messages. The error messages contain a lot of detail in a terse
+format, so they may be confusing at first. Error messages will be
+illustrated using this example program:
+
+@lisp
+(defmacro zoq (x)
+ `(roq (ploq (+ ,x 3))))
+
+(defun foo (y)
+ (declare (symbol y))
+ (zoq y))
+@end lisp
+
+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.
+
+
+@menu
+* The Parts of the Error Message::
+* The Original and Actual Source::
+* Error Severity::
+* Errors During Macroexpansion::
+* Read Errors::
+@end menu
+
+@node The Parts of the Error Message, The Original and Actual Source, Error Messages, Error Messages
+@comment node-name, next, previous, up
+@subsection The Parts of the Error Message
+
+When processing this program, the compiler will produce this warning:
+
+@example
+file: /tmp/foo.lisp
+
+in: DEFUN FOO
+(ZOQ Y)
+--> ROQ PLOQ +
+==>
+Y
+caught WARNING:
+Result is a SYMBOL, not a NUMBER.
+@end example
+
+In this example we see each of the six possible parts of a compiler
+error message:
+
+@enumerate
+
+@item
+@samp{File: /tmp/foo.lisp} This 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
+@samp{in: DEFUN FOO} This is the definition top level form responsible
+for the error. It is obtained by taking the first two elements of the
+enclosing form whose first element is a symbol beginning with
+``@samp{def}''. If there is no such enclosing ``@samp{def}'' form,
+then the outermost form is used. If there are multiple @samp{def}
+forms, then they are all printed from the outside in, separated by
+@samp{=>}'s. In this example, the problem was in the @code{defun} for
+@code{foo}.
+
+@item
+@samp{(ZOQ Y)} This is the @dfn{original source} form responsible for
+the error. 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 error.
+
+@item
+@samp{--> ROQ PLOQ +} This is the @dfn{processing path} that the
+compiler used to produce the errorful code. 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},
+@code{ploq} and @code{+}. These calls resulted from the expansion of
+the @code{zoq} macro.
+
+@item
+@samp{==> Y} This is the @dfn{actual source} responsible for the
+error. 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
+@samp{caught WARNING: Result is a SYMBOL, not a NUMBER.} This is the
+@dfn{explanation} of the problem. In this example, the problem is that
+@code{y} evaluates to a symbol, but is in a context where a number is
+required (the argument to @code{+}).
+
+@end enumerate
+
+Note that each part of the error message is distinctively marked:
+
+@itemize
+
+@item
+ @samp{file:} and @samp{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 @samp{-->}
+
+@item
+The actual source form is indented like the original source, but is
+marked by a preceding @samp{==>} line.
+
+
+@item
+The explanation is prefixed with the error severity, which can be
+@samp{caught ERROR:}, @samp{caught WARNING:}, @samp{caught
+STYLE-WARNING:}, or @samp{note:}.
+
+@end itemize
+
+Each part of the error message is more specific than the preceding
+one. If consecutive error messages are for nearby locations, then the
+front part of the error 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: @samp{[Last
+message occurs @var{repeats} times]} where @var{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 The Original and Actual Source, Error Severity, The Parts of the Error Message, Error Messages
+@comment node-name, next, previous, up
+@subsection The Original and Actual Source
+
+The @emph{original source} displayed will almost always be a list. If
+the actual source for an error 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 error
+message, it always displays the most specific (innermost) responsible
+form. For example, compiling this function
+
+@lisp
+(defun bar (x)
+ (let (a)
+ (declare (fixnum a))
+ (setq a (foo x))
+ a))
+@end lisp
+
+gives this error message
+
+@example
+in: DEFUN BAR
+(LET (A) (DECLARE (FIXNUM A)) (SETQ A (FOO X)) A)
+caught WARNING: The binding of A is not a FIXNUM:
+NIL
+@end example
+
+This error message is not saying ``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}.
+
+
+@subsection The Processing Path
+@cindex Processing path
+@cindex Macroexpansion
+@cindex Source-to-source transformation
+
+The processing path is mainly useful for debugging macros, so if you
+don't write macros, you can probably ignore it. Consider this example:
+
+@lisp
+(defun foo (n)
+ (dotimes (i n *undefined*)))
+@end lisp
+
+Compiling results in this error message:
+
+@example
+in: DEFUN FOO
+(DOTIMES (I N *UNDEFINED*))
+--> DO BLOCK LET TAGBODY RETURN-FROM
+==>
+(PROGN *UNDEFINED*)
+caught STYLE-WARNING:
+undefined variable: *UNDEFINED*
+@end example
+
+Note that @code{do} appears in the processing path. This is because
+@code{dotimes} expands into:
+
+@lisp
+(do ((i 0 (1+ i)) (#:g1 n))
+ ((>= i #:g1) *undefined*)
+ (declare (type unsigned-byte i)))
+@end lisp
+
+The rest of the processing path results from the expansion of
+@code{do}:
+
+@lisp
+(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 lisp
+
+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
+@code{*undefined*} itself, but that also appeared in the
+explanation, so the compiler backed out one level.
+
+
+@node Error Severity, Errors During Macroexpansion, The Original and Actual Source, Error Messages
+@comment node-name, next, previous, up
+@subsection Error Severity
+@cindex Severity of compiler errors
+@cindex compiler error severity
+
+There are four levels of compiler error severity: @emph{error},
+@emph{warning}, @emph{style warning}, and @emph{note}. 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}, is used for problems which are too mild for the standard
+condition classes, typically hints about how efficiency might be
+improved.
+
+
+@node Errors During Macroexpansion, Read Errors, Error Severity, Error Messages
+@comment node-name, next, previous, up
+@subsection Errors During Macroexpansion
+@cindex Macroexpansion, errors during
+
+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:
+
+@lisp
+(defun foo (e l)
+ (do ((current l (cdr current))
+ ((atom current) nil))
+ (when (eq (car current) e) (return current))))
+@end lisp
+
+gives this error:
+
+@example
+in: DEFUN FOO
+(DO ((CURRENT L #) (# NIL)) (WHEN (EQ # 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, , Errors During Macroexpansion, Error Messages
+@comment node-name, next, previous, up
+@subsection Read Errors
+@cindex Read errors, compiler
+
+SBCL's compiler (unlike CMUCL's) 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.
+
+
+@c <!-- FIXME: How much control over error messages is in SBCL?
+@c _ How much should be? How much of this documentation should
+@c _ we save or adapt?
+@c _
+@c _ %%\node Error Message Parameterization, , Read Errors, Interpreting Error Messages
+@c _ \subsection{Error Message Parameterization}
+@c _ \cpsubindex{error messages}{verbosity}
+@c _ \cpsubindex{verbosity}{of error messages}
+@c _
+@c _ There is some control over the verbosity of error messages. See also
+@c _ \varref{undefined-warning-limit}, \code{*efficiency-note-limit*} and
+@c _ \varref{efficiency-note-cost-threshold}.
+@c _
+@c _ \begin{defvar}{}{enclosing-source-cutoff}
+@c _
+@c _ This variable specifies the number of enclosing actual source forms
+@c _ that are printed in full, rather than in the abbreviated processing
+@c _ path format. Increasing the value from its default of \code{1}
+@c _ allows you to see more of the guts of the macroexpanded source,
+@c _ which is useful when debugging macros.
+@c _ \end{defvar}
+@c _
+@c _ \begin{defvar}{}{error-print-length}
+@c _ \defvarx{error-print-level}
+@c _
+@c _ These variables are the print level and print length used in
+@c _ printing error messages. The default values are \code{5} and
+@c _ \code{3}. If null, the global values of \code{*print-level*} and
+@c _ \code{*print-length*} are used.
+@c _ \end{defvar}
+@c _
+@c _ \begin{defmac}{extensions:}{define-source-context}{%
+@c _ \args{\var{name} \var{lambda-list} \mstar{form}}}
+@c _
+@c _ This macro defines how to extract an abbreviated source context from
+@c _ the \var{name}d form when it appears in the compiler input.
+@c _ \var{lambda-list} is a \code{defmacro} style lambda-list used to
+@c _ parse the arguments. The \var{body} should return a list of
+@c _ subforms that can be printed on about one line. There are
+@c _ predefined methods for \code{defstruct}, \code{defmethod}, etc. If
+@c _ no method is defined, then the first two subforms are returned.
+@c _ Note that this facility implicitly determines the string name
+@c _ associated with anonymous functions.
+@c _ \end{defmac}
+@c _
+@c _ -->
+
+
+@node Handling of Types, Compiler Policy, Error Messages, The Compiler
+@comment node-name, next, previous, up
+@section The Compiler's Handling of Types
+
+The most unusual features of the SBCL compiler (which is very similar
+to the original CMUCL compiler, also known as @dfn{Python}) is its
+unusually sophisticated understanding of the Common Lisp type system
+and its unusually 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
+(@pxref{Efficiency}), the use of appropriate type declarations can be
+very important for performance as well.
+
+The SBCL compiler, like the related compiler in CMUCL, treats type
+declarations much differently than other Lisp compilers. By default
+(@emph{i.e.}, at ordinary levels of the @code{safety} compiler
+optimization parameter), the compiler doesn't blindly believe most
+type declarations; it considers them assertions about the program that
+should be checked.
+
+The SBCL compiler also has a greater knowledge of the
+Common Lisp type system than other compilers. Support is incomplete
+only for the @code{not}, @code{and} and @code{satisfies}
+types.
+
+@c <!-- FIXME: See also sections \ref{advanced-type-stuff}
+@c and \ref{type-inference}, once we snarf them from the
+@c CMU CL manual. -->
+
+
+@menu
+* Type Errors at Compile Time::
+* Precise Type Checking::
+* Weakened Type Checking::
+* Getting Existing Programs to Run::
+* Implementation Limitations::
+@end menu
+
+
+@node Type Errors at Compile Time, Precise Type Checking, Handling of Types, Handling of Types
+@comment node-name, next, previous, up
+@subsection Type Errors at Compile Time
+@cindex Compile time type errors
+@cindex Type checking, 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:
+
+
+@lisp
+(defun raz (foo)
+ (let ((x (case foo
+ (:this 13)
+ (:that 9)
+ (:the-other 42))))
+ (declare (fixnum x))
+ (foo x)))
+@end lisp
+
+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.
+
+
+Type warnings are inhibited when the @code{sb-ext:inhibit-warnings}
+optimization quality is @code{3}. @xref{Compiler Policy}. This
+can be used in a local declaration to inhibit type warnings in a code
+fragment that has spurious warnings.
+
+
+@node Precise Type Checking, Weakened Type Checking, Type Errors at Compile Time, Handling of Types
+@comment node-name, next, previous, up
+@subsection Precise Type Checking
+@cindex Precise type checking
+@cindex Type checking, precise
+
+With the default compilation policy, all type declarations are
+precisely checked, except in a few situations where they are simply
+ignored instead. 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. In SBCL, adding type declarations makes
+code safer. (Except that remaining bugs in the compiler's handling of
+types unfortunately provide some exceptions to this rule, see
+@ref{Implementation Limitations}).
+
+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.
+
+Argument and result type declarations are automatically enforced. If
+you declare the type of a function argument, a type check will be done
+when that function is called. In a function call, the called function
+does the argument type checking.
+
+The types of structure slots are also checked. The value of a
+structure slot must always be of the type indicated in any
+@code{:type} slot option.
+
+In traditional Common Lisp compilers, not all type assertions are
+checked, and type checks are not precise. Traditional compilers
+blindly trust explicit type declarations, but may check the argument
+type assertions for built-in functions. Type checking is not precise,
+since the argument type checks will be for the most general type legal
+for that argument. In many systems, type declarations suppress what
+little type checking is being done, so adding type declarations makes
+code unsafe. This is a problem since it discourages writing type
+declarations during initial coding. In addition to being more error
+prone, adding type declarations during tuning also loses all the
+benefits of debugging with checked type assertions.
+
+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 Weakened Type Checking, Getting Existing Programs to Run, Precise Type Checking, Handling of Types
+@comment node-name, next, previous, up
+@subsection Weakened Type Checking
+@cindex Weakened type checking
+@cindex Type checking, weakened
+
+At one time, CMUCL supported another level of type checking,
+``weakened type checking'', when the value for the @code{speed}
+optimization quality is greater than @code{safety}, and @code{safety}
+is not @code{0}. The CMUCL manual still has a description of it, but
+even the CMU CL code no longer corresponds to the manual. Some of this
+partial safety checking lingers on in SBCL, but it's not a supported
+feature, and should not be relied on. If you ask the compiler to
+optimize @code{speed} to a higher level than @code{safety}, your
+program is performing without a safety net, because SBCL may at its
+option believe any or all type declarations with either partial or
+nonexistent runtime checking.
+
+
+@node Getting Existing Programs to Run, Implementation Limitations, Weakened Type Checking, Handling of Types
+@comment node-name, next, previous, up
+@subsection Getting Existing Programs to Run
+@cindex Existing programs, to run
+@cindex Types, portability
+@cindex Compatibility with other Lisps
+@c (should also have an entry in the non-ANSI-isms section)-->
+
+Since SBCL's compiler, like CMUCL'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.
+
+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 @code{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:
+
+@lisp
+(prog (foo)
+ (declare (fixnum foo))
+ (setq foo ...)
+ ...)
+@end lisp
+
+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
+
+@lisp
+(prog (foo)
+ (declare (type (or fixnum null) foo))
+ (setq foo ...)
+ ...)
+@end lisp
+
+or change the initial value
+
+@lisp
+(prog ((foo 0))
+ (declare (fixnum foo))
+ (setq foo ...)
+ ...)
+@end lisp
+
+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:
+
+@lisp
+(defmacro my-1+ (x)
+ (declare (fixnum x))
+ `(the fixnum (1+ ,x)))
+@end lisp
+
+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:
+
+@lisp
+(my-1+ (+ 4 5))
+@end lisp
+
+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:
+
+@lisp
+(defmacro my-1+ (x)
+ `(the fixnum (1+ (the fixnum ,x))))
+@end lisp
+
+In this case, it would be stylistically preferable to change this
+macro back to a function and declare it inline.
+@c <!--FIXME: <xref>inline-expansion, once we crib the
+@c relevant text from the CMU CL manual.-->
+
+Some more subtle problems are caused by incorrect declarations that
+can't be detected at compile time. Consider this code:
+
+@lisp
+(do ((pos 0 (position #\a string :start (1+ pos))))
+ ((null pos))
+ (declare (fixnum pos))
+ ...)
+@end lisp
+
+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)} @footnote{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:
+
+@lisp
+(do ((pos 0 (position #\a string :start (1+ pos))))
+ ((null pos))
+ (let ((pos pos))
+ (declare (fixnum pos))
+ ...))
+@end lisp
+
+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.
+@c <!-- FIXME: <xref>ND-variables, once we crib the text from the
+@c CMU CL manual. -->
+
+@node Implementation Limitations, , Getting Existing Programs to Run, Handling of Types
+@comment node-name, next, previous, up
+@subsection Implementation Limitations
+
+
+Ideally, the compiler would consider @emph{all} type declarations to
+be assertions, so that adding type declarations to a program, no
+matter how incorrect they might be, would @emph{never} cause undefined
+behavior. As of SBCL version 0.8.1, the compiler is known to fall
+short of this goal in two areas:
+
+ @itemize
+
+@item
+@code{Proclaim}ed constraints on argument and result types of a
+function are supposed to be checked by the function. If the function
+type is proclaimed before function definition, type checks are
+inserted by the compiler, but the standard allows the reversed order,
+in which case the compiler will trust the declaration.
+
+@item
+The compiler cannot check types of an unknown number of values; if the
+number of generated values is unknown, but the number of consumed is
+known, only consumed values are checked.
+
+@item
+There are a few poorly characterized but apparently very uncommon
+situations where a type declaration in an unexpected location will be
+trusted and never checked by the compiler.
+
+@end itemize
+
+These are important bugs, but are not necessarily easy to fix, so they
+may, alas, remain in the system for a while.
+
+
+@node Compiler Policy, Open Coding and Inline Expansion, Handling of Types, The Compiler
+@comment node-name, next, previous, up
+@section Compiler Policy
+
+As of version 0.6.4, SBCL still uses most of the CMUCL code for
+compiler policy. The CMUCL code has many features and high-quality
+documentation, but the two unfortunately do not match. So this area of
+the compiler and its interface needs to be cleaned up. Meanwhile, here
+is some rudimentary documentation on the current behavior of the
+system.
+
+Compiler policy is controlled by the @code{optimize} declaration. The
+compiler supports the ANSI optimization qualities, and also an
+extension @code{sb-ext:inhibit-warnings}.
+
+Ordinarily, when the @code{speed} quality is high, the compiler emits
+notes to notify the programmer about its inability to apply various
+optimizations. Setting @code{sb-ext:inhibit-warnings} to a value at
+least as large as the @code{speed} quality inhibits this
+notification. This can be useful to suppress notes about code which is
+known to be unavoidably inefficient. (For example, the compiler issues
+notes about having to use generic arithmetic instead of fixnum
+arithmetic, which is not helpful for code which by design supports
+arbitrary-sized integers instead of being limited to fixnums.)
+
+@quotation
+Note: The basic functionality of the @code{optimize
+inhibit-warnings} extension will probably be supported in all future
+versions of the system, but it will probably be renamed when the
+compiler and its interface are cleaned up. The current name is
+misleading, because it mostly inhibits optimization notes, not
+warnings. And making it an optimization quality is misleading, because
+it shouldn't affect the resulting code at all. It may become a
+declaration identifier with a name like
+@code{sb-ext:inhibit-notes}, so that what's currently written.
+
+@lisp
+(declaim (optimize (sb-ext:inhibit-warnings 2)))
+@end lisp
+
+would become something like
+
+@lisp
+(declaim (sb-ext:inhibit-notes 2))
+@end lisp
+
+@end quotation
+
+In early versions of SBCL, a @code{speed} value of zero was used to
+enable byte compilation, but since version 0.7.0, SBCL only supports
+native compilation.
+
+When @code{safety} is zero, almost all runtime checking of types,
+array bounds, and so forth is suppressed.
+
+When @code{safety} is less than @code{speed}, any and all type checks
+may be suppressed. At some point in the past, CMUCL had a more nuanced
+interpretation of this (@pxref{Weakened Type Checking}). However, SBCL
+doesn't support that interpretation, and setting @code{safety} less
+than @code{speed} may have roughly the same effect as setting
+@code{safety} to zero.
+
+The value of @code{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 swapping.
+
+@c <!-- FIXME: old CMU CL compiler policy, should perhaps be adapted
+@c _ for SBCL. (Unfortunately, the CMU CL docs are out of sync with the
+@c _ CMU CL code, so adapting this requires not only reformatting
+@c _ the documentation, but rooting out code rot.)
+@c _
+@c _<sect2 id="compiler-policy"><title>Compiler Policy</1000
+@c _ INDEX {policy}{compiler}
+@c _ INDEX compiler policy
+@c _
+@c _<para>The policy is what tells the compiler <emphasis>how</emphasis> to
+@c _compile a program. This is logically (and often textually) distinct
+@c _from the program itself. Broad control of policy is provided by the
+@c _<parameter>optimize</parameter> declaration; other declarations and variables
+@c _control more specific aspects of compilation.
+@c _
+@c _\begin{comment}
+@c _* The Optimize Declaration::
+@c _* The Optimize-Interface Declaration::
+@c _\end{comment}
+@c _
+@c _%%\node The Optimize Declaration, The Optimize-Interface Declaration, Compiler Policy, Compiler Policy
+@c _\subsection{The Optimize Declaration}
+@c _\label{optimize-declaration}
+@c _\cindex{optimize declaration}
+@c _\cpsubindex{declarations}{\code{optimize}}
+@c _
+@c _The \code{optimize} declaration recognizes six different
+@c _\var{qualities}. The qualities are conceptually independent aspects
+@c _of program performance. In reality, increasing one quality tends to
+@c _have adverse effects on other qualities. The compiler compares the
+@c _relative values of qualities when it needs to make a trade-off; i.e.,
+@c _if \code{speed} is greater than \code{safety}, then improve speed at
+@c _the cost of safety.
+@c _
+@c _The default for all qualities (except \code{debug}) is \code{1}.
+@c _Whenever qualities are equal, ties are broken according to a broad
+@c _idea of what a good default environment is supposed to be. Generally
+@c _this downplays \code{speed}, \code{compile-speed} and \code{space} in
+@c _favor of \code{safety} and \code{debug}. Novice and casual users
+@c _should stick to the default policy. Advanced users often want to
+@c _improve speed and memory usage at the cost of safety and
+@c _debuggability.
+@c _
+@c _If the value for a quality is \code{0} or \code{3}, then it may have a
+@c _special interpretation. A value of \code{0} means ``totally
+@c _unimportant'', and a \code{3} means ``ultimately important.'' These
+@c _extreme optimization values enable ``heroic'' compilation strategies
+@c _that are not always desirable and sometimes self-defeating.
+@c _Specifying more than one quality as \code{3} is not desirable, since
+@c _it doesn't tell the compiler which quality is most important.
+@c _
+@c _
+@c _These are the optimization qualities:
+@c _\begin{Lentry}
+@c _
+@c _\item[\code{speed}] \cindex{speed optimization quality}How fast the
+@c _ program should is run. \code{speed 3} enables some optimizations
+@c _ that hurt debuggability.
+@c _
+@c _\item[\code{compilation-speed}] \cindex{compilation-speed optimization
+@c _ quality}How fast the compiler should run. Note that increasing
+@c _ this above \code{safety} weakens type checking.
+@c _
+@c _\item[\code{space}] \cindex{space optimization quality}How much space
+@c _ the compiled code should take up. Inline expansion is mostly
+@c _ inhibited when \code{space} is greater than \code{speed}. A value
+@c _ of \code{0} enables indiscriminate inline expansion. Wide use of a
+@c _ \code{0} value is not recommended, as it may waste so much space
+@c _ that run time is slowed. \xlref{inline-expansion} for a discussion
+@c _ of inline expansion.
+@c _
+@c _\item[\code{debug}] \cindex{debug optimization quality}How debuggable
+@c _ the program should be. The quality is treated differently from the
+@c _ other qualities: each value indicates a particular level of debugger
+@c _ information; it is not compared with the other qualities.
+@c _ \xlref{debugger-policy} for more details.
+@c _
+@c _\item[\code{safety}] \cindex{safety optimization quality}How much
+@c _ error checking should be done. If \code{speed}, \code{space} or
+@c _ \code{compilation-speed} is more important than \code{safety}, then
+@c _ type checking is weakened (\pxlref{weakened-type-checks}). If
+@c _ \code{safety} if \code{0}, then no run time error checking is done.
+@c _ In addition to suppressing type checks, \code{0} also suppresses
+@c _ argument count checking, unbound-symbol checking and array bounds
+@c _ checks.
+@c _
+@c _\item[\code{extensions:inhibit-warnings}] \cindex{inhibit-warnings
+@c _ optimization quality}This is a CMU extension that determines how
+@c _ little (or how much) diagnostic output should be printed during
+@c _ compilation. This quality is compared to other qualities to
+@c _ determine whether to print style notes and warnings concerning those
+@c _ qualities. If \code{speed} is greater than \code{inhibit-warnings},
+@c _ then notes about how to improve speed will be printed, etc. The
+@c _ default value is \code{1}, so raising the value for any standard
+@c _ quality above its default enables notes for that quality. If
+@c _ \code{inhibit-warnings} is \code{3}, then all notes and most
+@c _ non-serious warnings are inhibited. This is useful with
+@c _ \code{declare} to suppress warnings about unavoidable problems.
+@c _\end{Lentry}
+@c _
+@c _%%\node The Optimize-Interface Declaration, , The Optimize Declaration, Compiler Policy
+@c _\subsection{The Optimize-Interface Declaration}
+@c _\label{optimize-interface-declaration}
+@c _\cindex{optimize-interface declaration}
+@c _\cpsubindex{declarations}{\code{optimize-interface}}
+@c _
+@c _The \code{extensions:optimize-interface} declaration is identical in
+@c _syntax to the \code{optimize} declaration, but it specifies the policy
+@c _used during compilation of code the compiler automatically generates
+@c _to check the number and type of arguments supplied to a function. It
+@c _is useful to specify this policy separately, since even thoroughly
+@c _debugged functions are vulnerable to being passed the wrong arguments.
+@c _The \code{optimize-interface} declaration can specify that arguments
+@c _should be checked even when the general \code{optimize} policy is
+@c _unsafe.
+@c _
+@c _Note that this argument checking is the checking of user-supplied
+@c _arguments to any functions defined within the scope of the
+@c _declaration, \code{not} the checking of arguments to \llisp{}
+@c _primitives that appear in those definitions.
+@c _
+@c _The idea behind this declaration is that it allows the definition of
+@c _functions that appear fully safe to other callers, but that do no
+@c _internal error checking. Of course, it is possible that arguments may
+@c _be invalid in ways other than having incorrect type. Functions
+@c _compiled unsafely must still protect themselves against things like
+@c _user-supplied array indices that are out of bounds and improper lists.
+@c _See also the \kwd{context-declarations} option to
+@c _\macref{with-compilation-unit}.
+@c _
+@c _(end of section on compiler policy)
+@c _-->
+
+
+@node Open Coding and Inline Expansion, , Compiler Policy, The Compiler
+@comment node-name, next, previous, up
+@section Open Coding and Inline Expansion
+@cindex Open-coding
+@cindex inline expansion
+@cindex static functions
+
+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.
+
+@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 compiler policy, @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
+
+@lisp
+(nthcdr 4 foobar)
+@end lisp
+
+might turn into
+
+@lisp
+(cdr (cdr (cdr (cdr foobar))))
+@end lisp
+
+or even
+
+@lisp
+(do ((i 0 (1+ i))
+ (list foobar (cdr foobar)))
+ ((= i 4) list))
+@end lisp
+
+If @code{nth} is closed coded, then
+
+@lisp
+(nth x l)
+@end lisp
+
+might stay the same, or turn into something like
+
+@lisp
+(car (nthcdr x l))
+@end lisp
+
+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.
+
--- /dev/null
+@node The Debugger, Efficiency, The Compiler, Top
+@comment node-name, next, previous, up
+@chapter The Debugger
+@cindex Debugger
+
+The SBCL debugger (as the CMUCL debugger it was derived from) has very
+good support for source-level debugging of compiled code. Although
+some other debuggers allow access of variables by name, this seems to
+be the first Lisp debugger that:
+
+@itemize
+
+@item
+Tells you when a variable doesn't have a value because it hasn't been
+initialized yet or has already been deallocated, or
+
+@item
+Can display the precise source location corresponding to a code
+location in the debugged program.
+
+@end itemize
+
+These features allow the debugging of compiled code to be made almost
+indistinguishable from interpreted code debugging.
+
+
+@menu
+* Starting the Debugger::
+* The Debugger Command Loop::
+* Controlling Printing in the Debugger::
+* Stack Frames::
+* Variable Access::
+* Source Location Printing::
+* Debugger Policy Control::
+* Exiting Commands::
+* Information Commands::
+* Function Tracing::
+@end menu
+
+@node Starting the Debugger, The Debugger Command Loop, The Debugger, The Debugger
+@comment node-name, next, previous, up
+@section Starting the Debugger
+
+The debugger is an interactive command loop that allows a user to examine
+the function call stack. The debugger is invoked when:
+
+@itemize
+
+@item
+A @code{serious-condition} is signaled, and it is not handled, or
+
+@item
+@code{error} is called, and the condition it signals is not handled,
+or
+
+@item
+the debugger is explicitly entered with the Lisp @code{break} or
+@code{debug} functions.
+
+@end itemize
+
+When you enter the TTY debugger, it looks something like this:
+
+@example
+debugger invoked on a TYPE-ERROR in thread 11184:
+ The value 3 is not of type LIST.
+restarts (invokable by number or by possibly-abbreviated name):
+ 0: [ABORT ] Reduce debugger level (leaving debugger, returning to toplevel).
+ 1: [TOPLEVEL] Restart at toplevel READ/EVAL/PRINT loop.
+(CAR 1 3)[:EXTERNAL]
+0]
+@end example
+
+The first group of lines describe what the error was that put us in
+the debugger. In this case @code{car} was called on @code{3}. After
+@samp{restarts} is a list of all the ways that we can restart
+execution after this error. In this case, both options return to
+top-level. After printing its banner, the debugger prints the current
+frame and the debugger prompt.
+
+
+@node The Debugger Command Loop, Controlling Printing in the Debugger, Starting the Debugger, The Debugger
+@comment node-name, next, previous, up
+@section The Debugger Command Loop
+@cindex Evaluation, in the debugger
+
+The debugger is an interactive read-eval-print loop much like the normal
+top-level, but some symbols are interpreted as debugger commands instead
+of being evaluated. A debugger command starts with the symbol name of
+the command, possibly followed by some arguments on the same line. Some
+commands prompt for additional input. Debugger commands can be
+abbreviated by any unambiguous prefix: @command{help} can be typed as
+@samp{h}, @samp{he}, etc. For convenience, some commands have
+ambiguous one-letter abbreviations: @samp{f} for @command{frame}.
+
+The package is not significant in debugger commands; any symbol with the
+name of a debugger command will work. If you want to show the value of
+a variable that happens also to be the name of a debugger command, you
+can use the @command{list-locals} command or the @code{sb-debug:var}
+function, or you can wrap the variable in a @code{progn} to hide it from
+the command loop.
+
+The debugger prompt is ``@code{@var{frame}]}'', where @var{frame} is
+the number of the current frame. Frames are numbered starting from
+zero at the top (most recent call), increasing down to the bottom.
+The current frame is the frame that commands refer to. The current
+frame also provides the lexical environment for evaluation of
+non-command forms.
+
+ The debugger evaluates forms in the lexical environment of the
+functions being debugged. The debugger can only access variables.
+You can't @code{go} or @code{return-from} into a function, and you
+can't call local functions. Special variable references are evaluated
+with their current value (the innermost binding around the debugger
+invocation) -- you don't get the value that the special had in the
+current frame. For more information on debugger variable access, see
+@ref{Variable Access}.
+
+
+@node Controlling Printing in the Debugger, Stack Frames, The Debugger Command Loop, The Debugger
+@comment node-name, next, previous, up
+@section Controlling Printing in the Debugger
+
+In the debugger, it is possible to override the printing behaviour of
+the REPL.
+
+@defvr {Variable} *debug-print-variable-alist*
+
+An association list describing new bindings for special variables
+(typically *PRINT-FOO* variables) to be used within the debugger, e.g.
+@lisp
+((*PRINT-LENGTH* . 10) (*PRINT-LEVEL* . 6) (*PRINT-PRETTY* . NIL))
+@end lisp
+The variables in the @code{car} position 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. @c FIXME: is this correct?
+@code{*debug-print-variable-alist*} does not contain any bindings
+initially.
+
+@end defvr
+
+@node Stack Frames, Variable Access, Controlling Printing in the Debugger, The Debugger
+@comment node-name, next, previous, up
+@section Stack Frames
+@cindex Stack frames
+
+A @dfn{stack frame} is the run-time representation of a call to a
+function; the frame stores the state that a function needs to remember
+what it is doing. Frames have:
+
+@itemize
+
+@item
+@dfn{Variables} (@pxref{Variable Access}), which are the values being operated
+on, and
+
+@item
+@dfn{Arguments} to the call (which are really just particularly
+interesting variables), and
+
+@item
+A current location (@pxref{Source Location Printing}), which is the place in
+the program where the function was running when it stopped to call
+another function, or because of an interrupt or error.
+
+@end itemize
+
+
+@menu
+* Stack Motion::
+* How Arguments are Printed::
+* Function Names::
+* Funny Frames::
+* Debug Tail Recursion::
+* Unknown Locations and Interrupts::
+@end menu
+
+@node Stack Motion, How Arguments are Printed, Stack Frames, Stack Frames
+@comment node-name, next, previous, up
+@subsection Stack Motion
+
+These commands move to a new stack frame and print the name of the
+function and the values of its arguments in the style of a Lisp
+function call:
+
+@deffn {Debugger Command} up
+Move up to the next higher frame. More recent function calls are
+considered to be higher on the stack.
+@end deffn
+
+@deffn {Debugger Command} down
+Move down to the next lower frame.
+@end deffn
+
+@deffn {Debugger Command} top
+Move to the highest frame, that is, the frame where the debugger was
+entered.
+@end deffn
+
+@deffn {Debugger Command} bottom
+Move to the lowest frame.
+@end deffn
+
+@deffn {Debugger Command} frame [@var{n}]
+Move to the frame with the specified number. Prompts for the number if not
+supplied. The frame with number 0 is the frame where the debugger
+was entered.
+@end deffn
+
+
+@node How Arguments are Printed, Function Names, Stack Motion, Stack Frames
+@comment node-name, next, previous, up
+@subsection How Arguments are Printed
+
+A frame is printed to look like a function call, but with the actual
+argument values in the argument positions. So the frame for this call
+in the source:
+
+@lisp
+(myfun (+ 3 4) 'a)
+@end lisp
+
+would look like this:
+
+@example
+(MYFUN 7 A)
+@end example
+
+All keyword and optional arguments are displayed with their actual
+values; if the corresponding argument was not supplied, the value will
+be the default. So this call:
+
+@lisp
+(subseq "foo" 1)
+@end lisp
+
+would look like this:
+
+@example
+(SUBSEQ "foo" 1 3)
+@end example
+
+And this call:
+
+@lisp
+(string-upcase "test case")
+@end lisp
+
+would look like this:
+
+@example
+(STRING-UPCASE "test case" :START 0 :END NIL)
+@end example
+
+The arguments to a function call are displayed by accessing the
+argument variables. Although those variables are initialized to the
+actual argument values, they can be set inside the function; in this
+case the new value will be displayed.
+
+@code{&rest} arguments are handled somewhat differently. The value of
+the rest argument variable is displayed as the spread-out arguments to
+the call, so:
+
+@lisp
+(format t "~A is a ~A." "This" 'test)
+@end lisp
+
+would look like this:
+
+@example
+(FORMAT T "~A is a ~A." "This" 'TEST)
+@end example
+
+Rest arguments cause an exception to the normal display of keyword
+arguments in functions that have both @code{&rest} and @code{&key}
+arguments. In this case, the keyword argument variables are not
+displayed at all; the rest arg is displayed instead. So for these
+functions, only the keywords actually supplied will be shown, and the
+values displayed will be the argument values, not values of the
+(possibly modified) variables.
+
+If the variable for an argument is never referenced by the function,
+it will be deleted. The variable value is then unavailable, so the
+debugger prints @samp{#<unused-arg>} instead of the value. Similarly,
+if for any of a number of reasons the value of the variable is
+unavailable or not known to be available (@pxref{Variable Access}),
+then @samp{#<unavailable-arg>} will be printed instead of the argument
+value.
+
+Printing of argument values is controlled by
+@code{*debug-print-variable-alist*}. @xref{Controlling Printing in
+the Debugger}.
+
+
+@node Function Names, Funny Frames, How Arguments are Printed, Stack Frames
+@comment node-name, next, previous, up
+@subsection Function Names
+
+If a function is defined by @code{defun}, @code{labels}, or
+@code{flet}, then the debugger will print the actual function name
+after the open parenthesis, like:
+
+@example
+(STRING-UPCASE "test case" :START 0 :END NIL)
+((SETF AREF) #\a "for" 1)
+@end example
+
+Otherwise, the function name is a string, and will be printed in
+quotes:
+
+@example
+("DEFUN MYFUN" BAR)
+("DEFMACRO DO" (DO ((I 0 (1+ I))) ((= I 13))) NIL)
+("SETQ *GC-NOTIFY-BEFORE*")
+@end example
+
+This string name is derived from the @code{def@var{mumble}} form
+that encloses or expanded into the lambda, or the outermost enclosing
+form if there is no @code{def@var{mumble}}.
+
+
+@node Funny Frames, Debug Tail Recursion, Function Names, Stack Frames
+@comment node-name, next, previous, up
+@subsection Funny Frames
+@cindex External entry points
+@cindex Entry points, external
+@cindex Block compilation, debugger implications
+@cindex External, stack frame kind
+@cindex Optional, stack frame kind
+@cindex Cleanup, stack frame kind
+
+Sometimes the evaluator introduces new functions that are used to
+implement a user function, but are not directly specified in the
+source. The main place this is done is for checking argument type and
+syntax. Usually these functions do their thing and then go away, and
+thus are not seen on the stack in the debugger. But when you get some
+sort of error during lambda-list processing, you end up in the
+debugger on one of these funny frames.
+
+These funny frames are flagged by printing
+``@code{[@var{keyword}]}'' after the parentheses. For example,
+this call:
+
+@lisp
+(car 'a 'b)
+@end lisp
+
+will look like this:
+
+@example
+(CAR 2 A)[:EXTERNAL]
+@end example
+
+And this call:
+
+@lisp
+(string-upcase "test case" :end)
+@end lisp
+
+would look like this:
+
+@example
+("SB!INT:&MORE processing" "test case" 1053984 1)[:OPTIONAL]
+@end example
+
+As you can see, these frames have only a vague resemblance to the
+original call. Fortunately, the error message displayed when you
+enter the debugger will usually tell you what problem is (in these
+cases, too many arguments and odd keyword arguments.) Also, if you go
+down the stack to the frame for the calling function, you can display
+the original source. @xref{Source Location Printing}.
+
+@c FIXME: is the block-compilation part correct for SBCL?
+
+With recursive or block compiled functions, an @code{:EXTERNAL} frame
+may appear before the frame representing the first call to the
+recursive function or entry to the compiled block. This is a
+consequence of the way the compiler does block compilation: there is
+nothing odd with your program. You will also see @code{:CLEANUP}
+frames during the execution of @code{unwind-protect} cleanup
+code. Note that inline expansion and open-coding affect what frames
+are present in the debugger, see @ref{Debugger Policy Control}.
+@comment FIXME: link here to section about open coding once it exists.
+@c @ref{open-coding}
+
+
+@node Debug Tail Recursion, Unknown Locations and Interrupts, Funny Frames, Stack Frames
+@comment node-name, next, previous, up
+@subsection Debug Tail Recursion
+@cindex Tail recursion
+@cindex Recursion, tail
+
+Both the compiler and the interpreter are ``properly tail recursive.''
+If a function call is in a tail-recursive position, the stack frame
+will be deallocated @emph{at the time of the call}, rather than after
+the call returns. Consider this backtrace:
+
+@example
+(BAR ...)
+(FOO ...)
+@end example
+
+Because of tail recursion, it is not necessarily the case that
+@code{FOO} directly called @code{BAR}. It may be that @code{FOO}
+called some other function @code{FOO2} which then called @code{BAR}
+tail-recursively, as in this example:
+
+@lisp
+(defun foo ()
+ ...
+ (foo2 ...)
+ ...)
+
+(defun foo2 (...)
+ ...
+ (bar ...))
+
+(defun bar (...)
+ ...)
+@end lisp
+
+Usually the elimination of tail-recursive frames makes debugging more
+pleasant, since theses frames are mostly uninformative. If there is
+any doubt about how one function called another, it can usually be
+eliminated by finding the source location in the calling frame.
+@xref{Source Location Printing}.
+
+The elimination of tail-recursive frames can be prevented by disabling
+tail-recursion optimization, which happens when the @code{debug}
+optimization quality is greater than @code{2}.
+@xref{Debugger Policy Control}.
+
+@comment FIXME: reinstate this link once the chapter is in the manual.
+@c For a more thorough discussion of tail recursion, @ref{tail-recursion}.
+
+
+@node Unknown Locations and Interrupts, , Debug Tail Recursion, Stack Frames
+@comment node-name, next, previous, up
+@subsection Unknown Locations and Interrupts
+@cindex Unknown code locations
+@cindex Locations, unknown
+@cindex Interrupts
+@cindex Errors, run-time
+
+The debugger operates using special debugging information attached to
+the compiled code. This debug information tells the debugger what it
+needs to know about the locations in the code where the debugger can
+be invoked. If the debugger somehow encounters a location not
+described in the debug information, then it is said to be
+@dfn{unknown}. If the code location for a frame is unknown, then some
+variables may be inaccessible, and the source location cannot be
+precisely displayed.
+
+There are three reasons why a code location could be unknown:
+
+@itemize
+
+@item
+There is inadequate debug information due to the value of the @code{debug}
+optimization quality. @xref{Debugger Policy Control}.
+
+@item
+The debugger was entered because of an interrupt such as @key{C-c}.
+
+@item
+A hardware error such as ``@samp{bus error}'' occurred in code that was
+compiled unsafely due to the value of the @code{safety} optimization
+quality.
+@comment FIXME: reinstate link when section on optimize qualities exists.
+@c @xref{optimize-declaration}.
+
+@end itemize
+
+In the last two cases, the values of argument variables are
+accessible, but may be incorrect. For more details on when variable
+values are accessible, @ref{Variable Value Availability}.
+
+It is possible for an interrupt to happen when a function call or
+return is in progress. The debugger may then flame out with some
+obscure error or insist that the bottom of the stack has been reached,
+when the real problem is that the current stack frame can't be
+located. If this happens, return from the interrupt and try again.
+
+
+@node Variable Access, Source Location Printing, Stack Frames, The Debugger
+@comment node-name, next, previous, up
+@section Variable Access
+@cindex Debug variables
+@cindex Variables, debugger access
+
+There are two ways to access the current frame's local variables in
+the debugger: @command{list-locals} and @code{sb-debug:var}.
+
+The debugger doesn't really understand lexical scoping; it has just
+one namespace for all the variables in the current stack frame. If a
+symbol is the name of multiple variables in the same function, then
+the reference appears ambiguous, even though lexical scoping specifies
+which value is visible at any given source location. If the scopes of
+the two variables are not nested, then the debugger can resolve the
+ambiguity by observing that only one variable is accessible.
+
+When there are ambiguous variables, the evaluator assigns each one a
+small integer identifier. The @code{sb-debug:var} function uses this
+identifier to distinguish between ambiguous variables. The
+@command{list-locals} command prints the identifier. In the
+following example, there are two variables named @code{X}. The first
+one has identifier 0 (which is not printed), the second one has
+identifier 1.
+
+@example
+X = 1
+X#1 = 2
+@end example
+
+@deffn {Debugger Command} list-locals [@var{prefix}]
+This command prints the name and value of all variables in the current
+frame whose name has the specified @var{prefix}. @var{prefix} may be
+a string or a symbol. If no @var{prefix} is given, then all available
+variables are printed. If a variable has a potentially ambiguous
+name, then the name is printed with a ``@code{#@var{identifier}}''
+suffix, where @var{identifier} is the small integer used to make the
+name unique.
+@end deffn
+
+@defun sb-debug:var @var{name} &optional @var{identifier}
+This function returns the value of the variable in the current frame
+with the specified @var{name}. If supplied, @var{identifier}
+determines which value to return when there are ambiguous variables.
+
+When @var{name} is a symbol, it is interpreted as the symbol name of
+the variable, i.e. the package is significant. If @var{name} is an
+uninterned symbol (gensym), then return the value of the uninterned
+variable with the same name. If @var{name} is a string,
+@code{sb-debug:var} interprets it as the prefix of a variable name
+that must unambiguously complete to the name of a valid variable.
+
+@var{identifier} is used to disambiguate the variable name; use
+@command{list-locals} to find out the identifiers.
+@end defun
+
+
+@menu
+* Variable Value Availability::
+* Note On Lexical Variable Access::
+@end menu
+
+@node Variable Value Availability, Note On Lexical Variable Access, Variable Access, Variable Access
+@comment node-name, next, previous, up
+@subsection Variable Value Availability
+@cindex Availability of debug variables
+@cindex Validity of debug variables
+@cindex Debug optimization quality
+
+The value of a variable may be unavailable to the debugger in portions
+of the program where Lisp says that the variable is defined. If a
+variable value is not available, the debugger will not let you read or
+write that variable. With one exception, the debugger will never
+display an incorrect value for a variable. Rather than displaying
+incorrect values, the debugger tells you the value is unavailable.
+
+The one exception is this: if you interrupt (e.g., with @key{C-c}) or
+if there is an unexpected hardware error such as ``@samp{bus error}''
+(which should only happen in unsafe code), then the values displayed
+for arguments to the interrupted frame might be
+incorrect.@footnote{Since the location of an interrupt or hardware
+error will always be an unknown location, non-argument variable values
+will never be available in the interrupted frame. @xref{Unknown
+Locations and Interrupts}.} This exception applies only to the
+interrupted frame: any frame farther down the stack will be fine.
+
+The value of a variable may be unavailable for these reasons:
+
+@itemize
+
+@item
+The value of the @code{debug} optimization quality may have omitted debug
+information needed to determine whether the variable is available.
+Unless a variable is an argument, its value will only be available when
+@code{debug} is at least @code{2}.
+
+@item
+The compiler did lifetime analysis and determined that the value was no longer
+needed, even though its scope had not been exited. Lifetime analysis is
+inhibited when the @code{debug} optimization quality is @code{3}.
+
+@item
+The variable's name is an uninterned symbol (gensym). To save space, the
+compiler only dumps debug information about uninterned variables when the
+@code{debug} optimization quality is @code{3}.
+
+@item
+The frame's location is unknown (@pxref{Unknown Locations and
+Interrupts}) because the debugger was entered due to an interrupt or
+unexpected hardware error. Under these conditions the values of
+arguments will be available, but might be incorrect. This is the
+exception mentioned above.
+
+@item
+The variable (or the code referencing it) was optimized out
+of existence. Variables with no reads are always optimized away. The
+degree to which the compiler deletes variables will depend on the
+value of the @code{compilation-speed} optimization quality, but most
+source-level optimizations are done under all compilation policies.
+
+@item
+The variable is never set and its definition looks like
+@lisp
+(LET ((var1 var2))
+ ...)
+@end lisp
+In this case, @code{var1} is substituted with @code{var2}.
+
+@item
+The variable is never set and is referenced exactly once. In this
+case, the reference is substituted with the variable initial value.
+
+@end itemize
+
+Since it is especially useful to be able to get the arguments to a
+function, argument variables are treated specially when the
+@code{speed} optimization quality is less than @code{3} and the
+@code{debug} quality is at least @code{1}. With this compilation
+policy, the values of argument variables are almost always available
+everywhere in the function, even at unknown locations. For
+non-argument variables, @code{debug} must be at least @code{2} for
+values to be available, and even then, values are only available at
+known locations.
+
+
+@node Note On Lexical Variable Access, , Variable Value Availability, Variable Access
+@comment node-name, next, previous, up
+@subsection Note On Lexical Variable Access
+
+When the debugger command loop establishes variable bindings for
+available variables, these variable bindings have lexical scope and
+dynamic extent.@footnote{The variable bindings are actually created
+using the Lisp @code{symbol-macrolet} special form.} You can close
+over them, but such closures can't be used as upward funargs.
+
+You can also set local variables using @code{setq}, but if the
+variable was closed over in the original source and never set, then
+setting the variable in the debugger may not change the value in all
+the functions the variable is defined in. Another risk of setting
+variables is that you may assign a value of a type that the compiler
+proved the variable could never take on. This may result in bad
+things happening.
+
+
+@node Source Location Printing, Debugger Policy Control, Variable Access, The Debugger
+@comment node-name, next, previous, up
+@section Source Location Printing
+@cindex Source location printing, debugger
+
+One of the debugger's capabilities is source level debugging of
+compiled code. These commands display the source location for the
+current frame:
+
+@deffn {Debugger Command} source [@var{context}]
+This command displays the file that the current frame's function was
+defined from (if it was defined from a file), and then the source form
+responsible for generating the code that the current frame was
+executing. If @var{context} is specified, then it is an integer
+specifying the number of enclosing levels of list structure to print.
+@end deffn
+
+The source form for a location in the code is the innermost list present
+in the original source that encloses the form responsible for generating
+that code. If the actual source form is not a list, then some enclosing
+list will be printed. For example, if the source form was a reference
+to the variable @code{*some-random-special*}, then the innermost
+enclosing evaluated form will be printed. Here are some possible
+enclosing forms:
+
+@lisp
+(let ((a *some-random-special*))
+ ...)
+
+(+ *some-random-special* ...)
+@end lisp
+
+If the code at a location was generated from the expansion of a macro
+or a source-level compiler optimization, then the form in the original
+source that expanded into that code will be printed. Suppose the file
+@file{/usr/me/mystuff.lisp} looked like this:
+
+@lisp
+(defmacro mymac ()
+ '(myfun))
+
+(defun foo ()
+ (mymac)
+ ...)
+@end lisp
+
+If @code{foo} has called @code{myfun}, and is waiting for it to
+return, then the @command{source} command would print:
+
+@example
+; File: /usr/me/mystuff.lisp
+
+(MYMAC)
+@end example
+
+Note that the macro use was printed, not the actual function call form,
+@code{(myfun)}.
+
+If enclosing source is printed by giving an argument to
+@command{source} or @command{vsource}, then the actual source form is
+marked by wrapping it in a list whose first element is
+@samp{#:***HERE***}. In the previous example, @code{source 1} would
+print:
+
+@example
+; File: /usr/me/mystuff.lisp
+
+(DEFUN FOO ()
+ (#:***HERE***
+ (MYMAC))
+ ...)
+@end example
+
+
+@menu
+* How the Source is Found::
+* Source Location Availability::
+@end menu
+
+@node How the Source is Found, Source Location Availability, Source Location Printing, Source Location Printing
+@comment node-name, next, previous, up
+@subsection How the Source is Found
+
+If the code was defined from Lisp by @code{compile} or
+@code{eval}, then the source can always be reliably located. If the
+code was defined from a @file{fasl} file created by
+@code{compile-file}, then the debugger gets the source forms it
+prints by reading them from the original source file. This is a
+potential problem, since the source file might have moved or changed
+since the time it was compiled.
+
+The source file is opened using the @code{truename} of the source file
+pathname originally given to the compiler. This is an absolute pathname
+with all logical names and symbolic links expanded. If the file can't
+be located using this name, then the debugger gives up and signals an
+error.
+
+If the source file can be found, but has been modified since the time it was
+compiled, the debugger prints this warning:
+
+@example
+; File has been modified since compilation:
+; @var{filename}
+; Using form offset instead of character position.
+@end example
+
+where @var{filename} is the name of the source file. It then proceeds
+using a robust but not foolproof heuristic for locating the source.
+This heuristic works if:
+
+@itemize
+
+@item
+No top-level forms before the top-level form containing the source
+have been added or deleted, and
+
+@item
+The top-level form containing the source has not been modified much.
+(More precisely, none of the list forms beginning before the source
+form have been added or deleted.)
+
+@end itemize
+
+If the heuristic doesn't work, the displayed source will be wrong, but will
+probably be near the actual source. If the ``shape'' of the top-level form in
+the source file is too different from the original form, then an error will be
+signaled. When the heuristic is used, the the source location commands are
+noticeably slowed.
+
+Source location printing can also be confused if (after the source was
+compiled) a read-macro you used in the code was redefined to expand
+into something different, or if a read-macro ever returns the same
+@code{eq} list twice. If you don't define read macros and don't use
+@code{##} in perverted ways, you don't need to worry about this.
+
+
+@node Source Location Availability, , How the Source is Found, Source Location Printing
+@comment node-name, next, previous, up
+@subsection Source Location Availability
+@cindex Debug optimization quality
+@cindex Block, basic
+@cindex Block, start location
+
+Source location information is only available when the @code{debug}
+optimization quality is at least @code{2}. If source location
+information is unavailable, the source commands will give an error
+message.
+
+If source location information is available, but the source location
+is unknown because of an interrupt or unexpected hardware error
+(@pxref{Unknown Locations and Interrupts}), then the command will
+print:
+
+@example
+Unknown location: using block start.
+@end example
+
+and then proceed to print the source location for the start of the
+@emph{basic block} enclosing the code location. It's a bit
+complicated to explain exactly what a basic block is, but here are
+some properties of the block start location:
+
+@itemize
+
+@item The block start location may be the same as the true location.
+
+@item The block start location will never be later in the the
+program's flow of control than the true location.
+
+@item No conditional control structures (such as @code{if},
+@code{cond}, @code{or}) will intervene between the block start and the
+true location (but note that some conditionals present in the original
+source could be optimized away.) Function calls @emph{do not} end
+basic blocks.
+
+@item The head of a loop will be the start of a block.
+
+@item The programming language concept of ``block structure'' and the
+Lisp @code{block} special form are totally unrelated to the compiler's
+basic block.
+
+@end itemize
+
+In other words, the true location lies between the printed location and the
+next conditional (but watch out because the compiler may have changed the
+program on you.)
+
+
+@node Debugger Policy Control, Exiting Commands, Source Location Printing, The Debugger
+@comment node-name, next, previous, up
+@section Debugger Policy Control
+@cindex Policy, debugger
+@cindex Debug optimization quality
+@cindex Optimize declaration
+@cindex Inline expansion
+@cindex Semi-inline expansion
+
+The compilation policy specified by @code{optimize} declarations
+affects the behavior seen in the debugger. The @code{debug} quality
+directly affects the debugger by controlling the amount of debugger
+information dumped. Other optimization qualities have indirect but
+observable effects due to changes in the way compilation is done.
+
+Unlike the other optimization qualities (which are compared in relative value
+to evaluate tradeoffs), the @code{debug} optimization quality is directly
+translated to a level of debug information. This absolute interpretation
+allows the user to count on a particular amount of debug information being
+available even when the values of the other qualities are changed during
+compilation. These are the levels of debug information that correspond to the
+values of the @code{debug} quality:
+
+@table @code
+
+@item 0
+Only the function name and enough information to allow the stack to
+be parsed.
+
+@item > 0
+Any level greater than @code{0} gives level @code{0} plus all argument
+variables. Values will only be accessible if the argument variable is
+never set and @code{speed} is not @code{3}. SBCL allows any real
+value for optimization qualities. It may be useful to specify
+@code{0.5} to get backtrace argument display without argument
+documentation.
+
+@item 1
+Level @code{1} provides argument documentation (printed arglists) and
+derived argument/result type information. This makes @code{describe}
+more informative, and allows the compiler to do compile-time argument
+count and type checking for any calls compiled at run-time. This is
+the default.
+
+@item 2
+Level @code{1} plus all interned local variables, source location
+information, and lifetime information that tells the debugger when
+arguments are available (even when @code{speed} is @code{3} or the
+argument is set).
+
+@item > 2
+Any level greater than @code{2} gives level @code{2} and in addition
+disables tail-call optimization, so that the backtrace will contain
+frames for all invoked functions, even those in tail positions.
+
+@item 3
+Level @code{2} plus all uninterned variables. In addition, lifetime
+analysis is disabled (even when @code{speed} is @code{3}), ensuring
+that all variable values are available at any known location within
+the scope of the binding. This has a speed penalty in addition to the
+obvious space penalty.
+
+@item > (max speed space)
+If @code{debug} is greater than both @code{speed} and @code{space},
+the command @command{return} can be used to continue execution by
+returning a value from the current stack frame.
+
+@end table
+
+As you can see, if the @code{speed} quality is @code{3}, debugger performance is
+degraded. This effect comes from the elimination of argument variable
+special-casing (@pxref{Variable Value Availability}). Some degree of
+speed/debuggability tradeoff is unavoidable, but the effect is not too drastic
+when @code{debug} is at least @code{2}.
+
+In addition to @code{inline} and @code{notinline} declarations, the
+relative values of the @code{speed} and @code{space} qualities also
+change whether functions are inline expanded.
+@comment FIXME: link to section about inline expansion when it exists
+@c (\pxlref{inline-expansion}.)
+If a function is inline expanded, then
+there will be no frame to represent the call, and the arguments will
+be treated like any other local variable. Functions may also be
+``semi-inline'', in which case there is a frame to represent the call,
+but the call is to an optimized local version of the function, not to
+the original function.
+
+
+@node Exiting Commands, Information Commands, Debugger Policy Control, The Debugger
+@comment node-name, next, previous, up
+@section Exiting Commands
+
+These commands get you out of the debugger.
+
+@deffn {Debugger Command} toplevel
+Throw to top level.
+@end deffn
+
+@deffn {Debugger Command} restart [@var{n}]
+Invokes the @var{n}th restart case as displayed by the @code{error}
+command. If @var{n} is not specified, the available restart cases are
+reported.
+@end deffn
+
+@deffn {Debugger Command} continue
+Calls @code{continue} on the condition given to @code{debug}. If there is no
+restart case named @var{continue}, then an error is signaled.
+@end deffn
+
+@deffn {Debugger Command} abort
+Calls @code{abort} on the condition given to @code{debug}. This is
+useful for popping debug command loop levels or aborting to top level,
+as the case may be.
+@end deffn
+
+@deffn {Debugger Command} return @var{value}
+Returns @var{value} from the current stack frame. This command is
+available when the @code{debug} optimization quality is greater than
+both @code{speed} and @code{space}. Care must be taken that the value
+is of the same type as SBCL expects the stack frame to return.
+@end deffn
+
+
+@node Information Commands, Function Tracing, Exiting Commands, The Debugger
+@comment node-name, next, previous, up
+@section Information Commands
+
+Most of these commands print information about the current frame or
+function, but a few show general information.
+
+@deffn {Debugger Command} help
+@deffnx {Debugger Command} ?
+Displays a synopsis of debugger commands.
+@end deffn
+
+@deffn {Debugger Command} describe
+Calls @code{describe} on the current function and displays the number of
+local variables.
+@end deffn
+
+@deffn {Debugger Command} print
+Displays the current function call as it would be displayed by moving to
+this frame.
+@end deffn
+
+@deffn {Debugger Command} error
+Prints the condition given to @code{invoke-debugger} and the active
+proceed cases.
+@end deffn
+
+@deffn {Debugger Command} backtrace [@var{n}]
+Displays all the frames from the current to the bottom. Only shows
+@var{n} frames if specified. The printing is controlled by @code{*debug-print-variable-alist*}.
+@end deffn
+
+@comment FIXME (rudi 2004-03-31): sbcl doesn't support breakpoints
+@comment and stepping as of version 0.8.9. The `list-locations'
+@comment command works, but executing a function leads to an error
+@comment when a breakpoint is hit. When stepping works, the
+@comment commented-out section below should be reinstated and the
+@comment example output updated to correspont to sbcl's behaviour.
+
+@c @node Breakpoint Commands, , Information Commands, The Debugger
+@c @comment node-name, next, previous, up
+@c @section Breakpoint Commands
+@c @cindex Breakpoints
+
+@c SBCL supports setting of breakpoints inside compiled functions and
+@c stepping of compiled code. Breakpoints can only be set at at known
+@c locations (@pxref{Unknown Locations and Interrupts}), so these
+@c commands are largely useless unless the @code{debug} optimize quality
+@c is at least @code{2} (@pxref{Debugger Policy Control}). These
+@c commands manipulate breakpoints:
+
+@c @deffn {Debugger Command} breakpoint @var{location} [@var{option} @var{value}]*
+@c Set a breakpoint in some function. @var{location} may be an integer
+@c code location number (as displayed by @command{list-locations}) or a
+@c keyword. The keyword can be used to indicate setting a breakpoint at
+@c the function start (@code{:start}, @code{:s}) or function end
+@c (@code{:end}, @code{:e}). The @command{breakpoint} command has
+@c @code{:condition}, @code{:break}, @code{:print} and @code{:function}
+@c options which work similarly to the @code{trace} options.
+@c @end deffn
+
+@c @deffn {Debugger Command} list-locations [@var{function}]
+@c @deffnx {Debugger Command} ll [@var{function}]
+@c List all the code locations in the current frame's function, or in
+@c @var{function} if it is supplied. The display format is the code
+@c location number, a colon and then the source form for that location:
+
+@c @example
+@c 3: (1- N)
+@c @end example
+
+@c If consecutive locations have the same source, then a numeric range
+@c like @code{3-5:} will be printed. For example, a default function
+@c call has a known location both immediately before and after the call,
+@c which would result in two code locations with the same source. The
+@c listed function becomes the new default function for breakpoint
+@c setting (via the @command{breakpoint}) command.
+@c @end deffn
+
+@c @deffn {Debugger Command} list-breakpoints
+@c @deffnx {Debugger Command} lb
+@c List all currently active breakpoints with their breakpoint number.
+@c @end deffn
+
+@c @deffn {Debugger Command} delete-breakpoint [@var{number}]
+@c @deffnx {Debugger Command} db [@var{number}]
+@c Delete a breakpoint specified by its breakpoint number. If no number
+@c is specified, delete all breakpoints.
+@c @end deffn
+
+@c @deffn {Debugger Command} step
+@c Step to the next possible breakpoint location in the current function.
+@c This always steps over function calls, instead of stepping into them.
+@c @end deffn
+
+
+@c @menu
+@c * Breakpoint Example::
+@c @end menu
+
+@c @node Breakpoint Example, , Breakpoint Commands, Breakpoint Commands
+@c @comment node-name, next, previous, up
+@c @subsection Breakpoint Example
+
+@c Consider this definition of the factorial function:
+
+@c @lisp
+@c (defun ! (n)
+@c (if (zerop n)
+@c 1
+@c (* n (! (1- n)))))
+@c @end lisp
+
+@c This debugger session demonstrates the use of breakpoints:
+
+@c @example
+@c * (break) ; invoke debugger
+
+@c debugger invoked on a SIMPLE-CONDITION in thread 11184: break
+
+@c restarts (invokable by number or by possibly-abbreviated name):
+@c 0: [CONTINUE] Return from BREAK.
+@c 1: [ABORT ] Reduce debugger level (leaving debugger, returning to toplevel).
+@c 2: [TOPLEVEL] Restart at toplevel READ/EVAL/PRINT loop.
+@c ("varargs entry for top level local call BREAK" "break")
+@c 0] ll #'!
+
+@c 0-1: (SB-INT:NAMED-LAMBDA ! (N) (BLOCK ! (IF (ZEROP N) 1 (* N (! #)))))
+@c 2: (BLOCK ! (IF (ZEROP N) 1 (* N (! (1- N)))))
+@c 3: (ZEROP N)
+@c 4: (* N (! (1- N)))
+@c 5: (1- N)
+@c 6: (! (1- N))
+@c 7-8: (* N (! (1- N)))
+@c 9-10: (IF (ZEROP N) 1 (* N (! (1- N))))
+@c 0] br 4
+
+@c (* N (! (1- N)))
+@c 1: 4 in !
+@c added
+@c 0] toplevel
+
+@c FIXME: SBCL errored out, and not in the expected way ... Copying the
+@c output verbatim from the CMUCL manual for now.
+
+@c common-lisp-user> (! 10) ; Call the function
+
+@c *Breakpoint hit*
+
+@c Restarts:
+@c 0: [CONTINUE] Return from BREAK.
+@c 1: [ABORT ] Return to Top-Level.
+
+@c Debug (type H for help)
+
+@c (! 10) ; We are now in first call (arg 10) before the multiply
+@c Source: (* N (! (1- N)))
+@c 3] st
+
+@c *Step*
+
+@c (! 10) ; We have finished evaluation of (1- n)
+@c Source: (1- N)
+@c 3] st
+
+@c *Breakpoint hit*
+
+@c Restarts:
+@c 0: [CONTINUE] Return from BREAK.
+@c 1: [ABORT ] Return to Top-Level.
+
+@c Debug (type H for help)
+
+@c (! 9) ; We hit the breakpoint in the recursive call
+@c Source: (* N (! (1- N)))
+@c 3]
+@c @end example
+
+
+@node Function Tracing, , Information Commands, The Debugger
+@comment node-name, next, previous, up
+@section Function Tracing
+@cindex Tracing
+@cindex Function, tracing
+
+The tracer causes selected functions to print their arguments and
+their results whenever they are called. Options allow conditional
+printing of the trace information and conditional breakpoints on
+function entry or exit.
+
+@comment rudi 2004-03-26: The docstring for `trace' is quite comprehensive,
+@comment so refer to it (see also ``OAOO'')
+The docstrings for @code{trace} and @code{untrace} explain SBCL's
+tracing facility.
+
+@comment FIXME rudi 2004-03-26: revive the documentation of variables
+@comment describing trace behaviour: *trace-encapsulate-default*,
+@comment *max-trace-indentation* and friends. Some of these are
+@comment mentioned (perhaps under different names) in the cmucl
+@comment manual.
+
+@comment FIXME rudi 2004-03-26: encapsulate is (per TODO file as of
+@comment 0.8.9) in a state of flux. When it's sorted out, revive the
+@comment cmucl documentation.
+
+
+
--- /dev/null
+;;;; -*- lisp -*-
+
+;;;; (c) 2004 Rudi Schlatte <rudi@constantly.at>
+;;;; Use it as you wish, send changes back to me if you like.
+
+#+sbcl
+(eval-when (:compile-toplevel :load-toplevel :execute)
+ (require 'sb-introspect))
+
+(defparameter *documentation-types*
+ '(compiler-macro
+ function
+ method-combination
+ setf
+ ;;structure ; also handled by `type'
+ type
+ variable)
+ "A list of symbols accepted as second argument of `documentation'")
+
+;;; Collecting info from package
+
+(defun documentation-for-symbol (symbol)
+ "Collects all doc for a symbol, returns a list of the
+ form (symbol doc-type docstring). See `*documentation-types*'
+ for the possible values of doc-type."
+ (loop for kind in *documentation-types*
+ for doc = (documentation symbol kind)
+ when doc
+ collect (list symbol kind doc)))
+
+(defun collect-documentation (package)
+ "Collects all documentation for all external symbols of the
+ given package, as well as for the package itself."
+ (let* ((package (find-package package))
+ (package-doc (documentation package t))
+ (result nil))
+ (check-type package package)
+ (do-external-symbols (symbol package)
+ (let ((docs (documentation-for-symbol symbol)))
+ (when docs (setf result (nconc docs result)))))
+ (when package-doc
+ (setf result (nconc (list (list (intern (package-name package) :keyword)
+ 'package package-doc)) result)))
+ result))
+
+;;; Helpers for texinfo output
+
+(defvar *texinfo-escaped-chars* "@{}"
+ "Characters that must be escaped with #\@ for Texinfo.")
+
+(defun texinfoify (string-designator)
+ "Return 'string-designator' with characters in
+ *texinfo-escaped-chars* escaped with #\@"
+ (let ((name (string string-designator)))
+ (nstring-downcase
+ (with-output-to-string (s)
+ (loop for char across name
+ when (find char *texinfo-escaped-chars*)
+ do (write-char #\@ s)
+ do (write-char char s))))))
+
+;;; Begin, rest and end of definition.
+
+(defun argument-list (fname)
+ (sb-introspect:function-arglist fname))
+
+(defvar *character-replacements*
+ '((#\* . "star") (#\/ . "slash") (#\+ . "plus"))
+ "Characters and their replacement names that `alphanumize'
+ uses. If the replacements contain any of the chars they're
+ supposed to replace, you deserve to lose.")
+
+(defvar *characters-to-drop* '(#\\ #\` #\')
+ "Characters that should be removed by `alphanumize'.")
+
+
+(defun alphanumize (symbol)
+ "Construct a string without characters like *`' that will
+ f-star-ck up filename handling. See `*character-replacements*'
+ and `*characters-to-drop*' for customization."
+ (let ((name (remove-if #'(lambda (x) (member x *characters-to-drop*))
+ (string symbol)))
+ (chars-to-replace (mapcar #'car *character-replacements*)))
+ (flet ((replacement-delimiter (index)
+ (cond ((or (< index 0) (>= index (length name))) "")
+ ((alphanumericp (char name index)) "-")
+ (t ""))))
+ (loop for index = (position-if #'(lambda (x) (member x chars-to-replace))
+ name)
+ while index
+ do (setf name (concatenate 'string (subseq name 0 index)
+ (replacement-delimiter (1- index))
+ (cdr (assoc (aref name index)
+ *character-replacements*))
+ (replacement-delimiter (1+ index))
+ (subseq name (1+ index))))))
+ name))
+
+(defun unique-name (symbol package kind)
+ (nstring-downcase
+ (format nil "~A-~A-~A"
+ (ecase kind
+ (compiler-macro "compiler-macro")
+ (function (cond
+ ((macro-function symbol) "macro")
+ ((special-operator-p symbol) "special-operator")
+ (t "fun")))
+ (method-combination "method-combination")
+ (package "package")
+ (setf "setf-expander")
+ (structure "struct")
+ (type (let ((class (find-class symbol)))
+ (etypecase class
+ (structure-class "struct")
+ (standard-class "class")
+ (sb-pcl::condition-class "condition")
+ ((or built-in-class null) "type"))))
+ (variable (if (constantp symbol)
+ "constant"
+ "var")))
+ (package-name package)
+ (alphanumize symbol))))
+
+(defun def-begin (symbol kind)
+ (ecase kind
+ (compiler-macro "@deffn {Compiler Macro}")
+ (function (cond
+ ((macro-function symbol) "@defmac")
+ ((special-operator-p symbol) "@defspec")
+ (t "@defun")))
+ (method-combination "@deffn {Method Combination}")
+ (package "@deffn Package")
+ (setf "@deffn {Setf Expander}")
+ (structure "@deftp Structure")
+ (type (let ((class (find-class symbol)))
+ (etypecase class
+ (structure-class "@deftp Structure")
+ (standard-class "@deftp Class")
+ (sb-pcl::condition-class "@deftp Condition")
+ ((or built-in-class null) "@deftp Type"))))
+ (variable (if (constantp symbol)
+ "@defvr Constant"
+ "@defvar"))))
+
+(defparameter *arglist-keywords*
+ '(&allow-other-keys &aux &body &environment &key &optional &rest &whole))
+
+(defun texinfoify-arglist-part (part)
+ (with-output-to-string (s)
+ (etypecase part
+ (string (prin1 (texinfoify part) s))
+ (number (prin1 part s))
+ (symbol
+ (if (member part *arglist-keywords*)
+ (princ (texinfoify part) s)
+ (format s "@var{~A}" (texinfoify part))))
+ (list
+ (format s "(~{~A~^ ~})" (mapcar #'texinfoify-arglist-part part))))))
+
+(defun def-rest (symbol kind)
+ (case kind
+ (function
+ (format nil "~{~A~^ ~}" (mapcar #'texinfoify-arglist-part
+ (argument-list symbol))))))
+
+(defun def-end (symbol kind)
+ (ecase kind
+ (compiler-macro "@end deffn")
+ (function (cond
+ ((macro-function symbol) "@end defmac")
+ ((special-operator-p symbol) "@end defspec")
+ (t "@end defun")))
+ (method-combination "@end deffn")
+ (package "@end deffn")
+ (setf "@end deffn")
+ (type "@end deftp")
+ (variable (if (constantp symbol)
+ "@end defvr"
+ "@defvar"))))
+
+(defun make-info-file (package &optional filename)
+ "Create a file containing all available documentation for the
+ exported symbols of `package' in Texinfo format. If `filename'
+ is not supplied, a file \"<packagename>.texinfo\" is generated.
+
+ The definitions can be referenced using Texinfo statements like
+ @ref{<doc-type>_<packagename>_<symbol-name>.texinfo}. Texinfo
+ syntax-significant characters are escaped in symbol names, but
+ if a docstring contains invalid Texinfo markup, you lose."
+ (let* ((package (find-package package))
+ (filename (or filename (make-pathname
+ :name (string-downcase (package-name package))
+ :type "texinfo")))
+ (docs (sort (collect-documentation package) #'string< :key #'first)))
+ (with-open-file (out filename :direction :output
+ :if-does-not-exist :create :if-exists :supersede)
+ (loop for (symbol kind docstring) in docs
+ do (format out "~&@anchor{~A}~%~A ~A~@[ ~A~]~%~A~%~A~%~%"
+ (unique-name symbol package kind)
+ (def-begin symbol kind)
+ (texinfoify symbol)
+ (def-rest symbol kind)
+ docstring
+ (def-end symbol kind))))
+ filename))
+
+(defun docstrings-to-texinfo (directory &rest packages)
+ "Create files in `directory' containing Texinfo markup of all
+ docstrings of each exported symbol in `packages'. `directory'
+ is created if necessary. If you supply a namestring that
+ doesn't end in a slash, you lose. The generated files are of
+ the form \"<doc-type>_<packagename>_<symbol-name>.texinfo\" and
+ can be included via @include statements. Texinfo
+ syntax-significant characters are escaped in symbol names, but
+ if a docstring contains invalid Texinfo markup, you lose."
+ (let ((directory (merge-pathnames (pathname directory))))
+ (ensure-directories-exist directory)
+ (dolist (package packages)
+ (loop
+ with docs = (collect-documentation (find-package package))
+ for (symbol kind docstring) in docs
+ for doc-identifier = (unique-name symbol package kind)
+ do (with-open-file (out
+ (merge-pathnames
+ (make-pathname :name doc-identifier :type "texinfo")
+ directory)
+ :direction :output
+ :if-does-not-exist :create :if-exists :supersede)
+ (format out "~&@anchor{~A}~%~A ~A~@[ ~A~]~%~A~%~A~%~%"
+ (unique-name symbol package kind)
+ (def-begin symbol kind)
+ (texinfoify symbol)
+ (def-rest symbol kind)
+ docstring
+ (def-end symbol kind)))))
+ directory))
--- /dev/null
+#!/bin/sh
+
+# Create Texinfo snippets from the documentation of exported symbols.
+
+# This software is part of the SBCL system. See the README file for
+# more information.
+#
+# This software is in the public domain and is provided with
+# absolutely no warranty. See the COPYING and CREDITS files for
+# more information.
+
+# how we invoke SBCL
+
+# We create the documentation from the in-tree sbcl if it is found,
+# else an installed sbcl is used.
+sbclsystem=`pwd`/../../src/runtime/sbcl
+if [ -e $sbclsystem ]
+then
+SBCL="${1:-$sbclsystem --core `pwd`/../../output/sbcl.core}"
+export SBCL_HOME=`pwd`/../../contrib
+else
+SBCL="${1:-`which sbcl`}"
+fi
+
+# List of package names that documentation will be created for.
+PACKAGES=":SB-ALIEN :SB-EXT :SB-GRAY :SB-MOP :SB-PROFILE :SB-THREAD"
+
+# Output directory. This has to end with a slash (it's interpreted by
+# Lisp's `pathname' function) or you lose.
+DOCSTRINGDIR="${DOCSTRINGDIR:-docstrings/}"
+
+
+echo /creating docstring snippets from SBCL=\'$SBCL\' for packages \'$PACKAGES\'
+echo "(progn (load \"docstrings.lisp\") (docstrings-to-texinfo \"$DOCSTRINGDIR\" $PACKAGES) (sb-ext:quit))" | $SBCL --noinform --sysinit /dev/null --userinit /dev/null --noprint --disable-debugger
--- /dev/null
+@node Efficiency, Beyond The ANSI Standard, The Debugger, Top
+@comment node-name, next, previous, up
+@chapter Efficiency
+
+FIXME: The material in the CMUCL manual about getting good
+performance from the compiler should be reviewed, reformatted in
+Texinfo, lightly edited for SBCL, and substituted into this
+manual. In the meantime, the original CMUCL manual is still 95+%
+correct for the SBCL version of the Python compiler. See the
+sections
+
+@itemize
+@item Advanced Compiler Use and Efficiency Hints
+@item Advanced Compiler Introduction
+@item More About Types in Python
+@item Type Inference
+@item Source Optimization
+@item Tail Recursion
+@item Local Call
+@item Block Compilation
+@item Inline Expansion
+@item Object Representation
+@item Numbers
+@item General Efficiency Hints
+@item Efficiency Notes
+@end itemize
+
+Besides this information from the CMUCL manual, there are a few other
+points to keep in mind.
+
+@itemize
+
+@item
+The CMUCL manual doesn't seem to state it explicitly, but Python has a
+mental block about type inference when assignment is involved. Python
+is very aggressive and clever about inferring the types of values
+bound with @code{let}, @code{let*}, inline function call, and so
+forth. However, it's much more passive and dumb about inferring the
+types of values assigned with @code{setq}, @code{setf}, and
+friends. It would be nice to fix this, but in the meantime don't
+expect that just because it's very smart about types in most respects
+it will be smart about types involved in assignments. (This doesn't
+affect its ability to benefit from explicit type declarations
+involving the assigned variables, only its ability to get by without
+explicit type declarations.)
+
+@c <!-- FIXME: Python dislikes assignments, but not in type
+@c inference. The real problems are loop induction, closed over
+@c variables and aliases. -->
+
+@item
+Since the time the CMUCL manual was written, CMUCL (and thus SBCL) has
+gotten a generational garbage collector. This means that there are
+some efficiency implications of various patterns of memory usage which
+aren't discussed in the CMUCL manual. (Some new material should be
+written about this.)
+
+@item
+SBCL has some important known efficiency problems. Perhaps the most
+important are
+
+@itemize @minus
+
+@item
+There is only limited support for the ANSI @code{dynamic-extent}
+declaration. @xref{Dynamic-extent allocation}.
+
+@item
+The garbage collector is not particularly efficient, at least on
+platforms without the generational collector (as of SBCL 0.8.9, all
+except x86).
+
+@item
+Various aspects of the PCL implementation of CLOS are more inefficient
+than necessary.
+
+@end itemize
+
+@end itemize
+
+Finally, note that Common Lisp defines many constructs which, in
+the infamous phrase, ``could be compiled efficiently by a
+sufficiently smart compiler''. The phrase is infamous because
+making a compiler which actually is sufficiently smart to find all
+these optimizations systematically is well beyond the state of the art
+of current compiler technology. Instead, they're optimized on a
+case-by-case basis by hand-written code, or not optimized at all if
+the appropriate case hasn't been hand-coded. Some cases where no such
+hand-coding has been done as of SBCL version 0.6.3 include
+
+@itemize
+
+@item
+@code{(reduce #'f x)} where the type of @code{x} is known at compile
+time
+
+@item
+various bit vector operations, e.g. @code{(position 0
+some-bit-vector)}
+
+@item
+specialized sequence idioms, e.g. @code{(remove item list :count 1)}
+
+@item
+cases where local compilation policy does not require excessive type
+checking, e.g. @code{(locally (declare (safety 1)) (assoc item
+list))} (which currently performs safe @code{endp} checking internal
+to assoc).
+
+@end itemize
+
+If your system's performance is suffering because of some construct
+which could in principle be compiled efficiently, but which the SBCL
+compiler can't in practice compile efficiently, consider writing a
+patch to the compiler and submitting it for inclusion in the main
+sources. Such code is often reasonably straightforward to write;
+search the sources for the string ``@code{deftransform}'' to find many
+examples (some straightforward, some less so).
+
+@menu
+* Dynamic-extent allocation::
+* Modular arithmetic::
+@end menu
+
+@node Dynamic-extent allocation, Modular arithmetic, Efficiency, Efficiency
+@comment node-name, next, previous, up
+@section Dynamic-extent allocation
+@cindex Dynamic-extent declaration
+
+SBCL has limited support for performing allocation on the stack when a
+variable is declared @code{dynamic-extent}. The @code{dynamic-extent}
+declarations are not verified, but are simply trusted; if the
+constraints in the Common Lisp standard are violated, the best that
+can happen is for the program to have garbage in variables and return
+values; more commonly, the system will crash.
+
+As a consequence of this, the condition for performing stack
+allocation is stringent: either of the @code{speed} or @code{space}
+optimization qualities must be higher than the maximum of
+@code{safety} and @code{debug} at the point of the allocation. For
+example:
+
+@lisp
+(locally
+ (declare (optimize speed (safety 1) (debug 1)))
+ (defun foo (&rest rest)
+ (declare (dynamic-extent rest))
+ (length rest)))
+@end lisp
+
+Here the @code{&rest} list will be allocated on the stack. Note that
+it would not be in the following situation:
+
+@lisp
+(defun foo (&rest rest)
+ (declare (optimize speed (safety 1) (debug 1)))
+ (declare (dynamic-extent rest))
+ (length rest))
+@end lisp
+
+because both the allocation of the @code{&rest} list and the variable
+binding are outside the scope of the @code{optimize} declaration.
+
+There are many cases when dynamic-extent declarations could be useful.
+At present, SBCL implements
+
+@itemize
+
+@item
+Stack allocation of @code{&rest} lists, where these are declared
+@code{dynamic-extent}.
+
+@end itemize
+
+Future plans include
+
+@itemize
+
+@item
+Stack allocation of closures, where these are declared
+@code{dynamic-extent};
+
+@item
+Stack allocation of @code{list}, @code{list*} and @code{cons}
+(including following chains during initialization, and also for
+binding mutation), where the allocation is declared
+@code{dynamic-extent};
+
+@item
+Automatic detection of the common idiom of applying a function to some
+defaults and a @code{&rest} list, even when this is not declared
+@code{dynamic-extent};
+
+@item
+Automatic detection of the common idiom of calling quantifiers with a
+closure, even when the closure is not declared @code{dynamic-extent}.
+
+@end itemize
+
+@node Modular arithmetic, , Dynamic-extent allocation, Efficiency
+@comment node-name, next, previous, up
+@section Modular arithmetic
+@cindex Modular arithmetic
+@cindex Arithmetic, modular
+@cindex Arithmetic, hardware
+
+Some numeric functions have a property: @var{N} lower bits of the
+result depend only on @var{N} lower bits of (all or some)
+arguments. If the compiler sees an expression of form @code{(logand
+@var{exp} @var{mask})}, where @var{exp} is a tree of such ``good''
+functions and @var{mask} is known to be of type @code{(unsigned-byte
+@var{w})}, where @var{w} is a ``good'' width, all intermediate results
+will be cut to @var{w} bits (but it is not done for variables and
+constants!). This often results in an ability to use simple machine
+instructions for the functions.
+
+Consider an example.
+
+@lisp
+(defun i (x y)
+ (declare (type (unsigned-byte 32) x y))
+ (ldb (byte 32 0) (logxor x (lognot y))))
+@end lisp
+
+The result of @code{(lognot y)} will be negative and of type
+@code{(signed-byte 33)}, so a naive implementation on a 32-bit
+platform is unable to use 32-bit arithmetic here. But modular
+arithmetic optimizer is able to do it: because the result is cut down
+to 32 bits, the compiler will replace @code{logxor} and @code{lognot}
+with versions cutting results to 32 bits, and because terminals
+(here---expressions @code{x} and @code{y}) are also of type
+@code{(unsigned-byte 32)}, 32-bit machine arithmetic can be used.
+
+
+As of SBCL 0.8.5 ``good'' functions are @code{+}, @code{-};
+@code{logand}, @code{logior}, @code{logxor}, @code{lognot} and their
+combinations; and @code{ash} with the positive second
+argument. ``Good'' widths are 32 on HPPA, MIPS, PPC, Sparc and X86 and
+64 on Alpha. While it is possible to support smaller widths as well,
+currently it is not implemented.
--- /dev/null
+@node The Foreign Function Interface, Function Index, Beyond The ANSI Standard, Top
+@comment node-name, next, previous, up
+@chapter The Foreign Function Interface
+
+This chapter describes SBCL's interface to C programs and
+libraries (and, since C interfaces are a sort of @emph{ingua
+franca} of the Unix world, to other programs and libraries in
+general.)
+
+@quotation
+Note: In the modern Lisp world, the usual term for this functionality
+is Foreign Function Interface, or @acronym{FFI}, where despite the
+mention of ``function'' in this term, @acronym{FFI} also
+refers to direct manipulation of C data structures as well as
+functions. The traditional CMUCL terminology is Alien Interface, and
+while that older terminology is no longer used much in the system
+documentation, it still reflected in names in the implementation,
+notably in the name of the @code{SB-ALIEN} package.
+@end quotation
+
+@menu
+* Introduction to the Foreign Function Interface::
+* Foreign Types::
+* Operations On Foreign Values::
+* Foreign Variables::
+* Foreign Data Structure Examples::
+* Loading Unix Object Files::
+* Foreign Function Calls::
+* Step-By-Step Example of the Foreign Function Interface::
+@end menu
+
+@node Introduction to the Foreign Function Interface, Foreign Types, The Foreign Function Interface, The Foreign Function Interface
+@comment node-name, next, previous, up
+@section Introduction to the Foreign Function Interface
+@c AKA "Introduction to Aliens" in the CMU CL manual
+
+Because of Lisp's emphasis on dynamic memory allocation and garbage
+collection, Lisp implementations use non-C-like memory representations
+for objects. This representation mismatch creates friction when a Lisp
+program must share objects with programs which expect C data. There
+are three common approaches to establishing communication:
+
+@itemize
+@item
+The burden can be placed on the foreign program (and programmer) by
+requiring the knowledge and use of the representations used internally
+by the Lisp implementation. This can require a considerable amount of
+``glue'' code on the C side, and that code tends to be sensitively
+dependent on the internal implementation details of the Lisp system.
+
+@item
+The Lisp system can automatically convert objects back and forth
+between the Lisp and foreign representations. This is convenient, but
+translation becomes prohibitively slow when large or complex data
+structures must be shared. This approach is supported by the SBCL
+@acronym{FFI}, and used automatically by the when passing integers and
+strings.
+
+@item
+The Lisp program can directly manipulate foreign objects through the
+use of extensions to the Lisp language.
+
+@end itemize
+
+SBCL, like CMUCL before it, relies primarily on the automatic
+conversion and direct manipulation approaches. The @code{SB-ALIEN}
+package provices a facility wherein foreign values of simple scalar
+types are automatically converted and complex types are directly
+manipulated in their foreign representation. Additionally the
+lower-level System Area Pointers (or @acronym{SAP}s) can be used where
+necessary to provide untyped access to foreign memory.
+
+Any foreign objects that can't automatically be converted into Lisp
+values are represented by objects of type @code{alien-value}. Since
+Lisp is a dynamically typed language, even foreign objects must have a
+run-time type; this type information is provided by encapsulating the
+raw pointer to the foreign data within an @code{alien-value} object.
+
+The type language and operations on foreign types are
+intentionally similar to those of the C language.
+
+@node Foreign Types, Operations On Foreign Values, Introduction to the Foreign Function Interface, The Foreign Function Interface
+@comment node-name, next, previous, up
+@section Foreign Types
+@c AKA "Alien Types" in the CMU CL manual
+
+Alien types have a description language based on nested list
+structure. For example the C type
+
+@example
+struct foo @{
+ int a;
+ struct foo *b[100];
+@};
+@end example
+
+has the corresponding SBCL @acronym{FFI} type
+
+@lisp
+(struct foo
+ (a int)
+ (b (array (* (struct foo)) 100)))
+@end lisp
+
+
+@menu
+* Defining Foreign Types::
+* Foreign Types and Lisp Types::
+* Foreign Type Specifiers::
+@end menu
+
+@node Defining Foreign Types, Foreign Types and Lisp Types, Foreign Types, Foreign Types
+@comment node-name, next, previous, up
+@subsection Defining Foreign Types
+
+Types may be either named or anonymous. With structure and union
+types, the name is part of the type specifier, allowing recursively
+defined types such as:
+
+@lisp
+(struct foo (a (* (struct foo))))
+@end lisp
+
+An anonymous structure or union type is specified by using the name
+@code{nil}. The @code{with-alien} macro defines a local scope which
+``captures'' any named type definitions. Other types are not
+inherently named, but can be given named abbreviations using the
+@code{define-alien-type} macro.
+
+@node Foreign Types and Lisp Types, Foreign Type Specifiers, Defining Foreign Types, Foreign Types
+@comment node-name, next, previous, up
+@subsection Foreign Types and Lisp Types
+
+The foreign types form a subsystem of the SBCL type system. An
+@code{alien} type specifier provides a way to use any foreign type as a
+Lisp type specifier. For example,
+
+@lisp
+(typep @var{foo} '(alien (* int)))
+@end lisp
+
+can be used to determine whether @var{foo} is a pointer to a foreign
+@code{int}. @code{alien} type specifiers can be used in the same ways
+as ordinary Lisp type specifiers (like @code{string}.) Alien type
+declarations are subject to the same precise type checking as any
+other declaration. @xref{Precise Type Checking}.
+
+Note that the type identifiers used in the foreign type system overlap
+with native Lisp type specifiers in some cases. For example, the type
+specifier @code{(alien single-float)} is identical to
+@code{single-float}, since foreign floats are automatically converted
+to Lisp floats. When @code{type-of} is called on an alien value that
+is not automatically converted to a Lisp value, then it will return an
+@code{alien} type specifier.
+
+@node Foreign Type Specifiers, , Foreign Types and Lisp Types, Foreign Types
+@comment node-name, next, previous, up
+@subsection Foreign Type Specifiers
+
+Note: All foreign type names are exported from the @code{sb-alien}
+package. Some foreign type names are also symbols in
+the @code{common-lisp} package, in which case they are
+reexported from the @code{sb-alien} package, so that
+e.g. it is legal to refer to @code{sb-alien:single-float}.
+
+These are the basic foreign type specifiers:
+
+@itemize
+@item
+The foreign type specifier @code{(* @var{foo})} describes a pointer to
+an object of type @var{foo}. A pointed-to type @var{foo} of @code{t}
+indicates a pointer to anything, similar to @code{void *} in
+ANSI C. A null alien pointer can be detected with the
+@code{sb-alien:null-alien} function.
+
+@item
+The foreign type specifier @code{(array @var{foo} &optional
+dimensions)} describes array of the specified @code{dimensions},
+holding elements of type @var{foo}. Note that (unlike in C) @code{(*
+@var{foo})} and @code{(array @var{foo})} are considered to be
+different types when type checking is done. If equivalence of pointer
+and array types is desired, it may be explicitly coerced using
+@code{sb-alien:cast}.
+
+Arrays are accessed using @code{sb-alien:deref}, passing the indices
+as additional arguments. Elements are stored in column-major order
+(as in C), so the first dimension determines only the size of the
+memory block, and not the layout of the higher dimensions. An array
+whose first dimension is variable may be specified by using @code{nil}
+as the first dimension. Fixed-size arrays can be allocated as array
+elements, structure slots or @code{sb-alien:with-alien}
+variables. Dynamic arrays can only be allocated using
+@code{sb-alien:make-alien}.
+
+@item
+The foreign type specifier @code{(sb-alien:struct @var{name} &rest
+@var{fields})} describes a structure type with the specified
+@var{name} and @var{fields}. Fields are allocated at the same offsets
+used by the implementation's C compiler. If @var{name} is @code{nil}
+then the structure is anonymous.
+
+If a named foreign @code{struct} specifier is passed to
+@code{define-alien-type} or @code{with-alien}, then this defines,
+respectively, a new global or local foreign structure type. If no
+@var{fields} are specified, then the fields are taken
+from the current (local or global) alien structure type definition of
+@var{name}.
+
+@item
+The foreign type specifier @code{(sb-alien:union @var{name} &rest
+@var{fields})} is similar to @code{sb-alien:struct}, but describes a
+union type. All fields are allocated at the same offset, and the size
+of the union is the size of the largest field. The programmer must
+determine which field is active from context.
+
+@item
+The foreign type specifier @code{(sb-alien:enum @var{name} &rest
+@var{specs})} describes an enumeration type that maps between integer
+values and keywords. If @var{name} is @code{nil}, then the type is
+anonymous. Each element of the @var{specs} list is either a Lisp
+keyword, or a list @code{(@var{keyword} @var{value})}. @var{value} is
+an integer. If @var{value} is not supplied, then it defaults to one
+greater than the value for the preceding spec (or to zero if it is the
+first spec).
+
+@item
+The foreign type specifier @code{(sb-alien:signed &optional
+@var{bits})} specifies a signed integer with the specified number of
+@var{bits} precision. The upper limit on integer
+precision is determined by the machine's word size. If
+@var{bits} is not specified, the maximum size will be
+used.
+
+@item
+The foreign type specifier @code{(integer &optional @var{bits})}
+is equivalent to the corresponding type specifier using
+@code{sb-alien:signed} instead of @code{integer}.
+
+@item
+The foreign type specifier @code{(sb-alien:unsigned &optional
+@var{bits})} is like corresponding type specifier using
+@code{sb-alien:signed} except that the variable is treated as an
+unsigned integer.
+
+@item
+The foreign type specifier @code{(boolean &optional @var{bits})} is
+similar to an enumeration type, but maps from Lisp @code{nil} and
+@code{t} to C @code{0} and @code{1} respectively. @var{bits}
+determines the amount of storage allocated to hold the truth value.
+
+@item
+The foreign type specifier @code{single-float} describes a
+floating-point number in IEEE single-precision format.
+
+@item
+The foreign type specifier @code{double-float} describes a
+floating-point number in IEEE double-precision format.
+
+@item
+The foreign type specifier @code{(function @var{result-type} &rest
+@var{arg-types})} describes a foreign function that takes arguments of
+the specified @var{arg-types} and returns a result of type
+@var{result-type}. Note that the only context where a foreign
+@code{function} type is directly specified is in the argument to
+@code{sb-alien:alien-funcall}. In all other contexts, foreign
+functions are represented by foreign function pointer types: @code{(*
+(function @dots{}))}.
+
+@item
+The foreign type specifier @code{sb-alien:system-area-pointer}
+describes a pointer which is represented in Lisp as a
+@code{system-area-pointer} object. SBCL exports this type from
+@code{sb-alien} because CMUCL did, but tentatively (as of the first
+draft of this section of the manual, SBCL 0.7.6) it is deprecated,
+since it doesn't seem to be required by user code.
+
+@item
+The foreign type specifier @code{sb-alien:void} is used in function
+types to declare that no useful value is returned. Using
+@code{alien-funcall} to call a @code{void} foreign function will
+return zero values.
+
+@item
+The foreign type specifier @code{sb-alien:c-string} is similar to
+@code{(* char)}, but is interpreted as a null-terminated string, and
+is automatically converted into a Lisp string when accessed; or if the
+pointer is C @code{NULL} or @code{0}, then accessing it gives Lisp
+@code{nil}. Lisp strings are stored with a trailing NUL
+termination, so no copying (either by the user or the implementation)
+is necessary when passing them to foreign code.
+
+Assigning a Lisp string to a @code{c-string} structure field or
+variable stores the contents of the string to the memory already
+pointed to by that variable. When a foreign object of type @code{(*
+char)} is assigned to a @code{c-string}, then the
+@code{c-string} pointer is assigned to. This allows
+@code{c-string} pointers to be initialized. For example:
+
+@lisp
+(cl:in-package "CL-USER") ; which USEs package "SB-ALIEN"
+
+(define-alien-type nil (struct foo (str c-string)))
+
+(defun make-foo (str)
+ (let ((my-foo (make-alien (struct foo))))
+ (setf (slot my-foo 'str) (make-alien char (length str))
+ (slot my-foo 'str) str)
+ my-foo))
+@end lisp
+
+Storing Lisp @code{NIL} in a @code{c-string} writes C @code{NULL} to
+the variable.
+
+@item
+@code{sb-alien} also exports translations of these C type
+specifiers as foreign type specifiers: @code{sb-alien:char},
+@code{sb-alien:short}, @code{sb-alien:int},
+@code{sb-alien:long}, @code{sb-alien:unsigned-char},
+@code{sb-alien:unsigned-short},
+@code{sb-alien:unsigned-int},
+@code{sb-alien:unsigned-long}, @code{sb-alien:float}, and
+@code{sb-alien:double}.
+
+@end itemize
+
+@node Operations On Foreign Values, Foreign Variables, Foreign Types, The Foreign Function Interface
+@comment node-name, next, previous, up
+@section Operations On Foreign Values
+@c AKA "Alien Operations" in the CMU CL manual
+
+This section describes how to read foreign values as Lisp values, how
+to coerce foreign values to different kinds of foreign values, and how
+to dynamically allocate and free foreign variables.
+
+@menu
+* Accessing Foreign Values::
+* Coercing Foreign Values::
+* Foreign Dynamic Allocation::
+@end menu
+
+@node Accessing Foreign Values, Coercing Foreign Values, Operations On Foreign Values, Operations On Foreign Values
+@comment node-name, next, previous, up
+@subsection Accessing Foreign Values
+
+@defun sb-alien:deref @var{pointer-or-array} &rest @var{indices}
+
+The @code{sb-alien:deref} function returns the value pointed to by a
+foreign pointer, or the value of a foreign array element. When
+dereferencing a pointer, an optional single index can be specified to
+give the equivalent of C pointer arithmetic; this index is scaled by
+the size of the type pointed to. When dereferencing an array, the
+number of indices must be the same as the number of dimensions in the
+array type. @code{deref} can be set with @code{setf} to assign a new
+value.
+
+@end defun
+
+@defun sb-alien:slot @var{struct-or-union} &rest @var{slot-names}
+
+The @code{sb-alien:slot} function extracts the value of the slot named
+@var{slot-name} from a foreign @code{struct} or @code{union}. If
+@var{struct-or-union} is a pointer to a structure or union, then it is
+automatically dereferenced. @code{sb-alien:slot} can be set with
+@code{setf} to assign a new value. Note that @var{slot-name} is
+evaluated, and need not be a compile-time constant (but only constant
+slot accesses are efficiently compiled).
+@end defun
+
+
+@subsubsection Untyped memory
+
+As noted at the beginning of the chapter, the System Area Pointer
+facilities allow untyped access to foreign memory. @acronym{SAP}s can
+be converted to and from the usual typed foreign values using
+@code{sap-alien} and @code{alien-sap} (described elsewhere), and also
+to and from integers - raw machine addresses. They should thus be
+used with caution; corrupting the Lisp heap or other memory with
+@acronym{SAP}s is trivial.
+
+@defun sb-sys:int-sap @var{machine-address}
+
+Creates a @acronym{SAP} pointing at the virtual address
+@var{machine-address}.
+@end defun
+
+@defun sb-sys:sap-ref-32 @var{sap} @var{offset}
+
+Access the value of the memory location at @var{offset} bytes from
+@var{sap}. This form may also be used with @code{setf} to alter the
+memory at that location.
+@end defun
+
+@defun sb-sys:sap= @var{sap1} @var{sap2}
+
+Compare @var{sap1} and @var{sap2} for equality.
+@end defun
+
+Similarly named functions exist for accessing other sizes of word,
+other comparisons, and other conversions. The reader is invited to
+use @code{apropos} and @code{describe} for more details
+
+@lisp
+(apropos "sap" :sb-sys)
+@end lisp
+
+
+@node Coercing Foreign Values, Foreign Dynamic Allocation, Accessing Foreign Values, Operations On Foreign Values
+@comment node-name, next, previous, up
+@subsection Coercing Foreign Values
+
+@defun sb-alien:addr @var{alien-expr}
+
+The @code{sb-alien:addr} macro returns a pointer to the location
+specified by @var{alien-expr}, which must be either a foreign
+variable, a use of @code{sb-alien:deref}, a use of
+@code{sb-alien:slot}, or a use of @code{sb-alien:extern-alien}.
+@end defun
+
+@defun sb-alien:cast @var{foreign-value} @var{new-type}
+
+The @code{sb-alien:cast} macro converts @var{foreign-value} to a new
+foreign value with the specified @var{new-type}. Both types, old and
+new, must be foreign pointer, array or function types. Note that the
+resulting Lisp foreign variable object is not @code{eq} to the
+argument, but it does refer to the same foreign data bits.
+@end defun
+
+@defun sb-alien:sap-alien @var{sap} @var{type}
+
+The @code{sb-alien:sap-alien} function converts @var{sap} (a system
+area pointer) to a foreign value with the specified
+@var{type}. @var{type} is not evaluated. </para>
+
+The @var{type} must be some foreign pointer, array, or record type.
+@end defun
+
+@defun sb-alien:alien-sap @var{foreign-value} @var{type}
+
+The @code{sb-alien:alien-sap} function returns the @acronym{SAP} which
+points to @var{alien-value}'s data.
+
+The @var{foreign-value} must be of some foreign pointer, array, or
+record type.
+@end defun
+
+
+@node Foreign Dynamic Allocation, , Coercing Foreign Values, Operations On Foreign Values
+@comment node-name, next, previous, up
+@subsection Foreign Dynamic Allocation
+
+Lisp code can call the C standard library functions @code{malloc} and
+@code{free} to dynamically allocate and deallocate foreign
+variables. The Lisp code shares the same allocator with foreign C
+code, so it's OK for foreign code to call @code{free} on the result of
+Lisp @code{sb-alien:make-alien}, or for Lisp code to call
+@code{sb-alien:free-alien} on foreign objects allocated by C
+code.
+
+@defmac sb-alien:make-alien @var{type} @var{size}
+
+The @code{sb-alien:make-alien} macro
+returns a dynamically allocated foreign value of the specified
+@var{type} (which is not evaluated.) The allocated memory is not
+initialized, and may contain arbitrary junk. If supplied,
+@var{size} is an expression to evaluate to compute the size of the
+allocated object. There are two major cases:
+
+@itemize
+@item
+When @var{type} is a foreign array type, an array of that type is
+allocated and a pointer to it is returned. Note that you must use
+@code{deref} to change the result to an array before you can use
+@code{deref} to read or write elements:
+
+@lisp
+(cl:in-package "CL-USER") ; which USEs package "SB-ALIEN"
+(defvar *foo* (make-alien (array char 10)))
+(type-of *foo*) @result{} (alien (* (array (signed 8) 10)))
+(setf (deref (deref foo) 0) 10) @result{} 10
+@end lisp
+
+If supplied, @var{size} is used as the first dimension for the
+ array.
+
+@item
+When @var{type} is any other foreign type, then an object for that
+type is allocated, and a pointer to it is returned. So
+@code{(make-alien int)} returns a @code{(* int)}. If @var{size} is
+specified, then a block of that many objects is allocated, with the
+result pointing to the first one.
+
+@end itemize
+
+@end defmac
+
+@defun sb-alien:free-alien @var{foreign-value}
+
+The @code{sb-alien:free-alien} function
+frees the storage for @var{foreign-value},
+which must have been allocated with Lisp @code{make-alien}
+or C @code{malloc}.
+
+See also the @code{sb-alien:with-alien} macro, which allocates foreign
+values on the stack.
+@end defun
+
+@node Foreign Variables, Foreign Data Structure Examples, Operations On Foreign Values, The Foreign Function Interface
+@comment node-name, next, previous, up
+@section Foreign Variables
+@c AKA "Alien Variables" in the CMU CL manual
+
+Both local (stack allocated) and external (C global) foreign variables
+are supported.
+
+@menu
+* Local Foreign Variables::
+* External Foreign Variables::
+@end menu
+
+@node Local Foreign Variables, External Foreign Variables, Foreign Variables, Foreign Variables
+@comment node-name, next, previous, up
+@subsection Local Foreign Variables
+
+@defmac sb-alien:with-alien @var{var-definitions} &body @var{body}
+
+The @code{with-alien} macro establishes local foreign variables with
+the specified alien types and names. This form is analogous to
+defining a local variable in C: additional storage is allocated, and
+the initial value is copied. This form is less analogous to
+@code{LET}-allocated Lisp variables, since the variables can't be
+captured in closures: they live only for the dynamic extent of the
+body, and referring to them outside is a gruesome error.
+
+The @var{var-definitions} argument is a list of
+variable definitions, each of the form
+@lisp
+(@var{name} @var{type} &optional @var{initial-value})
+@end lisp
+
+The names of the variables are established as symbol-macros; the
+bindings have lexical scope, and may be assigned with @code{setq} or
+@code{setf}.
+
+The @code{with-alien} macro also establishes a new scope for named
+structures and unions. Any @var{type} specified for a variable may
+contain named structure or union types with the slots specified.
+Within the lexical scope of the binding specifiers and body, a locally
+defined foreign structure type @var{foo} can be referenced by its name
+using @code{(struct @var{foo})}.
+@end defmac
+
+@node External Foreign Variables, , Local Foreign Variables, Foreign Variables
+@comment node-name, next, previous, up
+@subsection External Foreign Variables
+
+External foreign names are strings, and Lisp names are symbols. When
+an external foreign value is represented using a Lisp variable, there
+must be a way to convert from one name syntax into the other. The
+macros @code{extern-alien}, @code{define-alien-variable} and
+@code{define-alien-routine} use this conversion heuristic:
+
+@itemize
+
+@item
+Alien names are converted to Lisp names by uppercasing and replacing
+underscores with hyphens.
+
+@item
+Conversely, Lisp names are converted to alien names by lowercasing and
+replacing hyphens with underscores.
+
+@item
+Both the Lisp symbol and alien string names may be separately
+specified by using a list of the form
+
+@lisp
+(alien-string lisp-symbol)
+@end lisp
+
+@end itemize
+
+@defmac sb-alien:define-alien-variable @var{name} @var{type}
+
+The @code{define-alien-variable} macro defines @var{name} as an
+external foreign variable of the specified foreign @code{type}.
+@var{name} and @code{type} are not evaluated. The Lisp name of the
+variable (see above) becomes a global alien variable. Global alien
+variables are effectively ``global symbol macros''; a reference to the
+variable fetches the contents of the external variable. Similarly,
+setting the variable stores new contents -- the new contents must be
+of the declared @code{type}. Someday, they may well be implemented
+using the @acronym{ANSI} @code{define-symbol-macro} mechanism, but as
+of SBCL 0.7.5, they are still implemented using an older more-or-less
+parallel mechanism inherited from CMUCL.
+
+For example, to access a C-level counter @var{foo}, one could write
+
+@lisp
+(define-alien-variable "foo" int)
+;; Now it is possible to get the value of the C variable foo simply by
+;; referencing that Lisp variable:
+(print foo)
+(setf foo 14)
+(incf foo)
+@end lisp
+@end defmac
+
+@defun sb-alien:get-errno
+
+Since in modern C libraries, the @code{errno} ``variable'' is typically
+no longer a variable, but some bizarre artificial construct
+which behaves superficially like a variable within a given thread,
+it can no longer reliably be accessed through the ordinary
+@code{define-alien-variable} mechanism. Instead, SBCL provides
+the operator @code{sb-alien:get-errno} to allow Lisp code to read it.
+@end defun
+
+@defmac sb-alien:extern-alien @var{name} @var{type}
+
+The @code{extern-alien} macro returns an alien with the specified
+@var{type} which points to an externally defined value. @var{name} is
+not evaluated, and may be either a string or a symbol. @var{type} is
+an unevaluated alien type specifier.
+@end defmac
+
+@node Foreign Data Structure Examples, Loading Unix Object Files, Foreign Variables, The Foreign Function Interface
+@comment node-name, next, previous, up
+@section Foreign Data Structure Examples
+@c AKA "Alien Data Structure Example" in the CMU CL manual
+
+Now that we have alien types, operations and variables, we can
+manipulate foreign data structures. This C declaration
+
+@example
+struct foo @{
+ int a;
+ struct foo *b[100];
+@};
+@end example
+
+can be translated into the following alien type:
+
+@lisp
+(define-alien-type nil
+ (struct foo
+ (a int)
+ (b (array (* (struct foo)) 100))))
+@end lisp
+
+Once the @code{foo} alien type has been defined as above, the C
+expression
+
+@example
+struct foo f;
+f.b[7].a;
+@end example
+
+can be translated in this way:
+
+@lisp
+(with-alien ((f (struct foo)))
+ (slot (deref (slot f 'b) 7) 'a)
+ ;;
+ ;; Do something with f...
+ )
+@end lisp
+
+Or consider this example of an external C variable and some accesses:
+
+@example
+struct c_struct @{
+ short x, y;
+ char a, b;
+ int z;
+ c_struct *n;
+@};
+extern struct c_struct *my_struct;
+my_struct->x++;
+my_struct->a = 5;
+my_struct = my_struct->n;
+@end example
+
+which can be manipulated in Lisp like this:
+
+@lisp
+(define-alien-type nil
+ (struct c-struct
+ (x short)
+ (y short)
+ (a char)
+ (b char)
+ (z int)
+ (n (* c-struct))))
+(define-alien-variable "my_struct" (* c-struct))
+(incf (slot my-struct 'x))
+(setf (slot my-struct 'a) 5)
+(setq my-struct (slot my-struct 'n))
+@end lisp
+
+@node Loading Unix Object Files, Foreign Function Calls, Foreign Data Structure Examples, The Foreign Function Interface
+@comment node-name, next, previous, up
+@section Loading Unix Object Files
+
+Foreign object files can be loaded into the running Lisp process by
+calling the functions @code{load-foreign} or @code{load-1-foreign}.
+
+The @code{sb-alien:load-1-foreign} function is the more primitive of
+the two operations. It loads a single object file into the currently
+running Lisp. The external symbols defining routines and variables are
+made available for future external references (e.g. by
+@code{extern-alien}). Forward references to foreign symbols aren't
+supported: @code{load-1-foreign} must be run before any of the defined
+symbols are referenced.
+
+@code{sb-alien:load-foreign} is built in terms of
+@code{load-1-foreign} and some other machinery like
+@code{sb-ext:run-program}. It accepts a list of files and libraries,
+and runs the linker on the files and libraries, creating an absolute
+Unix object file which is then processed by @code{load-1-foreign}.
+
+@quotation
+Note: As of SBCL 0.7.5, all foreign code (code loaded with
+@code{load-1-function} or @code{load-function}) is lost when a Lisp
+core is saved with @code{sb-ext:save-lisp-and-die}, and no attempt is
+made to restore it when the core is loaded. Historically this has been
+an annoyance both for SBCL users and for CMUCL users. It's hard to
+solve this problem completely cleanly, but some generally-reliable
+partial solution might be useful. Once someone in either camp gets
+sufficiently annoyed to create it, SBCL is likely to adopt some
+mechanism for automatically restoring foreign code when a saved core
+is loaded.
+@end quotation
+
+
+@node Foreign Function Calls, Step-By-Step Example of the Foreign Function Interface, Loading Unix Object Files, The Foreign Function Interface
+@comment node-name, next, previous, up
+@section Foreign Function Calls
+
+The foreign function call interface allows a Lisp program to call
+many functions written in languages that use the C calling convention.
+
+Lisp sets up various signal handling routines and other environment
+information when it first starts up, and expects these to be in place
+at all times. The C functions called by Lisp should not change the
+environment, especially the signal handlers: the signal handlers
+installed by Lisp typically have interesting flags set (e.g to request
+machine context information, or for signal delivery on an alternate
+stack) which the Lisp runtime relies on for correct operation.
+Precise details of how this works may change without notice between
+versions; the source, or the brain of a friendly SBCL developer, is
+the only documentation. Users of a Lisp built with the
+@code{:sb-thread} feature should also read the section about threads,
+@ref{Threading}.
+
+@menu
+* The alien-funcall Primitive::
+* The define-alien-routine Macro::
+* define-alien-routine Example::
+* Calling Lisp From C::
+@end menu
+
+@node The alien-funcall Primitive, The define-alien-routine Macro, Foreign Function Calls, Foreign Function Calls
+@comment node-name, next, previous, up
+@subsection The @code{alien-funcall} Primitive
+
+@defun sb-alien:alien-funcall @var{alien-function} &rest @var{arguments}
+
+The @code{alien-funcall} function is the foreign function call
+primitive: @var{alien-function} is called with the supplied
+@var{arguments} and its C return value is returned as a Lisp value.
+The @var{alien-function} is an arbitrary run-time expression; to refer
+to a constant function, use @code{extern-alien} or a value defined by
+@code{define-alien-routine}.
+
+The type of @code{alien-function} must be @code{(alien (function
+...))} or @code{(alien (* (function ...)))}. The function type is
+used to determine how to call the function (as though it was declared
+with a prototype.) The type need not be known at compile time, but
+only known-type calls are efficiently compiled. Limitations:
+
+@itemize
+
+@item
+Structure type return values are not implemented.
+
+@item
+Passing of structures by value is not implemented.
+
+@end itemize
+
+@end defun
+
+Here is an example which allocates a @code{(struct foo)}, calls a
+foreign function to initialize it, then returns a Lisp vector of all
+the @code{(* (struct foo))} objects filled in by the foreign call:
+
+@lisp
+;; Allocate a foo on the stack.
+(with-alien ((f (struct foo)))
+ ;; Call some C function to fill in foo fields.
+ (alien-funcall (extern-alien "mangle_foo" (function void (* foo)))
+ (addr f))
+ ;; Find how many foos to use by getting the A field.
+ (let* ((num (slot f 'a))
+ (result (make-array num)))
+ ;; Get a pointer to the array so that we don't have to keep extracting it:
+ (with-alien ((a (* (array (* (struct foo)) 100)) (addr (slot f 'b))))
+ ;; Loop over the first N elements and stash them in the result vector.
+ (dotimes (i num)
+ (setf (svref result i) (deref (deref a) i)))
+ ;; Voila.
+ result)))
+@end lisp
+
+@node The define-alien-routine Macro, define-alien-routine Example, The alien-funcall Primitive, Foreign Function Calls
+@comment node-name, next, previous, up
+@subsection The @code{define-alien-routine} Macro
+
+@defmac sb-alien:define-alien-routine @var{name} @var{result-type} &rest @var{arg-specifiers}
+
+The @code{define-alien-routine} macro is a convenience for
+automatically generating Lisp interfaces to simple foreign functions.
+The primary feature is the parameter style specification, which
+translates the C pass-by-reference idiom into additional return
+values.
+
+@var{name} is usually a string external symbol, but may also be a
+symbol Lisp name or a list of the foreign name and the Lisp name. If
+only one name is specified, the other is automatically derived as for
+@code{extern-alien}. @var{result-type} is the alien type of the
+return value.
+
+Each element of the @var{arg-specifiers} list
+specifies an argument to the foreign function, and is
+of the form
+@lisp
+(aname atype &optional style)
+@end lisp
+
+@var{aname} is the symbol name of the argument to the constructed
+function (for documentation). @var{atype} is the alien type of
+corresponding foreign argument. The semantics of the actual call are
+the same as for @code{alien-funcall}. @var{style} specifies how this
+argument should be handled at call and return time, and should be one
+of the following:
+
+@itemize
+
+@item
+@code{:in} specifies that the argument is passed by value. This is the
+default. @code{:in} arguments have no corresponding return value from
+the Lisp function.
+
+@item
+@code{:copy} is similar to @code{:in}, but the argument is copied to a
+pre-allocated object and a pointer to this object is passed to the
+foreign routine.
+
+@item
+@code{:out} specifies a pass-by-reference output value. The type of
+the argument must be a pointer to a fixed-sized object (such as an
+integer or pointer). @code{:out} and @code{:in-out} style cannot be
+used with pointers to arrays, records or functions. An object of the
+correct size is allocated on the stack, and its address is passed to
+the foreign function. When the function returns, the contents of this
+location are returned as one of the values of the Lisp function (and
+the location is automatically deallocated).
+
+@item
+@code{:in-out} is a combination of @code{:copy} and @code{:out}. The
+argument is copied to a pre-allocated object and a pointer to this
+object is passed to the foreign routine. On return, the contents of
+this location is returned as an additional value.
+
+@end itemize
+
+@quotation
+Note: Any efficiency-critical foreign interface function should be inline
+expanded, which can be done by preceding the
+@code{define-alien-routine} call with:
+
+@lisp
+(declaim (inline lisp-name))
+@end lisp
+
+In addition to avoiding the Lisp call overhead, this allows
+pointers, word-integers and floats to be passed using non-descriptor
+representations, avoiding consing.)
+@end quotation
+
+@end defmac
+
+@node define-alien-routine Example, Calling Lisp From C, The define-alien-routine Macro, Foreign Function Calls
+@comment node-name, next, previous, up
+@subsection @code{define-alien-routine} Example
+
+Consider the C function @code{cfoo} with the following calling
+convention:
+
+@example
+void
+cfoo (str, a, i)
+ char *str;
+ char *a; /* update */
+ int *i; /* out */
+@{
+ /* body of cfoo(...) */
+@}
+@end example
+
+This can be described by the following call to
+@code{define-alien-routine}:
+
+@lisp
+(define-alien-routine "cfoo" void
+ (str c-string)
+ (a char :in-out)
+ (i int :out))
+@end lisp
+
+The Lisp function @code{cfoo} will have two arguments (@var{str} and
+@var{a}) and two return values (@var{a} and @var{i}).
+
+@node Calling Lisp From C, , define-alien-routine Example, Foreign Function Calls
+@comment node-name, next, previous, up
+@subsection Calling Lisp From C
+
+Calling Lisp functions from C is sometimes possible, but is extremely
+hackish and poorly supported as of SBCL 0.7.5. See @code{funcall0}
+@dots{} @code{funcall3} in the runtime system. The arguments must be
+valid SBCL object descriptors (so that e.g. fixnums must be
+left-shifted by 2.) As of SBCL 0.7.5, the format of object descriptors
+is documented only by the source code and, in parts, by the old CMUCL
+@file{INTERNALS} documentation.
+
+Note that the garbage collector moves objects, and won't be
+able to fix up any references in C variables. There are three
+mechanisms for coping with this:
+
+@enumerate
+@item
+The @code{sb-ext:purify} moves all live Lisp
+data into static or read-only areas such that it will never be moved
+(or freed) again in the life of the Lisp session
+
+@item
+@code{sb-sys:with-pinned-objects} is a macro which arranges for some
+set of objects to be pinned in memory for the dynamic extent of its
+body forms. On ports which use the generational garbage collector (as
+of SBCL 0.8.3, only the x86) this has a page granularity - i.e. the
+entire 4k page or pages containing the objects will be locked down. On
+other ports it is implemented by turning off GC for the duration (so
+could be said to have a whole-world granularity).
+
+@item
+Disable GC, using the @code{without-gcing} macro or @code{gc-off}
+call.
+@end enumerate
+
+@c <!-- FIXME: This is a "changebar" section from the CMU CL manual.
+@c I (WHN 2002-07-14) am not very familiar with this content, so
+@c I'm not immediately prepared to try to update it for SBCL, and
+@c I'm not feeling masochistic enough to work to encourage this
+@c kind of low-level hack anyway. However, I acknowledge that callbacks
+@c are sometimes really really necessary, so I include the original
+@c text in case someone is hard-core enough to benefit from it. If
+@c anyone brings the information up to date for SBCL, it belong
+@c either in the main manual or on a CLiki SBCL Internals page.
+@c LaTeX \subsection{Accessing Lisp Arrays}
+@c LaTeX
+@c LaTeX Due to the way \cmucl{} manages memory, the amount of memory that can
+@c LaTeX be dynamically allocated by \code{malloc} or \funref{make-alien} is
+@c LaTeX limited\footnote{\cmucl{} mmaps a large piece of memory for it's own
+@c LaTeX use and this memory is typically about 8 MB above the start of the C
+@c LaTeX heap. Thus, only about 8 MB of memory can be dynamically
+@c LaTeX allocated.}.
+
+@c Empirically determined to be considerably >8Mb on this x86 linux
+@c machine, but I don't know what the actual values are - dan 2003.09.01
+
+@c Note that this technique is used in SB-GROVEL in the SBCL contrib
+
+@c LaTeX
+@c LaTeX To overcome this limitation, it is possible to access the content of
+@c LaTeX Lisp arrays which are limited only by the amount of physical memory
+@c LaTeX and swap space available. However, this technique is only useful if
+@c LaTeX the foreign function takes pointers to memory instead of allocating
+@c LaTeX memory for itself. In latter case, you will have to modify the
+@c LaTeX foreign functions.
+@c LaTeX
+@c LaTeX This technique takes advantage of the fact that \cmucl{} has
+@c LaTeX specialized array types (\pxlref{specialized-array-types}) that match
+@c LaTeX a typical C array. For example, a \code{(simple-array double-float
+@c LaTeX (100))} is stored in memory in essentially the same way as the C
+@c LaTeX array \code{double x[100]} would be. The following function allows us
+@c LaTeX to get the physical address of such a Lisp array:
+@c LaTeX \begin{example}
+@c LaTeX (defun array-data-address (array)
+@c LaTeX "Return the physical address of where the actual data of an array is
+@c LaTeX stored.
+@c LaTeX
+@c LaTeX ARRAY must be a specialized array type in CMU Lisp. This means ARRAY
+@c LaTeX must be an array of one of the following types:
+@c LaTeX
+@c LaTeX double-float
+@c LaTeX single-float
+@c LaTeX (unsigned-byte 32)
+@c LaTeX (unsigned-byte 16)
+@c LaTeX (unsigned-byte 8)
+@c LaTeX (signed-byte 32)
+@c LaTeX (signed-byte 16)
+@c LaTeX (signed-byte 8)
+@c LaTeX "
+@c LaTeX (declare (type (or #+signed-array (array (signed-byte 8))
+@c LaTeX #+signed-array (array (signed-byte 16))
+@c LaTeX #+signed-array (array (signed-byte 32))
+@c LaTeX (array (unsigned-byte 8))
+@c LaTeX (array (unsigned-byte 16))
+@c LaTeX (array (unsigned-byte 32))
+@c LaTeX (array single-float)
+@c LaTeX (array double-float))
+@c LaTeX array)
+@c LaTeX (optimize (speed 3) (safety 0))
+@c LaTeX (ext:optimize-interface (safety 3)))
+@c LaTeX ;; with-array-data will get us to the actual data. However, because
+@c LaTeX ;; the array could have been displaced, we need to know where the
+@c LaTeX ;; data starts.
+@c LaTeX (lisp::with-array-data ((data array)
+@c LaTeX (start)
+@c LaTeX (end))
+@c LaTeX (declare (ignore end))
+@c LaTeX ;; DATA is a specialized simple-array. Memory is laid out like this:
+@c LaTeX ;;
+@c LaTeX ;; byte offset Value
+@c LaTeX ;; 0 type code (should be 70 for double-float vector)
+@c LaTeX ;; 4 4 * number of elements in vector
+@c LaTeX ;; 8 1st element of vector
+@c LaTeX ;; ... ...
+@c LaTeX ;;
+@c LaTeX (let ((addr (+ 8 (logandc1 7 (kernel:get-lisp-obj-address data))))
+@c LaTeX (type-size (let ((type (array-element-type data)))
+@c LaTeX (cond ((or (equal type '(signed-byte 8))
+@c LaTeX (equal type '(unsigned-byte 8)))
+@c LaTeX 1)
+@c LaTeX ((or (equal type '(signed-byte 16))
+@c LaTeX (equal type '(unsigned-byte 16)))
+@c LaTeX 2)
+@c LaTeX ((or (equal type '(signed-byte 32))
+@c LaTeX (equal type '(unsigned-byte 32)))
+@c LaTeX 4)
+@c LaTeX ((equal type 'single-float)
+@c LaTeX 4)
+@c LaTeX ((equal type 'double-float)
+@c LaTeX 8)
+@c LaTeX (t
+@c LaTeX (error "Unknown specialized array element type"))))))
+@c LaTeX (declare (type (unsigned-byte 32) addr)
+@c LaTeX (optimize (speed 3) (safety 0) (ext:inhibit-warnings 3)))
+@c LaTeX (system:int-sap (the (unsigned-byte 32)
+@c LaTeX (+ addr (* type-size start)))))))
+@c LaTeX \end{example}
+@c LaTeX
+@c LaTeX Assume we have the C function below that we wish to use:
+@c LaTeX \begin{example}
+@c LaTeX double dotprod(double* x, double* y, int n)
+@c LaTeX \{
+@c LaTeX int k;
+@c LaTeX double sum = 0;
+@c LaTeX
+@c LaTeX for (k = 0; k < n; ++k) \{
+@c LaTeX sum += x[k] * y[k];
+@c LaTeX \}
+@c LaTeX \}
+@c LaTeX \end{example}
+@c LaTeX The following example generates two large arrays in Lisp, and calls the C
+@c LaTeX function to do the desired computation. This would not have been
+@c LaTeX possible using \code{malloc} or \code{make-alien} since we need about
+@c LaTeX 16 MB of memory to hold the two arrays.
+@c LaTeX \begin{example}
+@c LaTeX (define-alien-routine "dotprod" double
+@c LaTeX (x (* double-float) :in)
+@c LaTeX (y (* double-float) :in)
+@c LaTeX (n int :in))
+@c LaTeX
+@c LaTeX (let ((x (make-array 1000000 :element-type 'double-float))
+@c LaTeX (y (make-array 1000000 :element-type 'double-float)))
+@c LaTeX ;; Initialize X and Y somehow
+@c LaTeX (let ((x-addr (system:int-sap (array-data-address x)))
+@c LaTeX (y-addr (system:int-sap (array-data-address y))))
+@c LaTeX (dotprod x-addr y-addr 1000000)))
+@c LaTeX \end{example}
+@c LaTeX In this example, it may be useful to wrap the inner \code{let}
+@c LaTeX expression in an \code{unwind-protect} that first turns off garbage
+@c LaTeX collection and then turns garbage collection on afterwards. This will
+@c LaTeX prevent garbage collection from moving \code{x} and \code{y} after we
+@c LaTeX have obtained the (now erroneous) addresses but before the call to
+@c LaTeX \code{dotprod} is made.
+@c LaTeX
+@c -->
+
+
+@node Step-By-Step Example of the Foreign Function Interface, , Foreign Function Calls, The Foreign Function Interface
+@comment node-name, next, previous, up
+@section Step-By-Step Example of the Foreign Function Interface
+
+This section presents a complete example of an interface to a somewhat
+complicated C function.
+
+Suppose you have the following C function which you want to be able to
+call from Lisp in the file @file{test.c}
+
+@example
+struct c_struct
+@{
+ int x;
+ char *s;
+@};
+
+struct c_struct *c_function (i, s, r, a)
+ int i;
+ char *s;
+ struct c_struct *r;
+ int a[10];
+@{
+ int j;
+ struct c_struct *r2;
+
+ printf("i = %d\n", i);
+ printf("s = %s\n", s);
+ printf("r->x = %d\n", r->x);
+ printf("r->s = %s\n", r->s);
+ for (j = 0; j < 10; j++) printf("a[%d] = %d.\n", j, a[j]);
+ r2 = (struct c_struct *) malloc (sizeof(struct c_struct));
+ r2->x = i + 5;
+ r2->s = "a C string";
+ return(r2);
+@};
+@end example
+
+It is possible to call this C function from Lisp using the file
+@file{test.lisp} containing
+
+@lisp
+(cl:defpackage "TEST-C-CALL" (:use "CL" "SB-ALIEN" "SB-C-CALL"))
+(cl:in-package "TEST-C-CALL")
+
+;;; Define the record C-STRUCT in Lisp.
+(define-alien-type nil
+ (struct c-struct
+ (x int)
+ (s c-string)))
+
+;;; Define the Lisp function interface to the C routine. It returns a
+;;; pointer to a record of type C-STRUCT. It accepts four parameters:
+;;; I, an int; S, a pointer to a string; R, a pointer to a C-STRUCT
+;;; record; and A, a pointer to the array of 10 ints.
+;;;
+;;; The INLINE declaration eliminates some efficiency notes about heap
+;;; allocation of alien values.
+(declaim (inline c-function))
+(define-alien-routine c-function
+ (* (struct c-struct))
+ (i int)
+ (s c-string)
+ (r (* (struct c-struct)))
+ (a (array int 10)))
+
+;;; a function which sets up the parameters to the C function and
+;;; actually calls it
+(defun call-cfun ()
+ (with-alien ((ar (array int 10))
+ (c-struct (struct c-struct)))
+ (dotimes (i 10) ; Fill array.
+ (setf (deref ar i) i))
+ (setf (slot c-struct 'x) 20)
+ (setf (slot c-struct 's) "a Lisp string")
+
+ (with-alien ((res (* (struct c-struct))
+ (c-function 5 "another Lisp string" (addr c-struct) ar)))
+ (format t "~&back from C function~%")
+ (multiple-value-prog1
+ (values (slot res 'x)
+ (slot res 's))
+
+ ;; Deallocate result. (after we are done referring to it:
+ ;; "Pillage, *then* burn.")
+ (free-alien res)))))
+@end lisp
+
+To execute the above example, it is necessary to compile the C
+routine, e.g.: @samp{cc -c test.c} (In order to enable incremental
+loading with some linkers, you may need to say @samp{cc -G 0 -c
+test.c})
+
+Once the C code has been compiled, you can start up Lisp and load it
+in: @samp{sbcl} Lisp should start up with its normal prompt.
+
+Within Lisp, compile the Lisp file. (This step can be done
+separately. You don't have to recompile every time.)
+@samp{(compile-file "test.lisp")}
+
+Within Lisp, load the foreign object file to define the necessary
+symbols: @samp{(load-foreign "test.o")}. This must be done before
+loading any code that refers to these symbols.
+
+Now you can load the compiled Lisp (``fasl'') file into Lisp:
+@samp{(load "test.fasl")}
+And once the Lisp file is loaded, you can call the
+Lisp routine that sets up the parameters and calls the C
+function:
+@samp{(test-c-call::call-cfun)}
+
+The C routine should print the following information to standard output:
+
+@example
+i = 5
+s = another Lisp string
+r->x = 20
+r->s = a Lisp string
+a[0] = 0.
+a[1] = 1.
+a[2] = 2.
+a[3] = 3.
+a[4] = 4.
+a[5] = 5.
+a[6] = 6.
+a[7] = 7.
+a[8] = 8.
+a[9] = 9.
+@end example
+
+After return from the C function,
+the Lisp wrapper function should print the following output:
+
+@example
+back from C function
+@end example
+
+And upon return from the Lisp wrapper function,
+before the next prompt is printed, the
+Lisp read-eval-print loop should print the following return values:
+
+@example
+10
+"a C string"
+@end example
--- /dev/null
+@node Introduction, The Compiler, Top, Top
+@comment node-name, next, previous, up
+@chapter Introduction
+
+SBCL is a mostly-conforming implementation of the ANSI Common Lisp
+standard. This manual focuses on behavior which is specific to SBCL,
+not on behavior which is common to all implementations of ANSI Common
+Lisp.
+
+@menu
+* More Common Lisp Information::
+* More SBCL Information::
+* Overview::
+@end menu
+
+@node More Common Lisp Information, More SBCL Information, Introduction, Introduction
+@comment node-name, next, previous, up
+@section Where To Go For More Information about Common Lisp in General
+
+Regardless of your ability level, two very useful resources for
+working with any implementation of Common Lisp are the ILISP package
+for Emacs at @uref{http://ilisp.cons.org} and the Common Lisp HyperSpec
+at @uref{http://www.lispworks.com/reference/HyperSpec/index.html}.
+
+If you're not a programmer and you're trying to learn, many
+introductory Lisp books are available. However, we don't have any
+standout favorites. If you can't decide, try checking the Usenet
+comp.lang.lisp FAQ for recent recommendations.
+
+If you are an experienced programmer in other languages but need to
+learn about Lisp, three books stand out.
+
+@itemize
+
+@item
+@emph{ANSI Common Lisp}, by Paul Graham, will teach you
+about most of the language. (And later it might also be worth checking
+out @emph{On Lisp}, by the same author.)
+
+@item
+@emph{Paradigms Of Artificial Intelligence
+Programming}, by Peter Norvig, also has some good information on
+general Common Lisp programming, and many nontrivial examples.
+Whether or not your work is AI, it's a very good book to look at.
+
+@item
+Neither of the books above emphasizes CLOS, but @emph{Object-Oriented
+Programming In Common Lisp} by Sonya Keene does. Even if you're very
+knowledgeable about object oriented programming in the abstract, it's
+worth looking at this book if you want to do any OO in Common
+Lisp. Some abstractions in CLOS (especially multiple dispatch) go
+beyond anything you'll see in most OO systems, and there are a number
+of lesser differences as well. This book tends to help with the
+culture shock.
+
+@end itemize
+
+
+@node More SBCL Information, Overview, More Common Lisp Information, Introduction
+@comment node-name, next, previous, up
+@section Where To Go For More Information About SBCL
+
+Before you read this user manual, you should probably read two other
+things.
+
+@itemize
+
+@item
+You should know how to program in Common Lisp. If you don't already
+know how, you should probably read a book on it. @xref{More Common
+Lisp Information}.
+
+@item
+The Unix ``man page'' for SBCL will tell you
+how to start the SBCL environment, so you can get to the classic
+``hello, world'' level of knowledge. It's the file called
+@file{sbcl.1} in the SBCL distribution. If SBCL is installed on your
+system, you can read a formatted copy by executing the command
+@samp{man sbcl}.
+
+@end itemize
+
+
+Besides this user manual and the Unix man page, some other
+SBCL-specific information is available:
+
+@itemize
+
+@item
+The SBCL home page at @uref{http://sbcl.sourceforge.net/} has some
+general information, plus links to mailing lists devoted to SBCL, and
+to archives of these mailing lists.
+
+@item
+Documentation for non-ANSI extensions for various commands is
+available online from the SBCL executable itself. The extensions for
+functions which have their own command prompts (e.g. the debugger, and
+@code{inspect}) are documented in text available by typing
+@command{help} at their command prompts. The extensions for functions
+which don't have their own command prompt (like @code{trace} does) are
+described in their documentation strings, unless your SBCL was
+compiled with an option not to include documentation strings, in which
+case the doc strings are only readable in the source code.
+
+@item
+Some low-level information describing the programming details of the
+conversion from CMUCL to SBCL is available in the
+@file{doc/FOR-CMUCL-DEVELOPERS} file in the SBCL
+distribution.
+
+@end itemize
+
+
+@node Overview, , More SBCL Information, Introduction
+@comment node-name, next, previous, up
+@section Overview Of SBCL, How It Works And Where It Came From
+
+You can work productively with SBCL without knowing anything
+understanding anything about where it came from, how it is
+implemented, or how it extends the ANSI Common Lisp standard. However,
+a little knowledge can be helpful in order to understand error
+messages, to troubleshoot problems, to understand why some parts of
+the system are better debugged than others, and to anticipate which
+known bugs, known performance problems, and missing extensions are
+likely to be fixed, tuned, or added.
+
+SBCL is descended from CMUCL, which is itself descended from Spice
+Lisp, including early implementations for the Mach operating system on
+the IBM RT, back in the 1980s. Design decisions from that time are
+still reflected in the current implementation:
+
+@itemize
+
+@item
+The system expects to be loaded into a fixed-at-compile-time location
+in virtual memory, and also expects the location of all of its heap
+storage to be specified at compile time.
+
+@item
+The system overcommits memory, allocating large amounts of address
+space from the system (often more than the amount of virtual memory
+available) and then failing if ends up using too much of the allocated
+storage.
+
+@item
+A word is a 32-bit quantity. The system has been ported to many
+processor architectures without altering this basic principle. Some
+hacks allow the system to run on the Alpha chip (a 64-bit
+architecture) but even there 32-bit words are used. The assumption
+that a word is 32 bits wide is implicit in hundreds of places in the
+system.
+
+@item
+The system is implemented as a C program which is responsible for
+supplying low-level services and loading a Lisp @file{.core}
+file.
+
+@end itemize
+
+SBCL also inherited some newer architectural features from CMUCL. The
+most important is that on some architectures it has a generational
+garbage collector (``GC''), which has various implications (mostly
+good) for performance. These are discussed another chapter,
+@ref{Efficiency}.
+
+SBCL has diverged from CMUCL in that SBCL is now essentially a
+``compiler-only implementation'' of Common Lisp. A Common Lisp
+implementation is permitted to implement both a compiler and an
+interpreter, and there's some special support in the standard
+(e.g. the distinction between @code{functionp} and
+@code{compiled-function-p}) to help support that. But SBCL has only a
+vestigial, rudimentary true interpreter. In SBCL, the @code{eval}
+function only truly ``interprets'' a few special classes of forms,
+such as symbols which are @code{boundp}. More complicated forms are
+evaluated by calling @code{compile} and then calling @code{funcall} on
+the returned result.
+
+
+The direct ancestor of SBCL is the X86 port of CMUCL. This port was in
+some ways the most cobbled-together of all the CMUCL ports, since a
+number of strange changes had to be made to support the register-poor
+X86 architecture. Some things (like tracing and debugging) do not work
+particularly well there. SBCL should be able to improve in these areas
+(and has already improved in some other areas), but it takes a while.
+
+On the x86, SBCL like the X86 port of CMUCL, uses a
+@emph{conservative} GC. This means that it doesn't maintain a strict
+separation between tagged and untagged data, instead treating some
+untagged data (e.g. raw floating point numbers) as possibly-tagged
+data and so not collecting any Lisp objects that they point to. This
+has some negative consequences for average time efficiency (though
+possibly no worse than the negative consequences of trying to
+implement an exact GC on a processor architecture as register-poor as
+the X86) and also has potentially unlimited consequences for
+worst-case memory efficiency. In practice, conservative garbage
+collectors work reasonably well, not getting anywhere near the worst
+case. But they can occasionally cause odd patterns of memory usage.
+
+The fork from CMUCL was based on a major rewrite of the system
+bootstrap process. CMUCL has for many years tolerated a very unusual
+``build'' procedure which doesn't actually build the complete system
+from scratch, but instead progressively overwrites parts of a running
+system with new versions. This quasi-build procedure can cause various
+bizarre bootstrapping hangups, especially when a major change is made
+to the system. It also makes the connection between the current source
+code and the current executable more tenuous than in other software
+systems -- it's easy to accidentally ``build'' a CMUCL system
+containing characteristics not reflected in the current version of the
+source code.
+
+Other major changes since the fork from CMUCL include
+
+@itemize
+
+@item
+SBCL has dropped support for many CMUCL extensions, (e.g. IP
+networking, remote procedure call, Unix system interface, and X11
+interface). Most of these are now available as contributed or
+third-party modules.
+
+@item
+SBCL has deleted or deprecated some nonstandard features and code
+complexity which helped efficiency at the price of
+maintainability. For example, the SBCL compiler no longer implements
+memory pooling internally (and so is simpler and more maintainable,
+but generates more garbage and runs more slowly), and various
+block-compilation efficiency-increasing extensions to the language
+have been deleted or are no longer used in the implementation of SBCL
+itself.
+
+@end itemize
--- /dev/null
+\input texinfo @c -*-texinfo-*-
+@c %**start of header
+@setfilename sbcl.info
+@settitle SBCL User Manual
+@c %**end of header
+
+
+@set EDITION 0.1
+@set VERSION 0.8.9
+@set UPDATED 2 April 2004
+@set UPDATE-MONTH April 2004
+
+
+@copying
+
+@quotation
+This manual is part of the SBCL software system. See the @file{README} file
+for more information.
+
+This manual is largely derived from the manual for the CMUCL system,
+which was produced at Carnegie Mellon University and later released
+into the public domain. This manual is in the public domain and is
+provided with absolutely no warranty. See the @file{COPYING} and
+@file{CREDITS} files for more information.
+@end quotation
+
+@end copying
+
+@titlepage
+
+@title SBCL User Manual
+@subtitle SBCL Version @value{VERSION}
+@subtitle @value{UPDATE-MONTH}
+@c @author The CMUCL and SBCL teams
+
+
+@c The following two commands start the copyright page.
+@page
+@vskip 0pt plus 1filll
+@insertcopying
+
+@end titlepage
+
+@contents
+
+@ifnottex
+
+@node Top, Introduction, (dir), (dir)
+@comment node-name, next, previous, up
+@top SBCL
+
+@insertcopying
+
+@menu
+* Introduction::
+* The Compiler::
+* The Debugger::
+* Efficiency::
+* Beyond The ANSI Standard::
+* The Foreign Function Interface::
+* Function Index::
+* Concept Index::
+* Colophon::
+
+@detailmenu
+ --- The Detailed Node Listing ---
+
+Introduction
+
+* More Common Lisp Information::
+* More SBCL Information::
+* Overview::
+
+The Compiler
+
+* Error Messages::
+* Handling of Types::
+* Compiler Policy::
+* Open Coding and Inline Expansion::
+
+Error Messages
+
+* The Parts of the Error Message::
+* The Original and Actual Source::
+* Error Severity::
+* Errors During Macroexpansion::
+* Read Errors::
+
+The Compiler's Handling of Types
+
+* Implementation Limitations::
+* Type Errors at Compile Time::
+* Precise Type Checking::
+* Weakened Type Checking::
+* Getting Existing Programs to Run::
+
+The Debugger
+
+* Starting the Debugger::
+* The Debugger Command Loop::
+* Controlling Printing in the Debugger::
+* Stack Frames::
+* Variable Access::
+* Source Location Printing::
+* Debugger Policy Control::
+* Exiting Commands::
+* Information Commands::
+* Function Tracing::
+
+Stack Frames
+
+* Stack Motion::
+* How Arguments are Printed::
+* Function Names::
+* Funny Frames::
+* Debug Tail Recursion::
+* Unknown Locations and Interrupts::
+
+Variable Access
+
+* Variable Value Availability::
+* Note On Lexical Variable Access::
+
+Source Location Printing
+
+* How the Source is Found::
+* Source Location Availability::
+
+Efficiency
+
+* Dynamic-extent allocation::
+* Modular arithmetic::
+
+Beyond The ANSI Standard
+
+* Non-Conformance With The ANSI Standard::
+* Idiosyncrasies::
+* Extensions::
+
+Extensions
+
+* Things Which Might Be In The Next ANSI Standard::
+* Threading::
+* Support For Unix::
+* Customization Hooks for Users::
+* Tools To Help Developers::
+* Interface To Low-Level SBCL Implementation::
+* Efficiency Hacks::
+
+The Foreign Function Interface
+
+* Introduction to the Foreign Function Interface::
+* Foreign Types::
+* Operations On Foreign Values::
+* Foreign Variables::
+* Foreign Data Structure Examples::
+* Loading Unix Object Files::
+* Foreign Function Calls::
+* Step-By-Step Example of the Foreign Function Interface::
+
+Foreign Types
+
+* Defining Foreign Types::
+* Foreign Types and Lisp Types::
+* Foreign Type Specifiers::
+
+Operations On Foreign Values
+
+* Accessing Foreign Values::
+* Coercing Foreign Values::
+* Foreign Dynamic Allocation::
+
+Foreign Variables
+
+* Local Foreign Variables::
+* External Foreign Variables::
+
+Foreign Function Calls
+
+* The alien-funcall Primitive::
+* The define-alien-routine Macro::
+* define-alien-routine Example::
+* Calling Lisp From C::
+
+@end detailmenu
+@end menu
+
+@end ifnottex
+
+@include intro.texinfo
+@include compiler.texinfo
+@include debugger.texinfo
+@include efficiency.texinfo
+@include beyond-ansi.texinfo
+@include ffi.texinfo
+@include backmatter.texinfo
+
+@bye
"ERROR-TRAP" "EVEN-FIXNUM-LOWTAG"
"EXPORTED-STATIC-SYMBOLS" "EXTERN-ALIEN-NAME"
"FDEFN-FUN-SLOT" "FDEFN-NAME-SLOT" "FDEFN-RAW-ADDR-SLOT"
- "FDEFN-SIZE" "FDEFN-WIDETAG" "FIND-HOLES" "FIXNUMIZE"
+ "FDEFN-SIZE" "FDEFN-WIDETAG" "FIXNUMIZE"
"FIXUP-CODE-OBJECT" "FLOAT-DENORMAL-TRAP-BIT"
"FLOAT-DIVIDE-BY-ZERO-TRAP-BIT"
"FLOAT-IMPRECISE-TRAP-BIT" "FLOAT-INVALID-TRAP-BIT"
\f
;;;; putting ourselves out of our misery when things become too much to bear
-(declaim (ftype (function (simple-string) nil) critically-unreachable))
+(declaim (ftype (function (simple-string) nil) !cold-lose))
(defun !cold-lose (msg)
(%primitive print msg)
(%primitive print "too early in cold init to recover from errors")
;; call site.
(set-floating-point-modes
:traps '(:overflow #!-netbsd :invalid :divide-by-zero))
- (sb!thread::maybe-install-futex-functions)
-
- ;; Clear pseudo atomic in case this core wasn't compiled with
- ;; support.
- ;;
- ;; FIXME: In SBCL our cores are always compiled with support. So
- ;; we don't need to do this, do we? At least not for this
- ;; reason.. (Perhaps we should do it anyway in case someone
- ;; manages to save an image from within a pseudo-atomic-atomic
- ;; operation?)
- #!+x86 (setf *pseudo-atomic-atomic* 0)))
+ (sb!thread::maybe-install-futex-functions)))
(gc-on)
(gc))
\f
(defconstant most-positive-double-float
(double-from-bits 0 sb!vm:double-float-normal-exponent-max
(ldb (byte sb!vm:double-float-digits 0) -1)))
-#!-long-float
+
(defconstant most-positive-long-float most-positive-double-float)
-#!+(and long-float x86)
-(defconstant most-positive-long-float
- (long-from-bits 0 sb!vm:long-float-normal-exponent-max
- (ldb (byte sb!vm:long-float-digits 0) -1)))
+
(defconstant most-negative-double-float
(double-from-bits 1 sb!vm:double-float-normal-exponent-max
(ldb (byte sb!vm:double-float-digits 0) -1)))
-#!-long-float
(defconstant most-negative-long-float most-negative-double-float)
-#!+(and long-float x86)
-(defconstant most-negative-long-float
- (long-from-bits 1 sb!vm:long-float-normal-exponent-max
- (ldb (byte sb!vm:long-float-digits 0) -1)))
;;; We don't want to do these DEFCONSTANTs at cross-compilation time,
;;; because the cross-compilation host might not support floating
'(make-single-float (fast-read-s-integer 4)))
(fast-read-double-float ()
'(let ((lo (fast-read-u-integer 4)))
- (make-double-float (fast-read-s-integer 4) lo)))
- #!+long-float
- (fast-read-long-float ()
- '(let ((lo (fast-read-u-integer 4))
- #!+sparc (mid (fast-read-u-integer 4))
- (hi (fast-read-u-integer 4)) ; XXX
- (exp (fast-read-s-integer #!+x86 2 #!+sparc 4)))
- (make-long-float exp hi #!+sparc mid lo))))
+ (make-double-float (fast-read-s-integer 4) lo))))
(macrolet ((define-complex-fop (name fop-code type)
(let ((reader (symbolicate "FAST-READ-" type)))
`(define-fop (,name ,fop-code)
(read-n-bytes *fasl-input-stream* result 0 (* length sb!vm:n-word-bytes 2))
result))
-#!+long-float
-(define-fop (fop-long-float-vector 88)
- (let* ((length (read-arg 4))
- (result (make-array length :element-type 'long-float)))
- (read-n-bytes *fasl-input-stream*
- result
- 0
- (* length sb!vm:n-word-bytes #!+x86 3 #!+sparc 4))
- result))
-
(define-fop (fop-complex-single-float-vector 86)
(let* ((length (read-arg 4))
(result (make-array length :element-type '(complex single-float))))
(* length sb!vm:n-word-bytes 2 2))
result))
-#!+long-float
-(define-fop (fop-complex-long-float-vector 89)
- (let* ((length (read-arg 4))
- (result (make-array length :element-type '(complex long-float))))
- (read-n-bytes *fasl-input-stream* result 0
- (* length sb!vm:n-word-bytes #!+x86 3 #!+sparc 4 2))
- result))
-
;;; CMU CL comment:
;;; *** NOT *** the FOP-INT-VECTOR as currently documented in rtguts.
;;; Size must be a directly supported I-vector element size, with no
(declare (ignore type))
`(sap-ref-double ,sap (/ ,offset sb!vm:n-byte-bits)))
-#!+long-float
-(define-alien-type-class (long-float :include (float (bits #!+x86 96
- #!+sparc 128))
- :include-args (type)))
-
-#!+long-float
-(define-alien-type-translator long-float ()
- (make-alien-long-float-type :type 'long-float))
-
-#!+long-float
-(define-alien-type-method (long-float :extract-gen) (type sap offset)
- (declare (ignore type))
- `(sap-ref-long ,sap (/ ,offset sb!vm:n-byte-bits)))
\f
;;;; the POINTER type
(sort time-info-list
#'>=
:key #'time-info-seconds))
+ (print-profile-table time-info-list)
- (format *trace-output*
- "~& seconds | consed | calls | sec/call | name~@
- ------------------------------------------------------~%")
+ (when no-call-name-list
+ (format *trace-output*
+ "~%These functions were not called:~%~{~<~%~:; ~S~>~}~%"
+ (sort no-call-name-list #'string<
+ :key (lambda (name)
+ (symbol-name (fun-name-block-name name))))))
+
+ (values)))
+
+
+(defun print-profile-table (time-info-list)
+ (let ((total-seconds 0.0)
+ (total-consed 0)
+ (total-calls 0)
+ (seconds-width (length "seconds"))
+ (consed-width (length "consed"))
+ (calls-width (length "calls"))
+ (sec/call-width 10)
+ (name-width 6))
+ (dolist (time-info time-info-list)
+ (incf total-seconds (time-info-seconds time-info))
+ (incf total-consed (time-info-consing time-info))
+ (incf total-calls (time-info-calls time-info)))
+ (setf seconds-width (max (length (format nil "~10,3F" total-seconds))
+ seconds-width)
+ calls-width (max (length (format nil "~:D" total-calls))
+ calls-width)
+ consed-width (max (length (format nil "~:D" total-consed))
+ consed-width))
+
+ (flet ((dashes ()
+ (dotimes (i (+ seconds-width consed-width calls-width
+ sec/call-width name-width
+ (* 5 3)))
+ (write-char #\- *trace-output*))
+ (terpri *trace-output*)))
+ (format *trace-output* "~&~@{ ~v:@<~A~>~^|~}~%"
+ seconds-width "seconds"
+ (1+ consed-width) "consed"
+ (1+ calls-width) "calls"
+ (1+ sec/call-width) "sec/call"
+ (1+ name-width) "name")
+
+ (dashes)
- (let ((total-time 0.0)
- (total-consed 0)
- (total-calls 0))
(dolist (time-info time-info-list)
- (incf total-time (time-info-seconds time-info))
- (incf total-calls (time-info-calls time-info))
- (incf total-consed (time-info-consing time-info))
- (format *trace-output*
- "~10,3F | ~9:D | ~7:D | ~10,6F | ~S~%"
- (time-info-seconds time-info)
- (time-info-consing time-info)
- (time-info-calls time-info)
- (/ (time-info-seconds time-info)
- (float (time-info-calls time-info)))
- (time-info-name time-info)))
- (format *trace-output*
- "------------------------------------------------------~@
- ~10,3F | ~9:D | ~7:D | | Total~%"
- total-time total-consed total-calls)
+ (format *trace-output* "~v,3F | ~v:D | ~v:D | ~10,6F | ~S~%"
+ seconds-width (time-info-seconds time-info)
+ consed-width (time-info-consing time-info)
+ calls-width (time-info-calls time-info)
+ (/ (time-info-seconds time-info)
+ (float (time-info-calls time-info)))
+ (time-info-name time-info)))
+
+ (dashes)
+
+ (format *trace-output* "~v,3F | ~v:D | ~v:D | | Total~%"
+ seconds-width total-seconds
+ consed-width total-consed
+ calls-width total-calls)
+
(format *trace-output*
"~%estimated total profiling overhead: ~4,2F seconds~%"
(* (overhead-total *overhead*) (float total-calls)))
"~&overhead estimation parameters:~% ~Ss/call, ~Ss total profiling, ~Ss internal profiling~%"
(overhead-call *overhead*)
(overhead-total *overhead*)
- (overhead-internal *overhead*)))
+ (overhead-internal *overhead*)))))
- (when no-call-name-list
- (format *trace-output*
- "~%These functions were not called:~%~{~<~%~:; ~S~>~}~%"
- (sort no-call-name-list #'string<
- :key (lambda (name)
- (symbol-name (fun-name-block-name name))))))
-
- (values)))
\f
;;;; overhead estimation
(values))
\f
-(defun find-holes (&rest spaces)
- (dolist (space (or spaces '(:read-only :static :dynamic)))
- (format t "In ~A space:~%" space)
- (let ((start-addr nil)
- (total-bytes 0))
- (declare (type (or null (unsigned-byte 32)) start-addr)
- (type (unsigned-byte 32) total-bytes))
- (map-allocated-objects
- (lambda (object typecode bytes)
- (declare (ignore typecode)
- (type (unsigned-byte 32) bytes))
- (if (and (consp object)
- (eql (car object) 0)
- (eql (cdr object) 0))
- (if start-addr
- (incf total-bytes bytes)
- (setf start-addr (sb!di::get-lisp-obj-address object)
- total-bytes bytes))
- (when start-addr
- (format t "~:D bytes at #X~X~%" total-bytes start-addr)
- (setf start-addr nil))))
- space)
- (when start-addr
- (format t "~:D bytes at #X~X~%" total-bytes start-addr))))
- (values))
-\f
;;;; PRINT-ALLOCATED-OBJECTS
(defun print-allocated-objects (space &key (percent 0) (pages 5)
tto)
(format t " loading to the dynamic space~%"))
- (let ((code (%primitive sb!c:allocate-dynamic-code-object
+ (let ((code (%primitive sb!c:allocate-code-object
box-num
code-length))
(index (+ sb!vm:code-trace-table-offset-slot box-num)))
of the default random state. If STATE is a random state, then return a
copy of it. If STATE is T then return a random state generated from
the universal time."
- (/show0 "entering !RANDOM-COLD-INIT")
+ (/show0 "entering MAKE-RANDOM-STATE")
(flet ((copy-random-state (state)
(/show0 "entering COPY-RANDOM-STATE")
(let ((state (random-state-state state))
(sb!vm::random-mt19937 state-vector))
1d0))))
-#!+long-float
-(declaim #!-sb-fluid (inline %random-long-float))
-#!+long-float
-(declaim (ftype (function ((long-float (0l0)) random-state) (long-float 0l0))
- %random-long-float))
-
-;;; using a faster inline VOP
-#!+(and long-float x86)
-(defun %random-long-float (arg state)
- (declare (type (long-float (0l0)) arg)
- (type random-state state))
- (let ((state-vector (random-state-state state)))
- (* arg
- (- (sb!impl::make-long-float
- (sb!impl::long-float-exp-bits 1l0)
- (logior (sb!vm::random-mt19937 state-vector)
- sb!vm:long-float-hidden-bit)
- (sb!vm::random-mt19937 state-vector))
- 1l0))))
-
-#!+(and long-float sparc)
-(defun %random-long-float (arg state)
- (declare (type (long-float (0l0)) arg)
- (type random-state state))
- (* arg
- (- (sb!impl::make-long-float
- (sb!impl::long-float-exp-bits 1l0) ; X needs more work
- (random-chunk state) (random-chunk state) (random-chunk state))
- 1l0)))
\f
;;;; random integers
(define-vop (listify-rest-args)
(:args (context-arg :target context :scs (descriptor-reg))
(count-arg :target count :scs (any-reg)))
- (:arg-types * tagged-num)
+ (:info dx)
+ (:ignore dx)
+ (:arg-types * tagged-num (:constant t))
(:temporary (:scs (any-reg) :from (:argument 0)) context)
(:temporary (:scs (any-reg) :from (:argument 1)) count)
(:temporary (:scs (descriptor-reg) :from :eval) temp dst)
(setf (segment-postits segment) (segment-postits other-segment))
(dolist (postit postits)
(emit-back-patch segment 0 postit)))
- #!-x86 (emit-alignment segment nil max-alignment)
- #!+x86 (emit-alignment segment nil max-alignment #x90)
+ (emit-alignment segment nil max-alignment #!+(or x86-64 x86) #x90)
(let ((segment-current-index-0 (segment-current-index segment))
(segment-current-posn-0 (segment-current-posn segment)))
(incf (segment-current-index segment)
nil)
((basic-combination-p dest)
(let ((kind (basic-combination-kind dest)))
- (cond ((eq cont (basic-combination-fun dest)) t)
- ((eq kind :local) t)
- ((eq kind :full)
- (and (combination-p dest)
- (not (values-subtypep ; explicit THE
- (continuation-externally-checkable-type cont)
- (continuation-type-to-check cont)))))
-
- ((eq kind :error) nil)
- ;; :ERROR means that we have an invalid syntax of
- ;; the call and the callee will detect it before
- ;; thinking about types.
-
- ((fun-info-ir2-convert kind) t)
- (t
- (dolist (template (fun-info-templates kind) nil)
- (when (eq (template-ltn-policy template) :fast-safe)
- (multiple-value-bind (val win)
- (valid-fun-use dest (template-type template))
- (when (or val (not win)) (return t)))))))))
+ (cond
+ ((eq cont (basic-combination-fun dest)) t)
+ (t
+ (ecase kind
+ (:local t)
+ (:full
+ (and (combination-p dest)
+ (not (values-subtypep ; explicit THE
+ (continuation-externally-checkable-type cont)
+ (continuation-type-to-check cont)))))
+ ;; :ERROR means that we have an invalid syntax of
+ ;; the call and the callee will detect it before
+ ;; thinking about types.
+ (:error nil)
+ (:known
+ (let ((info (basic-combination-fun-info dest)))
+ (if (fun-info-ir2-convert info)
+ t
+ (dolist (template (fun-info-templates info) nil)
+ (when (eq (template-ltn-policy template)
+ :fast-safe)
+ (multiple-value-bind (val win)
+ (valid-fun-use dest (template-type template))
+ (when (or val (not win)) (return t)))))))))))))
(t t))))
;;; Return a lambda form that we can convert to do a hairy type check
(let ((kind (basic-combination-kind node)))
(format t "~(~A~A ~A~) "
(if (node-tail-p node) "tail " "")
- (if (fun-info-p kind) "known" kind)
+ kind
(type-of node))
(print-lvar (basic-combination-fun node))
(dolist (arg (basic-combination-args node))
;;; the maximum alignment we can guarantee given the object format. If
;;; the loader only loads objects 8-byte aligned, we can't do any
;;; better then that ourselves.
-(def!constant max-alignment 3)
+(def!constant max-alignment sb!vm:n-lowtag-bits)
+
(deftype alignment ()
`(integer 0 ,max-alignment))
(defknown %cleanup-point () t)
(defknown %special-bind (t t) t)
(defknown %special-unbind (t) t)
-(defknown %listify-rest-args (t index) list (flushable))
+(defknown %dynamic-extent-start () t)
+(defknown %dynamic-extent-end () t)
+(defknown %listify-rest-args (t index t) list (flushable))
(defknown %more-arg-context (t t) (values t index) (flushable))
(defknown %more-arg (t index) t)
(defknown %more-arg-values (t index index) * (flushable))
;;; out the full names. Or even define them in DEF EVEN-FIXNUM-LOWTAG
;;; style so searches like 'def.*even-fixnum-lowtag' can find them.
-;;; Tags for the main low-level types are stored in the low three
+;;; Tags for the main low-level types are stored in the low n (usually three)
;;; bits to identify the type of a machine word. Certain constraints
;;; apply:
;;; * EVEN-FIXNUM-LOWTAG and ODD-FIXNUM-LOWTAG must be 0 and 4: code
;;; which shifts left two places to convert raw integers to tagged
;;; fixnums is ubiquitous.
-;;; * LIST-POINTER-LOWTAG + 4 = OTHER-POINTER-LOWTAG: NIL is both a
-;;; cons and a symbol (at the same address) and depends on this.
+;;; * LIST-POINTER-LOWTAG + N-WORD-BYTES = OTHER-POINTER-LOWTAG: NIL
+;;; is both a cons and a symbol (at the same address) and depends on this.
;;; See the definition of SYMBOL in objdef.lisp
;;; * OTHER-POINTER-LOWTAG > 4: Some code in the SPARC backend,
;;; which uses bit 2 of the ALLOC register to indicate that
;;; PSEUDO-ATOMIC is on, doesn't strip the low bits of reg_ALLOC
;;; before ORing in OTHER-POINTER-LOWTAG within a PSEUDO-ATOMIC
;;; section.
+;;; * OTHER-IMMEDIATE-0-LOWTAG are spaced 4 apart: various code wants to
+;;; iterate through these
;;; (These are just the ones we know about as of sbcl-0.7.1.22. There
;;; might easily be more, since these values have stayed highly
;;; constrained for more than a decade, an inviting target for
;; The EVAL-WHEN is necessary (at least for Lispworks), because the
;; second DEFENUM uses the value of OTHER-IMMEDIATE-0-LOWTAG, which is
;; defined in the first DEFENUM. -- AL 20000216
+ #!+x86-64
+ (defenum (:suffix -lowtag)
+ even-fixnum
+ instance-pointer
+ other-immediate-0
+ pad0 pad1 pad2
+ other-immediate-1
+ list-pointer
+ odd-fixnum
+ fun-pointer
+ other-immediate-2
+ pad3 pad4 pad5
+ other-immediate-3
+ other-pointer)
+ #!-x86-64
(defenum (:suffix -lowtag)
even-fixnum
- ;; Note: CMU CL, and SBCL < 0.pre7.39, had FUN-POINTER-LOWTAG
- ;; here. We swapped FUN-POINTER-LOWTAG and
- ;; INSTANCE-POINTER-LOWTAG in sbcl-0.pre7.39 in order to help with a
- ;; low-level pun in the function call sequence on the PPC port.
- ;; For more information, see the PPC port code. -- WHN 2001-10-03
instance-pointer
other-immediate-0
list-pointer
other-immediate-1
other-pointer))
+(def!constant nil-value
+ (+ static-space-start n-word-bytes other-pointer-lowtag))
+
;;; the heap types, stored in 8 bits of the header of an object on the
;;; heap, to identify the type of the heap object (which'll be at
;;; least two machine words, often more)
;;; rather than two separate tests and jumps
(defenum (:suffix -widetag
:start (+ (ash 1 n-lowtag-bits) other-immediate-0-lowtag)
- :step (ash 1 (1- n-lowtag-bits)))
+ :step 4)
bignum
ratio
single-float
double-float
- #!+long-float long-float
complex
complex-single-float
complex-double-float
- #!+long-float complex-long-float
code-header
simple-fun-header
unused05
unused06
unused07
- #!-long-float unused08
- #!-long-float unused09
+ unused08
+ unused09
- #!+long-float simple-array-long-float
- #!+long-float simple-array-complex-long-float
- #!-long-float unused10
- #!-long-float unused11
+ unused10
+ unused11
simple-array-unsigned-byte-2
simple-array-unsigned-byte-4
;;; the number of bits at the low end of a pointer used for type
;;; information
-(def!constant n-lowtag-bits 3)
+(def!constant n-lowtag-bits
+ (integer-length (1- (/ (* 2 n-word-bits) n-byte-bits))))
;;; a mask to extract the low tag bits from a pointer
(def!constant lowtag-mask (1- (ash 1 n-lowtag-bits)))
;;; the exclusive upper bound on the value of the low tag bits from a
;;; pointer
(def!constant lowtag-limit (ash 1 n-lowtag-bits))
+;;; the number of tag bits used for a fixnum
+(def!constant n-fixnum-tag-bits (1- n-lowtag-bits))
+;;; the fixnum tag mask
+(def!constant fixnum-tag-mask (1- (ash 1 n-fixnum-tag-bits)))
+;;; the bit width of positive fixnums
+(def!constant n-positive-fixnum-bits (- n-word-bits n-fixnum-tag-bits 1))
;;; the number of bits used in the header word of a data block to store
;;; the type
;;; a mask to extract the type from a data block header word
(def!constant widetag-mask (1- (ash 1 n-widetag-bits)))
-(def!constant sb!xc:most-positive-fixnum (1- (ash 1 29))
+(def!constant sb!xc:most-positive-fixnum
+ (1- (ash 1 (- n-word-bits n-lowtag-bits)))
#!+sb-doc
"the fixnum closest in value to positive infinity")
-(def!constant sb!xc:most-negative-fixnum (ash -1 29)
+(def!constant sb!xc:most-negative-fixnum
+ (ash -1 (- n-word-bits n-lowtag-bits))
#!+sb-doc
"the fixnum closest in value to negative infinity")
(ldb (byte 8 ,(- n 8 (* i 8))) new-value)))))
`(progn
(defun ,name (bigvec byte-index)
- (aver (= sb!vm:n-word-bits 32))
- (aver (= sb!vm:n-byte-bits 8))
(logior ,@(ecase sb!c:*backend-byte-order*
(:little-endian ash-list-le)
(:big-endian ash-list-be))))
(defun (setf ,name) (new-value bigvec byte-index)
- (aver (= sb!vm:n-word-bits 32))
- (aver (= sb!vm:n-byte-bits 8))
(setf ,@(ecase sb!c:*backend-byte-order*
(:little-endian setf-list-le)
(:big-endian setf-list-be))))))))
(make-bvref-n 8)
(make-bvref-n 16)
- (make-bvref-n 32))
+ (make-bvref-n 32)
+ (make-bvref-n 64))
+
+;; lispobj-sized word, whatever that may be
+(defun bvref-word (bytes index)
+ #!+x86-64 (bvref-64 bytes index)
+ #!-x86-64 (bvref-32 bytes index))
+
+(defun (setf bvref-word) (new-val bytes index)
+ #!+x86-64 (setf (bvref-64 bytes index) new-val)
+ #!-x86-64 (setf (bvref-32 bytes index) new-val))
\f
;;;; representation of spaces in the core
;; it's hard to see how it could have been wrong, since CMU CL
;; genesis worked. It would be nice to understand how this came
;; to be.. -- WHN 19990901
- (logior (ash bits -2) (ash -1 (- sb!vm:n-word-bits 2)))
- (ash bits -2))))
+ (logior (ash bits (- 1 sb!vm:n-lowtag-bits))
+ (ash -1 (- sb!vm:n-word-bits (1- sb!vm:n-lowtag-bits))))
+ (ash bits (- 1 sb!vm:n-lowtag-bits)))))
;;; common idioms
(defun descriptor-bytes (des)
(bytes (gspace-bytes gspace))
(byte-index (ash (+ index (descriptor-word-offset address))
sb!vm:word-shift))
- (value (bvref-32 bytes byte-index)))
+ (value (bvref-word bytes byte-index)))
(make-random-descriptor value)))
(declaim (ftype (function (descriptor) descriptor) read-memory))
(let* ((bytes (gspace-bytes (descriptor-intuit-gspace address)))
(byte-index (ash (+ index (descriptor-word-offset address))
sb!vm:word-shift)))
- (setf (bvref-32 bytes byte-index)
+ (setf (bvref-word bytes byte-index)
(descriptor-bits value)))))
(declaim (ftype (function (descriptor descriptor)) write-memory))
(:big-endian
(write-wordindexed des sb!vm:double-float-value-slot high-bits)
(write-wordindexed des (1+ sb!vm:double-float-value-slot) low-bits)))
- des))
- #!+(and long-float x86)
- (long-float
- (let ((des (allocate-unboxed-object *dynamic*
- sb!vm:n-word-bits
- (1- sb!vm:long-float-size)
- sb!vm:long-float-widetag))
- (exp-bits (make-random-descriptor (long-float-exp-bits x)))
- (high-bits (make-random-descriptor (long-float-high-bits x)))
- (low-bits (make-random-descriptor (long-float-low-bits x))))
- (ecase sb!c:*backend-byte-order*
- (:little-endian
- (write-wordindexed des sb!vm:long-float-value-slot low-bits)
- (write-wordindexed des (1+ sb!vm:long-float-value-slot) high-bits)
- (write-wordindexed des (+ 2 sb!vm:long-float-value-slot) exp-bits))
- (:big-endian
- (error "LONG-FLOAT is not supported for big-endian byte order.")))
des))))
(defun complex-single-float-to-core (num)
;;; Copy the given number to the core.
(defun number-to-core (number)
(typecase number
- (integer (if (< (integer-length number) 30)
+ (integer (if (< (integer-length number)
+ (- (1+ sb!vm:n-word-bits) sb!vm:n-lowtag-bits))
(make-fixnum-descriptor number)
(bignum-to-core number)))
(ratio (number-pair-to-core (number-to-core (numerator number))
(cold-set '*!reversed-cold-toplevels* *current-reversed-cold-toplevels*)
- #!+x86
+ #!+(or x86 x86-64)
(progn
(cold-set 'sb!vm::*fp-constant-0d0* (number-to-core 0d0))
(cold-set 'sb!vm::*fp-constant-1d0* (number-to-core 1d0))
(cold-set 'sb!vm::*fp-constant-0f0* (number-to-core 0f0))
- (cold-set 'sb!vm::*fp-constant-1f0* (number-to-core 1f0))
- #!+long-float
- (progn
- (cold-set 'sb!vm::*fp-constant-0l0* (number-to-core 0L0))
- (cold-set 'sb!vm::*fp-constant-1l0* (number-to-core 1L0))
- ;; FIXME: Why is initialization of PI conditional on LONG-FLOAT?
- ;; (ditto LG2, LN2, L2E, etc.)
- (cold-set 'sb!vm::*fp-constant-pi* (number-to-core pi))
- (cold-set 'sb!vm::*fp-constant-l2t* (number-to-core (log 10L0 2L0)))
- (cold-set 'sb!vm::*fp-constant-l2e*
- (number-to-core (log 2.718281828459045235360287471352662L0 2L0)))
- (cold-set 'sb!vm::*fp-constant-lg2* (number-to-core (log 2L0 10L0)))
- (cold-set 'sb!vm::*fp-constant-ln2*
- (number-to-core
- (log 2L0 2.718281828459045235360287471352662L0))))))
+ (cold-set 'sb!vm::*fp-constant-1f0* (number-to-core 1f0))))
;;; Make a cold list that can be used as the arg list to MAKE-PACKAGE in order
;;; to make a package that is similar to PKG.
;;; The x86 port needs to store code fixups along with code objects if
;;; they are to be moved, so fixups for code objects in the dynamic
;;; heap need to be noted.
-#!+x86
+#!+(or x86 x86-64)
(defvar *load-time-code-fixups*)
-#!+x86
+#!+(or x86 x86-64)
(defun note-load-time-code-fixup (code-object offset value kind)
;; If CODE-OBJECT might be moved
(when (= (gspace-identifier (descriptor-intuit-gspace code-object))
(push (list code-object offset value kind) *load-time-code-fixups*))
(values))
-#!+x86
+#!+(or x86 x86-64)
(defun output-load-time-code-fixups ()
(dolist (fixups *load-time-code-fixups*)
(let ((code-object (first fixups))
(dpb (ldb (byte 10 0) value)
(byte 10 0)
(bvref-32 gspace-bytes gspace-byte-offset))))))
- (:x86
- (let* ((un-fixed-up (bvref-32 gspace-bytes
+ ((:x86 :x86-64)
+ (let* ((un-fixed-up (bvref-word gspace-bytes
gspace-byte-offset))
(code-object-start-addr (logandc2 (descriptor-bits code-object)
sb!vm:lowtag-mask)))
(let ((fixed-up (- (+ value un-fixed-up)
gspace-byte-address
gspace-byte-offset
- sb!vm:n-word-bytes))) ; length of CALL argument
+ 4))) ; "length of CALL argument"
(setf (bvref-32 gspace-bytes gspace-byte-offset)
fixed-up)
;; Note relative fixups that point outside the code
(define-cold-number-fop fop-complex-single-float)
(define-cold-number-fop fop-complex-double-float)
-#!+long-float
-(define-cold-fop (fop-long-float)
- (ecase +backend-fasl-file-implementation+
- (:x86 ; (which has 80-bit long-float format)
- (prepare-for-fast-read-byte *fasl-input-stream*
- (let* ((des (allocate-unboxed-object *dynamic* sb!vm:n-word-bits
- (1- sb!vm:long-float-size)
- sb!vm:long-float-widetag))
- (low-bits (make-random-descriptor (fast-read-u-integer 4)))
- (high-bits (make-random-descriptor (fast-read-u-integer 4)))
- (exp-bits (make-random-descriptor (fast-read-s-integer 2))))
- (done-with-fast-read-byte)
- (write-wordindexed des sb!vm:long-float-value-slot low-bits)
- (write-wordindexed des (1+ sb!vm:long-float-value-slot) high-bits)
- (write-wordindexed des (+ 2 sb!vm:long-float-value-slot) exp-bits)
- des)))
- ;; This was supported in CMU CL, but isn't currently supported in
- ;; SBCL.
- #+nil
- (#.sb!c:sparc-fasl-file-implementation ; 128 bit long-float format
- (prepare-for-fast-read-byte *fasl-input-stream*
- (let* ((des (allocate-unboxed-object *dynamic* sb!vm:n-word-bits
- (1- sb!vm:long-float-size)
- sb!vm:long-float-widetag))
- (low-bits (make-random-descriptor (fast-read-u-integer 4)))
- (mid-bits (make-random-descriptor (fast-read-u-integer 4)))
- (high-bits (make-random-descriptor (fast-read-u-integer 4)))
- (exp-bits (make-random-descriptor (fast-read-s-integer 4))))
- (done-with-fast-read-byte)
- (write-wordindexed des sb!vm:long-float-value-slot exp-bits)
- (write-wordindexed des (1+ sb!vm:long-float-value-slot) high-bits)
- (write-wordindexed des (+ 2 sb!vm:long-float-value-slot) mid-bits)
- (write-wordindexed des (+ 3 sb!vm:long-float-value-slot) low-bits)
- des)))))
-
-#!+long-float
-(define-cold-fop (fop-complex-long-float)
- (ecase +backend-fasl-file-implementation+
- (:x86 ; (which has 80-bit long-float format)
- (prepare-for-fast-read-byte *fasl-input-stream*
- (let* ((des (allocate-unboxed-object *dynamic* sb!vm:n-word-bits
- (1- sb!vm:complex-long-float-size)
- sb!vm:complex-long-float-widetag))
- (real-low-bits (make-random-descriptor (fast-read-u-integer 4)))
- (real-high-bits (make-random-descriptor (fast-read-u-integer 4)))
- (real-exp-bits (make-random-descriptor (fast-read-s-integer 2)))
- (imag-low-bits (make-random-descriptor (fast-read-u-integer 4)))
- (imag-high-bits (make-random-descriptor (fast-read-u-integer 4)))
- (imag-exp-bits (make-random-descriptor (fast-read-s-integer 2))))
- (done-with-fast-read-byte)
- (write-wordindexed des
- sb!vm:complex-long-float-real-slot
- real-low-bits)
- (write-wordindexed des
- (1+ sb!vm:complex-long-float-real-slot)
- real-high-bits)
- (write-wordindexed des
- (+ 2 sb!vm:complex-long-float-real-slot)
- real-exp-bits)
- (write-wordindexed des
- sb!vm:complex-long-float-imag-slot
- imag-low-bits)
- (write-wordindexed des
- (1+ sb!vm:complex-long-float-imag-slot)
- imag-high-bits)
- (write-wordindexed des
- (+ 2 sb!vm:complex-long-float-imag-slot)
- imag-exp-bits)
- des)))
- ;; This was supported in CMU CL, but isn't currently supported in SBCL.
- #+nil
- (#.sb!c:sparc-fasl-file-implementation ; 128 bit long-float format
- (prepare-for-fast-read-byte *fasl-input-stream*
- (let* ((des (allocate-unboxed-object *dynamic* sb!vm:n-word-bits
- (1- sb!vm:complex-long-float-size)
- sb!vm:complex-long-float-widetag))
- (real-low-bits (make-random-descriptor (fast-read-u-integer 4)))
- (real-mid-bits (make-random-descriptor (fast-read-u-integer 4)))
- (real-high-bits (make-random-descriptor (fast-read-u-integer 4)))
- (real-exp-bits (make-random-descriptor (fast-read-s-integer 4)))
- (imag-low-bits (make-random-descriptor (fast-read-u-integer 4)))
- (imag-mid-bits (make-random-descriptor (fast-read-u-integer 4)))
- (imag-high-bits (make-random-descriptor (fast-read-u-integer 4)))
- (imag-exp-bits (make-random-descriptor (fast-read-s-integer 4))))
- (done-with-fast-read-byte)
- (write-wordindexed des
- sb!vm:complex-long-float-real-slot
- real-exp-bits)
- (write-wordindexed des
- (1+ sb!vm:complex-long-float-real-slot)
- real-high-bits)
- (write-wordindexed des
- (+ 2 sb!vm:complex-long-float-real-slot)
- real-mid-bits)
- (write-wordindexed des
- (+ 3 sb!vm:complex-long-float-real-slot)
- real-low-bits)
- (write-wordindexed des
- sb!vm:complex-long-float-real-slot
- imag-exp-bits)
- (write-wordindexed des
- (1+ sb!vm:complex-long-float-real-slot)
- imag-high-bits)
- (write-wordindexed des
- (+ 2 sb!vm:complex-long-float-real-slot)
- imag-mid-bits)
- (write-wordindexed des
- (+ 3 sb!vm:complex-long-float-real-slot)
- imag-low-bits)
- des)))))
-
(define-cold-fop (fop-ratio)
(let ((den (pop-stack)))
(number-pair-to-core (pop-stack) den sb!vm:ratio-widetag)))
(defun write-word (num)
(ecase sb!c:*backend-byte-order*
(:little-endian
- (dotimes (i 4)
+ (dotimes (i sb!vm:n-word-bytes)
(write-byte (ldb (byte 8 (* i 8)) num) *core-file*)))
(:big-endian
- (dotimes (i 4)
- (write-byte (ldb (byte 8 (* (- 3 i) 8)) num) *core-file*))))
+ (dotimes (i sb!vm:n-word-bytes)
+ (write-byte (ldb (byte 8 (* (- (1- sb!vm:n-word-bytes) i) 8)) num)
+ *core-file*))))
num)
(defun advance-to-page ()
;; we can save a register on the x86.
:variant simple
;; we can save a couple of instructions and a branch on the ppc.
- ;; FIXME: make this be FIXNUM-MASK
- :mask 3)
+ :mask fixnum-tag-mask)
(!define-type-vops functionp check-fun function object-not-fun-error
(fun-pointer-lowtag)
object-not-complex-double-float-error
(complex-double-float-widetag))
-#!+long-float
-(!define-type-vops complex-long-float-p check-complex-long-float complex-long-float
- object-not-complex-long-float-error
- (complex-long-float-widetag))
-
(!define-type-vops single-float-p check-single-float single-float
object-not-single-float-error
(single-float-widetag))
object-not-double-float-error
(double-float-widetag))
-#!+long-float
-(!define-type-vops long-float-p check-long-float long-float
- object-not-long-float-error
- (long-float-widetag))
-
(!define-type-vops simple-string-p check-simple-string nil
object-not-simple-string-error
(simple-base-string-widetag simple-array-nil-widetag))
(real :c-type "double" :length 2)
(imag :c-type "double" :length 2))
-#!+long-float
-(define-primitive-object (complex-long-float
- :lowtag other-pointer-lowtag
- :widetag complex-long-float-widetag)
- #!+sparc (filler)
- (real :c-type "long double" :length #!+x86 3 #!+sparc 4)
- (imag :c-type "long double" :length #!+x86 3 #!+sparc 4))
-
;;; this isn't actually a lisp object at all, it's a c structure that lives
;;; in c-land. However, we need sight of so many parts of it from Lisp that
;;; it makes sense to define it here anyway, so that the GENESIS machinery
(!def-primitive-type single-float (single-reg descriptor-reg))
(/show0 "about to !DEF-PRIMITIVE-TYPE DOUBLE-FLOAT")
(!def-primitive-type double-float (double-reg descriptor-reg))
-#!+long-float
-(!def-primitive-type long-float (long-reg descriptor-reg))
+
(/show0 "about to !DEF-PRIMITIVE-TYPE COMPLEX-SINGLE-FLOAT")
(!def-primitive-type complex-single-float (complex-single-reg descriptor-reg)
:type (complex single-float))
(/show0 "about to !DEF-PRIMITIVE-TYPE COMPLEX-DOUBLE-FLOAT")
(!def-primitive-type complex-double-float (complex-double-reg descriptor-reg)
:type (complex double-float))
-#!+long-float
-(!def-primitive-type complex-long-float (complex-long-reg descriptor-reg)
- :type (complex long-float))
+
;;; primitive other-pointer array types
(/show0 "primtype.lisp 96")
(return (values
(primitive-type-or-lose type)
(and (= lo min) (= hi max))))))))
- ((or (and hi (< hi most-negative-fixnum))
- (and lo (> lo most-positive-fixnum)))
+ ((or (and hi (< hi sb!xc:most-negative-fixnum))
+ (and lo (> lo sb!xc:most-positive-fixnum)))
(part-of bignum))
(t
(any))))
((short-float single-float)
(values (primitive-type-or-lose 'single-float)
exact))
- ((double-float #!-long-float long-float)
+ ((double-float)
(values (primitive-type-or-lose 'double-float)
exact))
- #!+long-float
- (long-float
- (values (primitive-type-or-lose 'long-float)
- exact))
(t
(any)))))
(t
((short-float single-float)
(values (primitive-type-or-lose 'complex-single-float)
exact))
- ((double-float #!-long-float long-float)
+ ((double-float long-float)
(values (primitive-type-or-lose 'complex-double-float)
exact))
- #!+long-float
- (long-float
- (values (primitive-type-or-lose 'complex-long-float)
- exact))
(t
(part-of complex))))
(part-of complex)))
(code-obj
;; FIXME: In CMU CL the X86 behavior here depended on
;; *ENABLE-DYNAMIC-SPACE-CODE*, but in SBCL we always use
- ;; dynamic space code, so we could make
- ;; ALLOCATE-DYNAMIC-CODE-OBJECT more parallel with
- ;; ALLOCATE-CODE-OBJECT and remove this confusing
- ;; read-macro conditionalization.
+ ;; dynamic space code, so we shoudl just rename the
+ ;; allocate-dynamic-code-object vop and lose this #+ stuff
#!+x86
(%primitive allocate-dynamic-code-object box-num total-length)
#!-x86
\f
;;; Make a fixnum out of NUM. (I.e. shift by two bits if it will fit.)
(defun fixnumize (num)
- (if (<= #x-20000000 num #x1fffffff)
- (ash num 2)
+ (if (fixnump num)
+ (ash num (1- n-lowtag-bits))
(error "~W is too big for a fixnum." num)))
\f
;;;; routines for dealing with static symbols
:importance 6)
(double-float 0.0d0 64 simple-array-double-float
:importance 5)
- #!+long-float
- (long-float 0.0l0 #!+x86 96 #!+sparc 128 simple-array-long-float
- :importance 4)
(bit 0 1 simple-bit-vector
:complex-typecode #.sb!vm:complex-bit-vector-widetag
:importance 16)
(foldable flushable))
(defknown %raw-ref-complex-double (raw-vector index) (complex double-float)
(foldable flushable))
-#!+long-float
-(defknown %raw-ref-complex-long (raw-vector index) (complex long-float)
- (foldable flushable))
+
(defknown %raw-set-complex-single (raw-vector index (complex single-float))
(complex single-float)
(unsafe))
(defknown %raw-set-complex-double (raw-vector index (complex double-float))
(complex double-float)
(unsafe))
-#!+long-float
-(defknown %raw-set-complex-long (raw-vector index (complex long-float))
- (complex long-float)
- (unsafe))
+
(defknown %raw-bits (t fixnum) (unsigned-byte 32)
(foldable flushable))
(constant-lvar-p count) ; ?
(plusp (lvar-value count)))
(cut-to-width integer width)
- '#1#)
- (setf (gethash '#1# *modular-versions*) '(ash 64))))
+ '#1#))
+ (setf (gethash '#1# *modular-versions*) '(ash 64)))
\f
;;; There are two different ways the multiplier can be recoded. The
`(single-float ,low ,high))
;;; an index into an integer
-(sb!xc:deftype bit-index () `(integer 0 ,most-positive-fixnum))
+(sb!xc:deftype bit-index () `(integer 0 ,sb!xc:most-positive-fixnum))
;;; worst-case values for float attributes
(sb!xc:deftype float-exponent ()
;;; order in which the TYPE-INFO-creation forms are generated doesn't
;;; match the relative order in which the forms need to be executed at
;;; cold load time.
-(defparameter *reversed-type-info-init-forms* nil)
+(defparameter *!reversed-type-info-init-forms* nil)
;;; Define a new type of global information for CLASS. TYPE is the
;;; name of the type, DEFAULT is the value for that type when it
(declare (ignorable name))
,',default))
(setf (type-info-type type-info) ',',type-spec))
- *reversed-type-info-init-forms*))
+ *!reversed-type-info-init-forms*))
',type))
) ; EVAL-WHEN
;;; we can set their DEFAULT and TYPE slots.
(macrolet ((frob ()
`(!cold-init-forms
- ,@(reverse *reversed-type-info-init-forms*))))
+ ,@(reverse *!reversed-type-info-init-forms*))))
(frob))
\f
;;;; a hack for detecting
-(in-package "SB!VM")
+;;;; the VM definition of function call for the HPPA
+
+;;;; This software is part of the SBCL system. See the README file for
+;;;; more information.
+;;;;
+;;;; This software is derived from the CMU CL system, which was
+;;;; written at Carnegie Mellon University and released into the
+;;;; public domain. The software is in the public domain and is
+;;;; provided with absolutely no warranty. See the COPYING and CREDITS
+;;;; files for more information.
+(in-package "SB!VM")
\f
;;;; Interfaces to IR2 conversion:
(define-vop (listify-rest-args)
(:args (context-arg :target context :scs (descriptor-reg))
(count-arg :target count :scs (any-reg)))
- (:arg-types * tagged-num)
+ (:info dx)
+ (:ignore dx)
+ (:arg-types * tagged-num (:constant t))
(:temporary (:scs (any-reg) :from (:argument 0)) context)
(:temporary (:scs (any-reg) :from (:argument 1)) count)
(:temporary (:scs (descriptor-reg) :from :eval) temp)
(defun note-failed-optimization (node failures)
(declare (type combination node) (list failures))
(unless (or (node-deleted node)
- (not (fun-info-p (combination-kind node))))
+ (not (eq :known (combination-kind node))))
(let ((*compiler-error-context* node))
(dolist (failure failures)
(let ((what (cdr failure))
(delete-ref node)
(unlink-node node))
(combination
- (let ((info (combination-kind node)))
- (when (fun-info-p info)
+ (let ((kind (combination-kind node))
+ (info (combination-fun-info node)))
+ (when (and (eq kind :known) (fun-info-p info))
(let ((attr (fun-info-attributes info)))
(when (and (not (ir1-attributep attr call))
;; ### For now, don't delete potentially
(propagate-fun-change node)
(maybe-terminate-block node nil))
(let ((args (basic-combination-args node))
- (kind (basic-combination-kind node)))
- (case kind
+ (kind (basic-combination-kind node))
+ (info (basic-combination-fun-info node)))
+ (ecase kind
(:local
(let ((fun (combination-lambda node)))
(if (eq (functional-kind fun) :let)
(propagate-let-args node fun)
(propagate-local-call-args node fun))))
- ((:full :error)
+ (:error
(dolist (arg args)
(when arg
(setf (lvar-reoptimize arg) nil))))
- (t
+ (:full
+ (dolist (arg args)
+ (when arg
+ (setf (lvar-reoptimize arg) nil)))
+ (when info
+ (let ((fun (fun-info-derive-type info)))
+ (when fun
+ (let ((res (funcall fun node)))
+ (when res
+ (derive-node-type node (coerce-to-values res))
+ (maybe-terminate-block node nil)))))))
+ (:known
+ (aver info)
(dolist (arg args)
(when arg
(setf (lvar-reoptimize arg) nil)))
- (let ((attr (fun-info-attributes kind)))
+ (let ((attr (fun-info-attributes info)))
(when (and (ir1-attributep attr foldable)
;; KLUDGE: The next test could be made more sensitive,
;; only suppressing constant-folding of functions with
(constant-fold-call node)
(return-from ir1-optimize-combination)))
- (let ((fun (fun-info-derive-type kind)))
+ (let ((fun (fun-info-derive-type info)))
(when fun
(let ((res (funcall fun node)))
(when res
(derive-node-type node (coerce-to-values res))
(maybe-terminate-block node nil)))))
- (let ((fun (fun-info-optimizer kind)))
+ (let ((fun (fun-info-optimizer info)))
(unless (and fun (funcall fun node))
- (dolist (x (fun-info-transforms kind))
+ (dolist (x (fun-info-transforms info))
#!+sb-show
(when *show-transforms-p*
(let* ((lvar (basic-combination-fun node))
(defined-fun-inlinep leaf)
:no-chance)))
(cond
- ((eq inlinep :notinline) (values nil nil))
+ ((eq inlinep :notinline)
+ (let ((info (info :function :info (leaf-source-name leaf))))
+ (when info
+ (setf (basic-combination-fun-info call) info))
+ (values nil nil)))
((not (and (global-var-p leaf)
(eq (global-var-kind leaf) :global-function)))
(values leaf nil))
(t
(let ((info (info :function :info (leaf-source-name leaf))))
(if info
- (values leaf (setf (basic-combination-kind call) info))
+ (values leaf
+ (progn
+ (setf (basic-combination-kind call) :known)
+ (setf (basic-combination-fun-info call) info)))
(values leaf nil)))))))
;;; Check whether CALL satisfies TYPE. If so, apply the type to the
(() (null (rest sets)) :exit-if-null)
(set-use (principal-lvar-use (set-value set)))
(() (and (combination-p set-use)
- (fun-info-p (combination-kind set-use))
+ (eq (combination-kind set-use) :known)
+ (fun-info-p (combination-fun-info set-use))
(not (node-to-be-deleted-p set-use))
(eq (combination-fun-source-name set-use) '+))
:exit-if-null)
(rest svars))))))
(values))
+;;; FIXME: this is the interface of the CMUCL WITH-DYNAMIC-EXTENT
+;;; macro. It is slightly confusing, in that START and BODY-START are
+;;; already-existing CTRANs (and FIXME: probably deserve a ONCE-ONLY),
+;;; whereas NEXT is a variable naming a CTRAN in the body. -- CSR,
+;;; 2004-03-30.
+(defmacro with-dynamic-extent ((start body-start next kind) &body body)
+ (with-unique-names (cleanup next-ctran)
+ `(progn
+ (ctran-starts-block ,body-start)
+ (let ((,cleanup (make-cleanup :kind :dynamic-extent))
+ (,next-ctran (make-ctran))
+ (,next (make-ctran)))
+ (ir1-convert ,start ,next-ctran nil '(%dynamic-extent-start))
+ (setf (cleanup-mess-up ,cleanup) (ctran-use ,next-ctran))
+ (let ((*lexenv* (make-lexenv :cleanup ,cleanup)))
+ (ir1-convert ,next-ctran ,next nil '(%cleanup-point))
+ (locally ,@body))))))
+
;;; Create a lambda node out of some code, returning the result. The
;;; bindings are specified by the list of VAR structures VARS. We deal
;;; with adding the names to the LEXENV-VARS for the conversion. The
;;; the special binding code.
;;;
;;; We ignore any ARG-INFO in the VARS, trusting that someone else is
-;;; dealing with &nonsense.
+;;; dealing with &NONSENSE, except for &REST vars with DYNAMIC-EXTENT.
;;;
;;; AUX-VARS is a list of VAR structures for variables that are to be
;;; sequentially bound. Each AUX-VAL is a form that is to be evaluated
:%source-name source-name
:%debug-name debug-name))
(result-ctran (make-ctran))
- (result-lvar (make-lvar)))
+ (result-lvar (make-lvar))
+ (dx-rest nil))
(awhen (lexenv-lambda *lexenv*)
(push lambda (lambda-children it))
(t
(when note-lexical-bindings
(note-lexical-binding (leaf-source-name var)))
- (new-venv (cons (leaf-source-name var) var))))))
+ (new-venv (cons (leaf-source-name var) var)))))
+ (let ((info (lambda-var-arg-info var)))
+ (when (and info
+ (eq (arg-info-kind info) :rest)
+ (leaf-dynamic-extent var))
+ (setq dx-rest t))))
(let ((*lexenv* (make-lexenv :vars (new-venv)
:lambda lambda
(ctran-starts-block prebind-ctran)
(link-node-to-previous-ctran bind prebind-ctran)
(use-ctran bind postbind-ctran)
- (ir1-convert-special-bindings postbind-ctran result-ctran result-lvar
- body
- aux-vars aux-vals (svars))))))
+ (if dx-rest
+ (with-dynamic-extent (postbind-ctran result-ctran dx :rest)
+ (ir1-convert-special-bindings dx result-ctran result-lvar
+ body aux-vars aux-vals
+ (svars)))
+ (ir1-convert-special-bindings postbind-ctran result-ctran
+ result-lvar body
+ aux-vars aux-vals (svars)))))))
(link-blocks (component-head *current-component*) (node-block bind))
(push lambda (component-new-functionals *current-component*))
(arg-vars context-temp count-temp)
(when rest
- (arg-vals `(%listify-rest-args ,n-context ,n-count)))
+ (arg-vals `(%listify-rest-args
+ ,n-context ,n-count ,(leaf-dynamic-extent rest))))
(when morep
(arg-vals n-context)
(arg-vals n-count))
(setf (lambda-var-ignorep var) t)))))
(values))
+(defun process-dx-decl (names vars)
+ (flet ((maybe-notify (control &rest args)
+ (when (policy *lexenv* (> speed inhibit-warnings))
+ (apply #'compiler-notify control args))))
+ (if (policy *lexenv* (= stack-allocate-dynamic-extent 3))
+ (dolist (name names)
+ (cond
+ ((symbolp name)
+ (let* ((bound-var (find-in-bindings vars name))
+ (var (or bound-var
+ (lexenv-find name vars)
+ (find-free-var name))))
+ (etypecase var
+ (leaf
+ (if bound-var
+ (setf (leaf-dynamic-extent var) t)
+ (maybe-notify
+ "ignoring DYNAMIC-EXTENT declaration for free ~S"
+ name)))
+ (cons
+ (compiler-error "DYNAMIC-EXTENT on symbol-macro: ~S" name))
+ (heap-alien-info
+ (compiler-error "DYNAMIC-EXTENT on heap-alien-info: ~S"
+ name)))))
+ ((and (consp name)
+ (eq (car name) 'function)
+ (null (cddr name))
+ (valid-function-name-p (cadr name)))
+ (maybe-notify "ignoring DYNAMIC-EXTENT declaration for ~S" name))
+ (t (compiler-error "DYNAMIC-EXTENT on a weird thing: ~S" name))))
+ (maybe-notify "ignoring DYNAMIC-EXTENT declarations for ~S" names))))
+
;;; FIXME: This is non-ANSI, so the default should be T, or it should
;;; go away, I think.
(defvar *suppress-values-declaration* nil
`(values ,@types)))))
res))
(dynamic-extent
- (when (policy *lexenv* (> speed inhibit-warnings))
- (compiler-notify
- "compiler limitation: ~
- ~% There's no special support for DYNAMIC-EXTENT (so it's ignored)."))
+ (process-dx-decl (cdr spec) vars)
res)
(t
(unless (info :declaration :recognized (first spec))
(append before-args inside-args after-args))
(change-ref-leaf (lvar-uses inside-fun)
(find-free-fun 'list "???"))
- (setf (combination-kind inside)
- (info :function :info 'list))
+ (setf (combination-fun-info inside) (info :function :info 'list)
+ (combination-kind inside) :known)
(setf (node-derived-type inside) *wild-type*)
(flush-dest lvar)
(values))))))
(declare (type combination call))
(let ((kind (basic-combination-kind call)))
(or (eq kind :full)
- (and (fun-info-p kind)
- (not (fun-info-ir2-convert kind))
- (dolist (template (fun-info-templates kind) t)
- (when (eq (template-ltn-policy template) :fast-safe)
- (multiple-value-bind (val win)
- (valid-fun-use call (template-type template))
- (when (or val (not win)) (return nil)))))))))
+ (and (eq kind :known)
+ (let ((info (basic-combination-fun-info call)))
+ (and
+ (not (fun-info-ir2-convert info))
+ (dolist (template (fun-info-templates info) t)
+ (when (eq (template-ltn-policy template) :fast-safe)
+ (multiple-value-bind (val win)
+ (valid-fun-use call (template-type template))
+ (when (or val (not win)) (return nil)))))))))))
\f
;;;; careful call
(defoptimizer (%special-unbind ir2-convert) ((var) node block)
(vop unbind node block))
+(defoptimizer (%dynamic-extent-start ir2-convert) (() node block) node block)
+(defoptimizer (%dynamic-extent-end ir2-convert) (() node block) node block)
+
;;; ### It's not clear that this really belongs in this file, or
;;; should really be done this way, but this is the least violation of
;;; abstraction in the current setup. We don't want to wire
(ir2-convert-ref node 2block)))))
(combination
(let ((kind (basic-combination-kind node)))
- (case kind
+ (ecase kind
(:local
(ir2-convert-local-call node 2block))
(:full
(ir2-convert-full-call node 2block))
- (t
- (let ((fun (fun-info-ir2-convert kind)))
+ (:known
+ (let* ((info (basic-combination-fun-info node))
+ (fun (fun-info-ir2-convert info)))
(cond (fun
(funcall fun node 2block))
((eq (basic-combination-info node) :full)
;;; can bail out to here.
(defun ltn-default-call (call)
(declare (type combination call))
- (let ((kind (basic-combination-kind call)))
+ (let ((kind (basic-combination-kind call))
+ (info (basic-combination-fun-info call)))
(annotate-fun-lvar (basic-combination-fun call))
(dolist (arg (basic-combination-args call))
(annotate-1-value-lvar arg))
(cond
- ((and (fun-info-p kind)
- (fun-info-ir2-convert kind))
+ ((and (eq kind :known)
+ (fun-info-p info)
+ (fun-info-ir2-convert info))
(setf (basic-combination-info call) :funny)
(setf (node-tail-p call) nil))
(t
(declare (type combination call)
(type ltn-policy ltn-policy))
(let ((safe-p (ltn-policy-safe-p ltn-policy))
- (current (fun-info-templates (basic-combination-kind call)))
+ (current (fun-info-templates (basic-combination-fun-info call)))
(fallback nil)
(rejected nil))
(loop
(or template
(template-or-lose 'call-named)))
*efficiency-note-cost-threshold*)))
- (dolist (try (fun-info-templates (basic-combination-kind call)))
+ (dolist (try (fun-info-templates (basic-combination-fun-info call)))
(when (> (template-cost try) max-cost) (return)) ; FIXME: UNLESS'd be cleaner.
(let ((guard (template-guard try)))
(when (and (or (not guard) (funcall guard))
(defun ltn-analyze-known-call (call)
(declare (type combination call))
(let ((ltn-policy (node-ltn-policy call))
- (method (fun-info-ltn-annotate (basic-combination-kind call)))
+ (method (fun-info-ltn-annotate (basic-combination-fun-info call)))
(args (basic-combination-args call)))
(when method
(funcall method call ltn-policy)
(and (leaf-has-source-name-p funleaf)
(eq (lvar-fun-name (combination-fun call))
(leaf-source-name funleaf))
- (let ((info (basic-combination-kind call)))
+ (let ((info (basic-combination-fun-info call)))
(not (or (fun-info-ir2-convert info)
(ir1-attributep (fun-info-attributes info)
recursive))))))
(etypecase node
(ref)
(combination
- (case (basic-combination-kind node)
+ (ecase (basic-combination-kind node)
(:local (ltn-analyze-local-call node))
((:full :error) (ltn-default-call node))
- (t
+ (:known
(ltn-analyze-known-call node))))
(cif (ltn-analyze-if node))
(creturn (ltn-analyze-return node))
;;; list. START-VAR, NEXT-VAR and RESULT-VAR are bound to the start and
;;; result continuations for the resulting IR1. KIND is the function
;;; kind to associate with NAME.
-(defmacro def-ir1-translator (name (lambda-list start-var next-var result-var
- &key (kind :special-form))
- &body body)
+(defmacro def-ir1-translator (name (lambda-list start-var next-var result-var)
+ &body body)
(let ((fn-name (symbolicate "IR1-CONVERT-" name))
(n-form (gensym))
(n-env (gensym)))
;; FIXME: Evidently "there can only be one!" -- we overwrite any
;; other :IR1-CONVERT value. This deserves a warning, I think.
(setf (info :function :ir1-convert ',name) #',fn-name)
- (setf (info :function :kind ',name) ,kind)
+ ;; FIXME: rename this to SPECIAL-OPERATOR, to update it to
+ ;; the 1990s?
+ (setf (info :function :kind ',name) :special-form)
;; It's nice to do this for error checking in the target
;; SBCL, but it's not nice to do this when we're running in
;; the cross-compilation host Lisp, which owns the
;; SYMBOL-FUNCTION of its COMMON-LISP symbols.
#-sb-xc-host
- ,@(when (eq kind :special-form)
- `((setf (symbol-function ',name)
- (lambda (&rest rest)
- (declare (ignore rest))
- (error 'special-form-function
- :name ',name)))))))))
+ (let ((fun (lambda (&rest rest)
+ (declare (ignore rest))
+ (error 'special-form-function :name ',name))))
+ (setf (%simple-fun-arglist fun) ',lambda-list)
+ (setf (symbol-function ',name) fun))
+ ',name))))
;;; (This is similar to DEF-IR1-TRANSLATOR, except that we pass if the
;;; syntax is invalid.)
-(in-package "SB!VM")
+;;;; the VM definition of function call for MIPS
+
+;;;; This software is part of the SBCL system. See the README file for
+;;;; more information.
+;;;;
+;;;; This software is derived from the CMU CL system, which was
+;;;; written at Carnegie Mellon University and released into the
+;;;; public domain. The software is in the public domain and is
+;;;; provided with absolutely no warranty. See the COPYING and CREDITS
+;;;; files for more information.
+(in-package "SB!VM")
\f
;;;; Interfaces to IR2 conversion:
(define-vop (listify-rest-args)
(:args (context-arg :target context :scs (descriptor-reg))
(count-arg :target count :scs (any-reg)))
- (:arg-types * tagged-num)
+ (:info dx)
+ (:ignore dx)
+ (:arg-types * tagged-num (:constant t))
(:temporary (:scs (any-reg) :from (:argument 0)) context)
(:temporary (:scs (any-reg) :from (:argument 1)) count)
(:temporary (:scs (descriptor-reg) :from :eval) temp dst)
(defstruct (cleanup (:copier nil))
;; the kind of thing that has to be cleaned up
(kind (missing-arg)
- :type (member :special-bind :catch :unwind-protect :block :tagbody))
+ :type (member :special-bind :catch :unwind-protect
+ :block :tagbody :dynamic-extent))
;; the node that messes things up. This is the last node in the
;; non-messed-up environment. Null only temporarily. This could be
;; deleted due to unreachability.
;; true if there was ever a REF or SET node for this leaf. This may
;; be true when REFS and SETS are null, since code can be deleted.
(ever-used nil :type boolean)
+ ;; is it declared dynamic-extent?
+ (dynamic-extent nil :type boolean)
;; some kind of info used by the back end
(info nil))
(args nil :type list)
;; the kind of function call being made. :LOCAL means that this is a
;; local call to a function in the same component, and that argument
- ;; syntax checking has been done, etc. Calls to known global
- ;; functions are represented by storing the FUN-INFO for the
- ;; function in this slot. :FULL is a call to an (as yet) unknown
- ;; function. :ERROR is like :FULL, but means that we have discovered
- ;; that the call contains an error, and should not be reconsidered
- ;; for optimization.
- (kind :full :type (or (member :local :full :error) fun-info))
+ ;; syntax checking has been done, etc. Calls to known global
+ ;; functions are represented by storing :KNOWN in this slot and the
+ ;; FUN-INFO for that function in the FUN-INFO slot. :FULL is a call
+ ;; to an (as yet) unknown function, or to a known function declared
+ ;; NOTINLINE. :ERROR is like :FULL, but means that we have
+ ;; discovered that the call contains an error, and should not be
+ ;; reconsidered for optimization.
+ (kind :full :type (member :local :full :error :known))
+ ;; if a call to a known global function, contains the FUN-INFO.
+ (fun-info nil :type (or fun-info null))
;; some kind of information attached to this node by the back end
(info nil))
(code `(%funcall ,fun))))
((:block :tagbody)
(dolist (nlx (cleanup-nlx-info cleanup))
- (code `(%lexical-exit-breakup ',nlx)))))))
+ (code `(%lexical-exit-breakup ',nlx))))
+ (:dynamic-extent
+ (code `(%dynamic-extent-end))))))
(when (code)
(aver (not (node-tail-p (block-last block1))))
3
0)
("no" "maybe" "yes" "yes"))
+
+(define-optimization-quality stack-allocate-dynamic-extent
+ (if (and (> (max speed space) (max debug safety))
+ (< safety 3))
+ 3
+ 0)
+ ("no" "maybe" "yes" "yes"))
(define-vop (listify-rest-args)
(:args (context-arg :target context :scs (descriptor-reg))
(count-arg :target count :scs (any-reg)))
- (:arg-types * tagged-num)
+ (:info dx)
+ (:ignore dx)
+ (:arg-types * tagged-num (:constant t))
(:temporary (:scs (any-reg) :from (:argument 0)) context)
(:temporary (:scs (any-reg) :from (:argument 1)) count)
(:temporary (:scs (descriptor-reg) :from :eval) temp)
\f
(defun %test-fixnum (value target not-p &key temp)
(assemble ()
- ;; FIXME: again, this 3 should be FIXNUM-MASK
- (inst andi. temp value 3)
+ (inst andi. temp value fixnum-tag-mask)
(inst b? (if not-p :ne :eq) target)))
(defun %test-fixnum-and-headers (value target not-p headers &key temp)
(let ((drop-through (gen-label)))
(assemble ()
- (inst andi. temp value 3)
+ (inst andi. temp value fixnum-tag-mask)
(inst beq (if not-p drop-through target)))
(%test-headers value target not-p nil headers
:drop-through drop-through :temp temp)))
,@(if mask
`((inst andi. temp value ,mask)
(inst twi 0 value (error-number-or-lose ',error-code))
- (inst twi :ne temp ,@(if ;; KLUDGE: At
- ;; present, MASK is
- ;; 3 or LOWTAG-MASK
- (eql mask 3)
- ;; KLUDGE
- `(0)
- type-codes))
+ (inst twi :ne temp ,@(ecase mask
+ ((fixnum-tag-mask) `(0))
+ ((lowtag-mask) type-codes)))
(move result value))
`((let ((err-lab
(generate-error-code vop ,error-code value)))
(define-vop (listify-rest-args)
(:args (context-arg :target context :scs (descriptor-reg))
(count-arg :target count :scs (any-reg)))
- (:arg-types * tagged-num)
+ (:info dx)
+ (:ignore dx)
+ (:arg-types * tagged-num (:constant t))
(:temporary (:scs (any-reg) :from (:argument 0)) context)
(:temporary (:scs (any-reg) :from (:argument 1)) count)
(:temporary (:scs (descriptor-reg) :from :eval) temp)
#!+sb-doc
"Number of bytes in a word.")
-(def!constant n-fixnum-tag-bits (1- n-lowtag-bits)
- #!+sb-doc
- "Number of tag bits used for a fixnum")
-
-(def!constant fixnum-tag-mask (1- (ash 1 n-fixnum-tag-bits))
- #!+sb-doc
- "Mask to get the fixnum tag")
-
-(def!constant n-positive-fixnum-bits (- n-word-bits n-fixnum-tag-bits 1)
- #!+sb-doc
- "Maximum number of bits in a positive fixnum")
-
(def!constant float-sign-shift 31)
(def!constant single-float-bias 126)
(cut-node (node &aux did-something)
(when (and (not (block-delete-p (node-block node)))
(combination-p node)
- (fun-info-p (basic-combination-kind node)))
+ (eq (basic-combination-kind node) :known))
(let* ((fun-ref (lvar-use (combination-fun node)))
(fun-name (leaf-source-name (ref-leaf fun-ref)))
(modular-fun (find-modular-version fun-name width)))
(:policy :safe)
(:args (context :scs (descriptor-reg) :target src)
(count :scs (any-reg) :target ecx))
- (:arg-types * tagged-num)
+ (:info *dynamic-extent*)
+ (:arg-types * tagged-num (:constant t))
(:temporary (:sc unsigned-reg :offset esi-offset :from (:argument 0)) src)
(:temporary (:sc unsigned-reg :offset ecx-offset :from (:argument 1)) ecx)
(:temporary (:sc unsigned-reg :offset eax-offset) eax)
(inst jecxz done)
(inst lea dst (make-ea :dword :index ecx :scale 2))
(pseudo-atomic
- (allocation dst dst node)
+ (allocation dst dst node *dynamic-extent*)
(inst lea dst (make-ea :byte :base dst :disp list-pointer-lowtag))
;; Convert the count into a raw value, so that we can use the
;; LOOP instruction.
(defvar *maybe-use-inline-allocation* t) ; FIXME unused
;;; Emit code to allocate an object with a size in bytes given by
-;;; Size. The size may be an integer of a TN. If Inline is a VOP
+;;; SIZE. The size may be an integer of a TN. If Inline is a VOP
;;; node-var then it is used to make an appropriate speed vs size
;;; decision.
-;;; This macro should only be used inside a pseudo-atomic section,
-;;; which should also cover subsequent initialization of the
-;;; object.
-(defun allocation (alloc-tn size &optional inline)
- ;; FIXME: since it appears that inline allocation is gone, we should
- ;; remove the INLINE parameter and *MAYBE-USE-INLINE-ALLOCATION*
- (declare (ignore inline))
+(defun allocation-dynamic-extent (alloc-tn size)
+ (inst sub esp-tn size)
+ ;; FIXME: SIZE _should_ be double-word aligned (suggested but
+ ;; unfortunately not enforced by PAD-DATA-BLOCK and
+ ;; WITH-FIXED-ALLOCATION), so that ESP is always divisible by 8 (for
+ ;; 32-bit lispobjs). In that case, this AND instruction is
+ ;; unneccessary and could be removed. If not, explain why. -- CSR,
+ ;; 2004-03-30
+ (inst and esp-tn #.(ldb (byte 32 0) (lognot lowtag-mask)))
+ (aver (not (location= alloc-tn esp-tn)))
+ (inst mov alloc-tn esp-tn)
+ (values))
+
+(defun allocation-notinline (alloc-tn size)
(flet ((load-size (dst-tn size)
(unless (and (tn-p size) (location= alloc-tn size))
(inst mov dst-tn size))))
(t
(load-size edi-tn size)
(inst call (make-fixup (extern-alien-name "alloc_to_edi")
- :foreign))))))))
+ :foreign)))))))))
+
+;;; This macro should only be used inside a pseudo-atomic section,
+;;; which should also cover subsequent initialization of the object.
+;;; (FIXME: so why aren't we asserting this?)
+(defun allocation (alloc-tn size &optional inline dynamic-extent)
+ ;; FIXME: since it appears that inline allocation is gone, we should
+ ;; remove the INLINE parameter and *MAYBE-USE-INLINE-ALLOCATION*
+ (declare (ignore inline))
+ (cond
+ (dynamic-extent (allocation-dynamic-extent alloc-tn size))
+ (t (allocation-notinline alloc-tn size)))
(values))
;;; Allocate an other-pointer object of fixed SIZE with a single word
;;; set with a single operation and cleared with SHR *PSEUDO-ATOMIC-BITS*,-2;
;;; the ATOMIC bit is bit 0, the INTERRUPTED bit is bit 1, and you check
;;; the C flag after the shift to see whether you were interrupted.
+;;;
+;;; KLUDGE: since the stack on the x86 is treated conservatively, it
+;;; does not matter whether a signal occurs during construction of a
+;;; dynamic-extent object, as the half-finished construction of the
+;;; object will not cause any difficulty. We can therefore elide
+(defvar *dynamic-extent* nil)
#!+sb-thread
(defmacro pseudo-atomic (&rest forms)
(with-unique-names (label)
- `(let ((,label (gen-label)))
- (inst fs-segment-prefix)
- (inst mov (make-ea :byte
- :disp (* 4 thread-pseudo-atomic-interrupted-slot)) 0)
- (inst fs-segment-prefix)
- (inst mov (make-ea :byte :disp (* 4 thread-pseudo-atomic-atomic-slot)) 1)
- ,@forms
- (inst fs-segment-prefix)
- (inst mov (make-ea :byte :disp (* 4 thread-pseudo-atomic-atomic-slot)) 0)
- (inst fs-segment-prefix)
- (inst cmp (make-ea :byte
- :disp (* 4 thread-pseudo-atomic-interrupted-slot)) 0)
- (inst jmp :eq ,label)
- ;; if PAI was set, interrupts were disabled at the same time
- ;; using the process signal mask.
- (inst break pending-interrupt-trap)
- (emit-label ,label))))
+ `(if *dynamic-extent* ; I will burn in hell
+ (progn ,@forms)
+ (let ((,label (gen-label)))
+ (inst fs-segment-prefix)
+ (inst mov (make-ea :byte
+ :disp (* 4 thread-pseudo-atomic-interrupted-slot)) 0)
+ (inst fs-segment-prefix)
+ (inst mov (make-ea :byte :disp (* 4 thread-pseudo-atomic-atomic-slot)) 1)
+ ,@forms
+ (inst fs-segment-prefix)
+ (inst mov (make-ea :byte :disp (* 4 thread-pseudo-atomic-atomic-slot)) 0)
+ (inst fs-segment-prefix)
+ (inst cmp (make-ea :byte
+ :disp (* 4 thread-pseudo-atomic-interrupted-slot)) 0)
+ (inst jmp :eq ,label)
+ ;; if PAI was set, interrupts were disabled at the same
+ ;; time using the process signal mask.
+ (inst break pending-interrupt-trap)
+ (emit-label ,label)))))
#!-sb-thread
(defmacro pseudo-atomic (&rest forms)
(with-unique-names (label)
- `(let ((,label (gen-label)))
- ;; FIXME: The MAKE-EA noise should become a MACROLET macro or
- ;; something. (perhaps SVLB, for static variable low byte)
- (inst mov (make-ea :byte :disp (+ nil-value
- (static-symbol-offset
- '*pseudo-atomic-interrupted*)
- (ash symbol-value-slot word-shift)
- ;; FIXME: Use mask, not minus, to
- ;; take out type bits.
- (- other-pointer-lowtag)))
- 0)
- (inst mov (make-ea :byte :disp (+ nil-value
- (static-symbol-offset
- '*pseudo-atomic-atomic*)
- (ash symbol-value-slot word-shift)
- (- other-pointer-lowtag)))
- (fixnumize 1))
- ,@forms
- (inst mov (make-ea :byte :disp (+ nil-value
- (static-symbol-offset
- '*pseudo-atomic-atomic*)
- (ash symbol-value-slot word-shift)
- (- other-pointer-lowtag)))
- 0)
- ;; KLUDGE: Is there any requirement for interrupts to be
- ;; handled in order? It seems as though an interrupt coming
- ;; in at this point will be executed before any pending interrupts.
- ;; Or do incoming interrupts check to see whether any interrupts
- ;; are pending? I wish I could find the documentation for
- ;; pseudo-atomics.. -- WHN 19991130
- (inst cmp (make-ea :byte
- :disp (+ nil-value
- (static-symbol-offset
- '*pseudo-atomic-interrupted*)
- (ash symbol-value-slot word-shift)
- (- other-pointer-lowtag)))
- 0)
- (inst jmp :eq ,label)
- ;; if PAI was set, interrupts were disabled at the same time
- ;; using the process signal mask.
- (inst break pending-interrupt-trap)
- (emit-label ,label))))
-
-
+ `(if *dynamic-extent*
+ (progn ,@forms)
+ (let ((,label (gen-label)))
+ ;; FIXME: The MAKE-EA noise should become a MACROLET macro
+ ;; or something. (perhaps SVLB, for static variable low
+ ;; byte)
+ (inst mov (make-ea :byte :disp (+ nil-value
+ (static-symbol-offset
+ '*pseudo-atomic-interrupted*)
+ (ash symbol-value-slot word-shift)
+ ;; FIXME: Use mask, not minus, to
+ ;; take out type bits.
+ (- other-pointer-lowtag)))
+ 0)
+ (inst mov (make-ea :byte :disp (+ nil-value
+ (static-symbol-offset
+ '*pseudo-atomic-atomic*)
+ (ash symbol-value-slot word-shift)
+ (- other-pointer-lowtag)))
+ (fixnumize 1))
+ ,@forms
+ (inst mov (make-ea :byte :disp (+ nil-value
+ (static-symbol-offset
+ '*pseudo-atomic-atomic*)
+ (ash symbol-value-slot word-shift)
+ (- other-pointer-lowtag)))
+ 0)
+ ;; KLUDGE: Is there any requirement for interrupts to be
+ ;; handled in order? It seems as though an interrupt coming
+ ;; in at this point will be executed before any pending
+ ;; interrupts. Or do incoming interrupts check to see
+ ;; whether any interrupts are pending? I wish I could find
+ ;; the documentation for pseudo-atomics.. -- WHN 19991130
+ (inst cmp (make-ea :byte
+ :disp (+ nil-value
+ (static-symbol-offset
+ '*pseudo-atomic-interrupted*)
+ (ash symbol-value-slot word-shift)
+ (- other-pointer-lowtag)))
+ 0)
+ (inst jmp :eq ,label)
+ ;; if PAI was set, interrupts were disabled at the same
+ ;; time using the process signal mask.
+ (inst break pending-interrupt-trap)
+ (emit-label ,label)))))
\f
;;;; indexed references
+++ /dev/null
-# -*- makefile -*-
-include Config.x86-bsd
-
-ASSEM_SRC += ldso-stubs.S
-OS_LINK_FLAGS = -dynamic -export-dynamic
-
-CFLAGS = -g -Wall -O2
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <sys/file.h>
#include <sys/types.h>
#include <sys/stat.h>
lose("warning: core/runtime address mismatch: DYNAMIC_SPACE_START");
}
#endif
-/* FIXME: Should the conditional here be reg_ALLOC instead of
- * defined(LISP_FEATURE_X86)
- * ? */
-#if defined(LISP_FEATURE_X86)
+#if defined(ALLOCATION_POINTER)
SetSymbolValue(ALLOCATION_POINTER, (lispobj)free_pointer,0);
#else
dynamic_space_free_pointer = free_pointer;
lispobj
load_core_file(char *file)
{
- u32 *header, val, len, *ptr, remaining_len;
+ lispobj *header, val, len, *ptr, remaining_len;
int fd = open(file, O_RDONLY), count;
lispobj initial_function = NIL;
#include "genesis/binding.h"
#include "genesis/thread.h"
-#if defined(LISP_FEATURE_X86)
+#if defined(BINDING_STACK_POINTER)
#define GetBSP() ((struct binding *)SymbolValue(BINDING_STACK_POINTER,thread))
#define SetBSP(value) SetSymbolValue(BINDING_STACK_POINTER, (lispobj)(value),thread)
#else
lispobj old_tl_value;
struct binding *binding;
struct thread *thread=(struct thread *)th;
+#ifdef LISP_FEATURE_SB_THREAD
struct symbol *sym=(struct symbol *)native_pointer(symbol);
+#endif
binding = GetBSP();
SetBSP(binding+1);
#ifdef LISP_FEATURE_SB_THREAD
return nwords;
}
+#ifndef LISP_FEATURE_X86
static int
scav_return_pc_header(lispobj *where, lispobj object)
{
(unsigned long) object);
return 0; /* bogus return value to satisfy static type checking */
}
+#endif /* LISP_FEATURE_X86 */
static lispobj
trans_return_pc_header(lispobj object)
}
#endif
+#ifndef LISP_FEATURE_X86
static int
scav_fun_header(lispobj *where, lispobj object)
{
(unsigned long) object);
return 0; /* bogus return value to satisfy static type checking */
}
+#endif /* LISP_FEATURE_X86 */
static lispobj
trans_fun_header(lispobj object)
return count;
}
-/* Count the number of dont_move pages. */
+#if QSHOW
static int
count_dont_move_pages(void)
{
}
return count;
}
+#endif /* QSHOW */
/* Work through the pages and add up the number of bytes used for the
* given generation. */
* assumes that all objects have been copied or promoted to an older
* generation. Bytes_allocated and the generation bytes_allocated
* counter are updated. The number of bytes freed is returned. */
-extern void i586_bzero(void *addr, int nbytes);
static int
free_oldspace(void)
{
os_invalidate(page_start, PAGE_BYTES*(last_page-first_page));
addr = os_validate(page_start, PAGE_BYTES*(last_page-first_page));
if (addr == NULL || addr != page_start) {
- /* Is this an error condition? I couldn't really tell from
- * the old CMU CL code, which fprintf'ed a message with
- * an exclamation point at the end. But I've never seen the
- * message, so it must at least be unusual..
- *
- * (The same condition is also tested for in gc_free_heap.)
- *
- * -- WHN 19991129 */
- lose("i586_bzero: page moved, 0x%08x ==> 0x%08x",
- page_start,
+ lose("free_oldspace: page moved, 0x%08x ==> 0x%08x",page_start,
addr);
}
} else {
int *page_start;
page_start = (int *)page_address(first_page);
- i586_bzero(page_start, PAGE_BYTES*(last_page-first_page));
+ memset(page_start, 0,PAGE_BYTES*(last_page-first_page));
}
first_page = last_page;
for_each_thread(th) {
void **ptr;
void **esp=(void **)-1;
- int i,free;
#ifdef LISP_FEATURE_SB_THREAD
+ int i,free;
if(th==arch_os_get_current_thread()) {
esp = (void **) &raise;
} else {
extern void post_signal_tramp(void);
void arrange_return_to_lisp_function(os_context_t *context, lispobj function)
{
+#ifndef LISP_FEATURE_X86
void * fun=native_pointer(function);
- char *code = &(((struct simple_fun *) fun)->code);
-
+ void *code = &(((struct simple_fun *) fun)->code);
+#endif
+
/* Build a stack frame showing `interrupted' so that the
* user's backtrace makes (as much) sense (as usual) */
#ifdef LISP_FEATURE_X86
sigsegv_handler(int signal, siginfo_t *info, void* void_context)
{
os_context_t *context = arch_os_get_context(&void_context);
- void* fault_addr = (void*)context->uc_mcontext.cr2;
+ void* fault_addr = (void*)info->si_addr;
if (!gencgc_handle_wp_violation(fault_addr))
if(!handle_control_stack_guard_triggered(context,fault_addr))
interrupt_handle_now(signal, info, void_context);
#include <stdio.h>
#include <errno.h>
-#include <strings.h>
+#include <string.h>
#include "sbcl.h"
#include "os.h"
#define PRINTNOISE
-#if defined(LISP_FEATURE_X86)
-/* again, what's so special about the x86 that this is differently
- * visible there than on other platforms? -dan 20010125
+#if defined(LISP_FEATURE_GENCGC)
+/* this is another artifact of the poor integration between gencgc and
+ * the rest of the runtime: on cheney gc there is a global
+ * dynamic_space_free_pointer which is valid whenever foreign function
+ * call is active, but in gencgc there's no such variable and we have
+ * to keep our own
*/
static lispobj *dynamic_space_free_pointer;
#endif
#endif
}
-static inline newspace_alloc(int nwords, int constantp)
+static inline lispobj *
+newspace_alloc(int nwords, int constantp)
{
lispobj *ret;
nwords=CEILING(nwords,2);
struct cons *old, *new, *orig;
int length;
- orig = newspace_alloc(0,constant);
+ orig = (struct cons *) newspace_alloc(0,constant);
length = 0;
do {
SetSymbolValue(READ_ONLY_SPACE_FREE_POINTER, (lispobj)read_only_free,0);
SetSymbolValue(STATIC_SPACE_FREE_POINTER, (lispobj)static_free,0);
-#if !defined(LISP_FEATURE_X86)
+#if !defined(ALLOCATION_POINTER)
dynamic_space_free_pointer = current_dynamic_space;
set_auto_gc_trigger(bytes_consed_between_gcs);
#else
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
-#if defined(SVR4) || defined(__linux__)
#include <unistd.h>
-#endif
#include <sys/ioctl.h>
#include <termios.h>
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#include <signal.h>
#include <sys/file.h>
#include <stdlib.h>
#include <stdio.h>
+#include <string.h>
#include <sched.h>
#include <signal.h>
#include <stddef.h>
th->pid=kid_pid; /* child will not start until this is set */
}
-pid_t create_initial_thread(lispobj initial_function) {
+void create_initial_thread(lispobj initial_function) {
struct thread *th=create_thread_struct(initial_function);
pid_t kid_pid=getpid();
if(th && kid_pid>0) {
}
}
-#ifdef HOLES
-
-static os_vm_address_t holes[] = HOLES;
-
-static void
-make_holes(void)
-{
- int i;
-
- for (i = 0; i < sizeof(holes)/sizeof(holes[0]); i++) {
- if (os_validate(holes[i], HOLE_SIZE) == NULL) {
- fprintf(stderr,
- "make_holes: failed to validate %ld bytes at 0x%08X\n",
- HOLE_SIZE,
- (unsigned long)holes[i]);
- exit(1);
- }
- os_protect(holes[i], HOLE_SIZE, 0);
- }
-}
-#endif
-
void
validate(void)
{
ensure_space( (lispobj *)DYNAMIC_1_SPACE_START , DYNAMIC_SPACE_SIZE);
#endif
-#ifdef HOLES
- make_holes();
-#endif
-
#ifdef PRINTNOISE
printf(" done.\n");
#endif
*/
#include <stdio.h>
-#include <strings.h>
+#include <string.h>
#include <sys/types.h>
#include <stdlib.h>
free(var);
}
}
- bzero(NameHash, sizeof(NameHash));
- bzero(ObjHash, sizeof(ObjHash));
+ memset(NameHash, 0, sizeof(NameHash));
+ memset(ObjHash, 0, sizeof(ObjHash));
tempcntr = 1;
for (var = perm; var != NULL; var = next) {
#include "sbcl.h"
#include "util.h"
-/* KLUDGE: Neither the OpenBSD nor the Linux man page give a header
- * file to find this in (?). -- WHN 2002-02-07 */
+/* Although it might seem as though this should be in some standard
+ Unix header, according to Perry E. Metzger, in a message on
+ sbcl-devel dated 2004-03-29, this is the POSIXly-correct way of
+ using environ: by an explicit declaration. -- CSR, 2004-03-30 */
extern char **environ;
\f
/*
ret
.size GNAME(do_pending_interrupt),.-GNAME(do_pending_interrupt)
\f
-#ifdef LISP_FEATURE_GENCGC
-/* This is a fast bzero using the FPU. The first argument is the start
- * address which needs to be aligned on an 8 byte boundary, the second
- * argument is the number of bytes, which must be a nonzero multiple
- * of 8 bytes. */
-/* FIXME whether this is still faster than using the OS's bzero or
- * equivalent, we don't know */
- .text
- .globl GNAME(i586_bzero)
- .type GNAME(i586_bzero),@function
- .align align_4byte,0x90
-GNAME(i586_bzero):
- movl 4(%esp),%edx # Load the start address.
- movl 8(%esp),%eax # Load the number of bytes.
- fldz
-l1: fstl 0(%edx)
- addl $8,%edx
- subl $8,%eax
- jnz l1
- fstp %st(0)
- ret
- .size GNAME(i586_bzero),.-GNAME(i586_bzero)
-#endif
-\f
/*
* Allocate bytes and return the start of the allocated space
(type (unsigned-byte 32) i))
(deref a i))))
(compiler-note () (error "The code is not optimized.")))
+
+(handler-case
+ (compile nil '(lambda (x)
+ (declare (type (integer -100 100) x))
+ (declare (optimize speed))
+ (declare (notinline identity))
+ (1+ (identity x))))
+ (compiler-note () (error "IDENTITY derive-type not applied.")))
;;; An &AUX variable in a boa-constructor without a default value
;;; means "do not initialize slot" and does not cause type error
+(declaim (notinline opaque-identity))
+(defun opaque-identity (x) x)
+
(defstruct (boa-saux (:constructor make-boa-saux (&aux a (b 3) (c))))
(a #\! :type (integer 1 2))
(b #\? :type (integer 3 4))
(c #\# :type (integer 5 6)))
(let ((s (make-boa-saux)))
- (declare (notinline identity))
(locally (declare (optimize (safety 3))
(inline boa-saux-a))
- (assert (raises-error? (identity (boa-saux-a s)) type-error)))
+ (assert (raises-error? (opaque-identity (boa-saux-a s)) type-error)))
(setf (boa-saux-a s) 1)
(setf (boa-saux-c s) 5)
(assert (eql (boa-saux-a s) 1))
; these two checks should be
; kept separated
(let ((s (make-boa-saux)))
- (declare (notinline identity))
(locally (declare (optimize (safety 0))
(inline boa-saux-a))
- (assert (eql (identity (boa-saux-a s)) 0)))
+ (assert (eql (opaque-identity (boa-saux-a s)) 0)))
(setf (boa-saux-a s) 1)
(setf (boa-saux-c s) 5)
(assert (eql (boa-saux-a s) 1))
(assert (eql (boa-saux-c s) 5)))
(let ((s (make-boa-saux)))
- (declare (notinline identity))
(locally (declare (optimize (safety 3))
(notinline boa-saux-a))
- (assert (raises-error? (identity (boa-saux-a s)) type-error)))
+ (assert (raises-error? (opaque-identity (boa-saux-a s)) type-error)))
(setf (boa-saux-a s) 1)
(setf (boa-saux-c s) 5)
(assert (eql (boa-saux-a s) 1))
--- /dev/null
+;;;; tests that dynamic-extent functionality works.
+
+;;;; This software is part of the SBCL system. See the README file for
+;;;; more information.
+;;;;
+;;;; While most of SBCL is derived from the CMU CL system, the test
+;;;; files (like this one) were written from scratch after the fork
+;;;; from CMU CL.
+;;;;
+;;;; This software is in the public domain and is provided with
+;;;; absolutely no warranty. See the COPYING and CREDITS files for
+;;;; more information.
+
+;;; &REST lists
+(defmacro defun-with-dx (name arglist &body body)
+ `(locally
+ (declare (optimize sb-c::stack-allocate-dynamic-extent))
+ (defun ,name ,arglist
+ ,@body)))
+
+(defun-with-dx dxlength (&rest rest)
+ (declare (dynamic-extent rest))
+ (length rest))
+
+(assert (= (dxlength 1 2 3) 3))
+(assert (= (dxlength t t t t t t) 6))
+(assert (= (dxlength) 0))
+
+(defun callee (list)
+ (destructuring-bind (a b c d e f &rest g) list
+ (+ a b c d e f (length g))))
+
+(defun-with-dx dxcaller (&rest rest)
+ (declare (dynamic-extent rest))
+ (callee rest))
+
+(assert (= (dxcaller 1 2 3 4 5 6 7) 22))
+\f
+(sb-ext:quit :unix-status 104)
\ No newline at end of file
(assert (not (array-has-fill-pointer-p *array*)))))
(when tmp-fasl (delete-file tmp-fasl))
(delete-file *tmp-filename*))))
+
+(quit :unix-status 104)
DEFSIGNAL(SIGBUS);
DEFSIGNAL(SIGCHLD);
DEFSIGNAL(SIGCONT);
-/* FIXME: Maybe #ifdef SIGEMT would be a smarter conditional? */
-#if (!(defined LISP_FEATURE_LINUX) || !((defined LISP_FEATURE_PPC) || (defined LISP_FEATURE_X86)))
+#ifdef SIGEMT
DEFSIGNAL(SIGEMT);
#endif
DEFSIGNAL(SIGFPE);
;;; checkins which aren't released. (And occasionally for internal
;;; versions, especially for internal versions off the main CVS
;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".)
-"0.8.9.6.netbsd.3"
+"0.8.9.29"