/
compiler.texinfo
1117 lines (930 loc) · 39.9 KB
/
compiler.texinfo
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
@node Compiler
@comment node-name, next, previous, up
@chapter 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
* Diagnostic Messages::
* Handling of Types::
* Compiler Policy::
* Compiler Errors::
* Open Coding and Inline Expansion::
* Interpreter::
@end menu
@node Diagnostic Messages
@comment node-name, next, previous, up
@section Diagnostic Messages
@cindex Messages, Compiler
@cindex Compiler messages
@menu
* Controlling Verbosity::
* Diagnostic Severity::
* Understanding Compiler Diagnostics::
@end menu
@node Controlling Verbosity
@comment node-name, next, previous, up
@subsection Controlling Verbosity
The compiler can be quite verbose in its diagnostic reporting, rather
more then some users would prefer -- the amount of noise emitted can
be controlled, however.
To control emission of compiler diagnostics (of any severity other
than @code{error}: @pxref{Diagnostic Severity}) use the
@code{sb-ext:muffle-conditions} and @code{sb-ext:unmuffle-conditions}
declarations, specifying the type of condition that is to be muffled
(the muffling is done using an associated @code{muffle-warning} restart).
Global control:
@lisp
;;; Muffle compiler-notes globally
(declaim (sb-ext:muffle-conditions sb-ext:compiler-note))
@end lisp
Local control:
@lisp
;;; Muffle compiler-notes based on lexical scope
(defun foo (x)
(declare (optimize speed) (fixnum x)
(sb-ext:muffle-conditions sb-ext:compiler-note))
(values (* x 5) ; no compiler note from this
(locally
(declare (sb-ext:unmuffle-conditions sb-ext:compiler-note))
;; this one gives a compiler note
(* x -5))))
@end lisp
@deffn {Declaration} sb-ext:muffle-conditions
Syntax: type*
Muffles the diagnostic messages that would be caused by compile-time
signals of given types.
@end deffn
@deffn {Declaration} sb-ext:unmuffle-conditions
Syntax: type*
Cancels the effect of a previous @code{sb-ext:muffle-condition}
declaration.
@end deffn
Various details of @emph{how} the compiler messages are printed can be
controlled via the alist
@code{sb-ext:*compiler-print-variable-alist*}.
@include var-sb-ext-star-compiler-print-variable-alist-star.texinfo
For information about muffling warnings signaled outside of the
compiler, see @ref{Customization Hooks for Users}.
@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{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 Diagnostic Severity
@comment node-name, next, previous, up
@subsection Diagnostic Severity
@cindex Severity of compiler messages
@cindex Compiler Diagnostic Severity
@tindex error
@tindex warning
@tindex style-warning
@tindex compiler-note
@tindex code-deletion-note
There are four levels of compiler diagnostic severity:
@enumerate 1
@item error
@item warning
@item style warning
@item note
@end enumerate
The first three levels correspond to condition classes which are
defined in the ANSI standard for Common Lisp and which have special
significance to the @code{compile} and @code{compile-file} functions.
These levels of compiler error severity occur when the compiler
handles conditions of these classes.
The fourth level of compiler error severity, @emph{note}, corresponds
to the @code{sb-ext:compiler-note}, and is used for problems which are
too mild for the standard condition classes, typically hints about how
efficiency might be improved. The @code{sb-ext:code-deletion-note}, a
subtype of @code{compiler-note}, is signalled when the compiler
deletes user-supplied code, usually after proving that the code in
question is unreachable.
Future work for SBCL includes expanding this hierarchy of types to
allow more fine-grained control over emission of diagnostic messages.
@include condition-sb-ext-compiler-note.texinfo
@include condition-sb-ext-code-deletion-note.texinfo
@node Understanding Compiler Diagnostics
@comment node-name, next, previous, up
@subsection Understanding Compile Diagnostics
The messages emitted by the compiler contain a lot of detail in a
terse format, so they may be confusing at first. The messages will be
illustrated using this example program:
@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 a Compiler Diagnostic::
* The Original and Actual Source::
* The Processing Path::
@end menu
@node The Parts of a Compiler Diagnostic
@comment node-name, next, previous, up
@subsubsection The Parts of a Compiler Diagnostic
When processing this program, the compiler will produce this warning:
@example
; file: /tmp/foo.lisp
; in: DEFUN FOO
; (ZOQ Y)
; --> ROQ PLOQ
; ==>
; (+ Y 3)
;
; caught WARNING:
; Asserted type NUMBER conflicts with derived type (VALUES SYMBOL &OPTIONAL).
@end example
In this example we see each of the six possible parts of a compiler
diagnostic:
@enumerate
@item
@findex with-compilation-unit
@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 diagnostic. 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
@cindex Original Source
@samp{(ZOQ Y)} This is the @dfn{original source} form responsible for
the diagnostic. Original source means that the form directly appeared
in the original input to the compiler, i.e. in the lambda passed to
@code{compile} or in the top level form read from the source file. In
this example, the expansion of the @code{zoq} macro was responsible
for the message.
@item
@cindex Processing Path
@samp{--> ROQ PLOQ} This is the @dfn{processing path} that the
compiler used to produce the code that caused the message to be
emitted. The processing path is a representation of the evaluated
forms enclosing the actual source that the compiler encountered when
processing the original source. The path is the first element of each
form, or the form itself if the form is not a list. These forms result
from the expansion of macros or source-to-source transformation done
by the compiler. In this example, the enclosing evaluated forms are
the calls to @code{roq} and @code{ploq}. These calls resulted from the
expansion of the @code{zoq} macro.
@item
@cindex Actual Source
@samp{==> (+ Y 3)} This is the @dfn{actual source} responsible for the
diagnostic. If the actual source appears in the explanation, then we
print the next enclosing evaluated form, instead of printing the
actual source twice. (This is the form that would otherwise have been
the last form of the processing path.) In this example, the problem is
with the evaluation of the reference to the variable @code{y}.
@item
@samp{caught WARNING: Asserted type NUMBER conflicts with derived type
(VALUES SYMBOL &OPTIONAL).} This is the @dfn{explanation} of the
problem. In this example, the problem is that, while the call to
@code{+} requires that its arguments are all of type @code{number},
the compiler has derived that @code{y} will evaluate to a
@code{symbol}. Note that @samp{(VALUES SYMBOL &OPTIONAL)} expresses
that @code{y} evaluates to precisely one value.
@end enumerate
Note that each part of the 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.
@comment no it isn't.
@item
The explanation is prefixed with the diagnostic severity, which can be
@samp{caught ERROR:}, @samp{caught WARNING:}, @samp{caught
STYLE-WARNING:}, or @samp{note:}.
@end itemize
Each part of the message is more specific than the preceding one. If
consecutive messages are for nearby locations, then the front part of
the messages would be the same. In this case, the compiler omits as
much of the second message as in common with the first. For example:
@example
; file: /tmp/foo.lisp
; in: DEFUN FOO
; (ZOQ Y)
; --> ROQ
; ==>
; (PLOQ (+ Y 3))
;
; caught STYLE-WARNING:
; undefined function: PLOQ
; ==>
; (ROQ (PLOQ (+ Y 3)))
;
; caught STYLE-WARNING:
; undefined function: ROQ
@end example
@comment fixing that weird blank line might be good
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
@comment node-name, next, previous, up
@subsubsection The Original and Actual Source
@cindex Original Source
@cindex Actual Source
The @emph{original source} displayed will almost always be a list. If
the actual source for an message is a symbol, the original source will
be the immediately enclosing evaluated list form. So even if the
offending symbol does appear in the original source, the compiler will
print the enclosing list and then print the symbol as the actual
source (as though the symbol were introduced by a macro.)
When the @emph{actual source} is displayed (and is not a symbol), it
will always be code that resulted from the expansion of a macro or a
source-to-source compiler optimization. This is code that did not
appear in the original source program; it was introduced by the
compiler.
Keep in mind that when the compiler displays a source form in an
diagnostic message, it always displays the most specific (innermost)
responsible form. For example, compiling this function
@lisp
(defun bar (x)
(let (a)
(declare (fixnum a))
(setq a (foo x))
a))
@end lisp
gives this error message
@example
; file: /tmp/foo.lisp
; in: DEFUN BAR
; (LET (A)
; (DECLARE (FIXNUM A))
; (SETQ A (FOO X))
; A)
;
; caught WARNING:
; Asserted type FIXNUM conflicts with derived type (VALUES NULL &OPTIONAL).
@end example
This message is not saying ``there is a problem somewhere in this
@code{let}'' -- it is saying that there is a problem with the
@code{let} itself. In this example, the problem is that @code{a}'s
@code{nil} initial value is not a @code{fixnum}.
@node The Processing Path
@comment node-name, next, previous, up
@subsubsection 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 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 Handling of Types
@comment node-name, next, previous, up
@section 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.
@findex satisfies
The SBCL compiler also has a greater knowledge of the Common Lisp
type system than other compilers. Support is incomplete only for types
involving the @code{satisfies} type specifier.
@c <!-- FIXME: See also sections \ref{advanced-type-stuff}
@c and \ref{type-inference}, once we snarf them from the
@c CMU CL manual. -->
@c
@c Also see my paper on improving Baker, when I get round to it.
@c
@c Whose paper?
@menu
* Declarations as Assertions::
* Precise Type Checking::
* Getting Existing Programs to Run::
* Implementation Limitations::
@end menu
@node Declarations as Assertions
@comment node-name, next, previous, up
@subsection Declarations as Assertions
@findex safety
The SBCL compiler treats type declarations differently from most
other Lisp compilers. Under default compilation policy the compiler
doesn't blindly believe type declarations, but considers them
assertions about the program that should be checked: all type
declarations that have not been proven to always hold are asserted at
runtime.
@quotation
@emph{Remaining bugs in the compiler's handling of types unfortunately
provide some exceptions to this rule, see @ref{Implementation
Limitations}).}
@end quotation
There are three type checking policies available in SBCL,
selectable via @code{optimize} declarations.
@table @strong
@c FIXME: This should be properly integrated with general policy
@c stuff, once that gets cleaned up.
@item Full Type Checks
All declarations are considered assertions to be checked at runtime,
and all type checks are precise. The default compilation policy
provides full type checks.
Used when @code{(or (>= safety 2) (>= safety speed 1))}.
@item Weak Type Checks
Declared types may be simplified into faster to check supertypes: for example,
@code{(and unsigned-byte fixnum)} is simplified into @code{fixnum}.
@strong{Note}: it is relatively easy to corrupt the heap when weak
type checks are used if the program contains type-errors.
Used when @code{(and (< safety 2) (< safety speed))}
@item No Type Checks
All declarations are believed without assertions. Also disables
argument count and array bounds checking.
@strong{Note}: any type errors in code where type checks are not
performed are liable to corrupt the heap.
Used when @code{(= safety 0)}.
@end table
@node Precise Type Checking
@comment node-name, next, previous, up
@subsection Precise Type Checking
@cindex Precise type checking
@cindex Type checking, precise
Precise checking means that the check is done as though @code{typep}
had been called with the exact type specifier that appeared in the
declaration.
If a variable is declared to be @code{(integer 3 17)} then its value
must always be an integer between @code{3} and @code{17}. If multiple
type declarations apply to a single variable, then all the
declarations must be correct; it is as though all the types were
intersected producing a single @code{and} type specifier.
To gain maximum benefit from the compiler's type checking, you should
always declare the types of function arguments and structure slots as
precisely as possible. This often involves the use of @code{or},
@code{member}, and other list-style type specifiers.
@node Getting Existing Programs to Run
@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 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
@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. However, the compiler is known to fall short of this goal in
two areas:
@itemize
@item
@emph{Proclaimed} 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.
For example,
@lisp
(defun foo (x)
(the integer (bar x)))
@end lisp
causes the following compiler diagnostic to be emitted:
@example
; note: type assertion too complex to check:
; (VALUES INTEGER &REST T).
@end example
A partial workaround is instead write:
@lisp
(defun foo (x)
(the (values integer &optional) (bar x)))
@end lisp
@end itemize
These are important issues, but are not necessarily easy to fix, so
they may, alas, remain in the system for a while.
@node Compiler Policy
@comment node-name, next, previous, up
@section Compiler Policy
Compiler policy is controlled by the @code{optimize} declaration,
supporting all ANSI optimization qualities (@code{debug},
@code{safety}, @code{space}, and @code{speed}).@footnote{A deprecated
extension @code{sb-ext:inhibit-warnings} is still supported, but
liable to go away at any time.}
For effects of various optimization qualities on type-safety and
debuggability see @ref{Declarations as Assertions} and @ref{Debugger
Policy Control}.
Ordinarily, when the @code{speed} quality is high, the compiler emits
notes to notify the programmer about its inability to apply various
optimizations. For selective muffling of these notes @xref{Controlling
Verbosity}.
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 even 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 _ ... and checking of tag existence in RETURN-FROM and GO.
@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 Compiler Errors
@comment node-name, next, previous, up
@section Compiler Errors
@menu
* Type Errors at Compile Time::
* Errors During Macroexpansion::
* Read Errors::
@end menu
@node Type Errors at Compile Time
@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.
@node Errors During Macroexpansion
@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