1 ;;;; A compiler from simple top-level forms to FASL operations.
3 ;;;; This software is part of the SBCL system. See the README file for
6 ;;;; This software is derived from the CMU CL system, which was
7 ;;;; written at Carnegie Mellon University and released into the
8 ;;;; public domain. The software is in the public domain and is
9 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
10 ;;;; files for more information.
14 ;;; SBCL has no proper byte compiler (having ditched the rather
15 ;;; ambitious and slightly flaky byte compiler inherited from CMU CL)
16 ;;; but its FOPs are a sort of byte code which is expressive enough
17 ;;; that we can compile some simple toplevel forms directly to them,
18 ;;; including very common operations like the forms that DEFVARs and
19 ;;; DECLAIMs macroexpand into.
21 ;;; FIXME: The expexnasion problem.
22 ;;; FOPCOMPILE and FOPCOMPILABLE-P cause multiple expansion of macros,
23 ;;; which may be problematic with side-effecting macros. When
24 ;;; FOPCOMPILABLE-P succeeds, FOPCOMPILE is called, resulting in
25 ;;; double macroexpansion. When FOPCOMPILABLE-P fails,
26 ;;; IR1-CONVERT-FUNCTOID expands already expanded macros for a second
28 ;;; And an edge case, when the top-level call has a complier-macro
29 ;;; which returns &whole it gets expanded three times, two times by
30 ;;; FOPCOMPILABLE-P and FOPCOMPILE, and one time by
31 ;;; PROCESS-TOPLEVEL-FORM, because unlike other macros, the expanded
32 ;;; form is still a macro-form. That's what the EXPAND optional
33 ;;; parameter solves, PROCESS-TOPLEVEL-FORM passes NIL, expanding
34 ;;; compiler macros at most once.
35 ;;; The instances of double expansion still remain, e.g. (fun (macro)),
36 ;;; since PROCESS-TOPLEVEL-FORM only expands the macros at the first
39 (flet ((setq-fopcompilable-p (args)
40 (loop for
(name value
) on args by
#'cddr
41 always
(and (symbolp name
)
42 (member (info :variable
:kind name
)
44 (fopcompilable-p value
))))
45 (cold-svset-fopcompilable-p (args)
46 (destructuring-bind (thing index value
) args
49 (eq (info :variable
:kind thing
) :global
)
50 (typep value
'(cons (eql function
) (cons symbol null
)))))))
51 (defun fopcompilable-p (form &optional
(expand t
))
52 ;; We'd like to be able to handle
53 ;; -- simple funcalls, nested recursively, e.g.
54 ;; (SET '*PACKAGE* (FIND-PACKAGE "CL-USER"))
55 ;; -- common self-evaluating forms like strings and keywords and
56 ;; fixnums, which are important for terminating
57 ;; the recursion of the simple funcalls above
58 ;; -- quoted lists (which are important for PROCLAIMs, which are
59 ;; common toplevel forms)
60 ;; -- fopcompilable stuff wrapped around non-fopcompilable expressions,
62 ;; (%DEFUN 'FOO (LAMBDA () ...) ...)
63 ;; -- the IF special form, to support things like (DEFVAR *X* 0)
64 ;; expanding into (UNLESS (BOUNDP '*X*) (SET '*X* 0))
66 ;; Special forms which we don't currently handle, but might consider
67 ;; supporting in the future are LOCALLY (with declarations),
68 ;; MACROLET, SYMBOL-MACROLET and THE.
69 ;; Also, if (FLET ((F () ...)) (DEFUN A () ...) (DEFUN B () ...))
70 ;; were handled, then it would probably automatically work in
71 ;; the cold loader too, providing definitions for A and B before
72 ;; executing all other toplevel forms.
75 (or (and (self-evaluating-p form
)
76 (constant-fopcompilable-p form
))
78 (let ((function (car form
)))
79 ;; It is assumed that uses of recognized functions are
80 ;; carefully controlled, and recursion on fopcompilable-p
82 (or (member function
'(sb!impl
::%defun
84 sb
!kernel
::%defstruct
))
85 (and (symbolp function
) ; no ((lambda ...) ...)
86 (get-properties (symbol-plist function
)
87 '(:sb-cold-funcall-handler
/for-effect
88 :sb-cold-funcall-handler
/for-value
)))
89 (and (eq function
'setf
)
90 (fopcompilable-p (%macroexpand form
*lexenv
*)))
91 (and (eq function
'sb
!kernel
:%svset
)
92 (cold-svset-fopcompilable-p (cdr form
)))
93 (and (eq function
'setq
)
94 (setq-fopcompilable-p (cdr form
))))))))
98 (%macroexpand form
*lexenv
*)
102 (expand-compiler-macro form
)
104 (or (and (self-evaluating-p form
)
105 (constant-fopcompilable-p form
))
107 (multiple-value-bind (macroexpansion macroexpanded-p
)
110 (fopcompilable-p macroexpansion
)
111 ;; Punt on :ALIEN variables
112 (let ((kind (info :variable
:kind form
)))
113 (member kind
'(:special
:constant
:global
:unknown
))))))
115 (ignore-errors (list-length form
))
116 (let ((macroexpansion (expand-cm form
)))
117 (if (neq macroexpansion form
)
118 (return-from fopcompilable-p
(fopcompilable-p macroexpansion
))
120 (multiple-value-bind (macroexpansion macroexpanded-p
)
123 (fopcompilable-p macroexpansion
)
124 (destructuring-bind (operator &rest args
) form
126 ;; Special operators that we know how to cope with
128 (every #'fopcompilable-p args
))
130 (and (= (length args
) 1)
131 (constant-fopcompilable-p (car args
))))
133 (and (= (length args
) 1)
134 ;; #'(LAMBDA ...), #'(NAMED-LAMBDA ...), etc. These
135 ;; are not fopcompileable as such, but we can compile
136 ;; the lambdas with the real compiler, and the rest
137 ;; of the expression with the fop-compiler.
138 (or (and (lambda-form-p (car args
))
139 ;; The lambda might be closing over some
140 ;; variable, punt. As a further improvement,
141 ;; we could analyze the lambda body to
142 ;; see whether it really closes over any
143 ;; variables. One place where even simple
144 ;; analysis would be useful are the PCL
145 ;; slot-definition type-check-functions
146 ;; -- JES, 2007-01-13
147 (notany (lambda (binding)
148 (lambda-var-p (cdr binding
)))
149 (lexenv-vars *lexenv
*)))
150 ;; #'FOO, #'(SETF FOO), etc
151 (legal-fun-name-p (car args
)))))
153 (and (<= 2 (length args
) 3)
154 (every #'fopcompilable-p args
)))
155 ;; Allow SETQ only on special or global variables
157 (setq-fopcompilable-p args
))
158 ;; The real toplevel form processing has already been
159 ;; done, so EVAL-WHEN handling will be easy.
161 (and (>= (length args
) 1)
162 (eq (set-difference (car args
)
170 (every #'fopcompilable-p
(cdr args
))))
171 ;; A LET or LET* that introduces only lexical
172 ;; bindings might be fopcompilable, depending on
173 ;; whether something closes over the bindings.
174 ;; (And whether there are declarations in the body,
177 (let-fopcompilable-p operator args
))
179 (every #'fopcompilable-p args
))
181 ;; ordinary function calls
182 (and (symbolp operator
)
183 ;; If a LET/LOCALLY tries to introduce
184 ;; declarations, we'll detect it here, and
185 ;; disallow fopcompilation. This is safe,
186 ;; since defining a function/macro named
187 ;; DECLARE would violate a package lock.
188 (not (eq operator
'declare
))
189 (not (special-operator-p operator
))
190 (not (macro-function operator
)) ; redundant check
191 ;; We can't FOP-FUNCALL with more than 255
192 ;; parameters. (We could theoretically use
193 ;; APPLY, but then we'd need to construct
194 ;; the parameter list for APPLY without
195 ;; calling LIST, which is probably more
196 ;; trouble than it's worth).
197 (<= (length args
) 255)
198 (every #'fopcompilable-p args
))))))))))))
200 (defun let-fopcompilable-p (operator args
)
201 (when (>= (length args
) 1)
202 (multiple-value-bind (body decls
)
203 (parse-body (cdr args
) :doc-string-allowed nil
)
204 (declare (ignore body
))
205 (let* ((orig-lexenv *lexenv
*)
206 (*lexenv
* (make-lexenv)))
207 ;; We need to check for declarations
208 ;; first. Otherwise the fake lexenv we're
209 ;; constructing might be invalid.
211 (loop for binding in
(car args
)
212 for name
= (if (consp binding
)
215 for value
= (if (consp binding
)
218 ;; Only allow binding locals, since special bindings can't
219 ;; be easily expressed with fops.
220 always
(and (eq (info :variable
:kind name
)
222 (let ((*lexenv
* (ecase operator
225 (fopcompilable-p value
)))
227 (setf *lexenv
* (make-lexenv))
229 (make-lambda-var :%source-name name
))
230 (lexenv-vars *lexenv
*))))
231 (every #'fopcompilable-p
(cdr args
)))))))
233 (defun lambda-form-p (form)
236 '(lambda named-lambda lambda-with-lexenv
))))
238 ;;; Check that a literal form is fopcompilable. It would not be, for example,
239 ;;; when the form contains structures with funny MAKE-LOAD-FORMS.
240 (defun constant-fopcompilable-p (constant)
241 (let ((xset (alloc-xset)))
242 (labels ((grovel (value)
243 ;; Unless VALUE is an object which which obviously
244 ;; can't contain other objects
245 ;; FIXME: OAOOM. See MAYBE-EMIT-MAKE-LOAD-FORMS.
247 '(or #-sb-xc-host unboxed-array
252 (if (xset-member-p value xset
)
253 (return-from grovel nil
)
254 (add-to-xset value xset
))
258 (grovel (cdr value
)))
260 (dotimes (i (length value
))
261 (grovel (svref value i
))))
263 (dotimes (i (length value
))
264 (grovel (aref value i
))))
266 ;; Even though the (ARRAY T) branch does the exact
267 ;; same thing as this branch we do this separately
268 ;; so that the compiler can use faster versions of
269 ;; array-total-size and row-major-aref.
270 (dotimes (i (array-total-size value
))
271 (grovel (row-major-aref value i
))))
273 (dotimes (i (array-total-size value
))
274 (grovel (row-major-aref value i
))))
275 ;; This is the same kludge as appears in EMIT-MAKE-LOAD-FORM
276 ;; which informs the xc that LAYOUTs are leaf-like nodes.
277 ;; This case was never reached before because cross-compiling
278 ;; used to generate target machine code for everything.
279 #+sb-xc-host
(layout)
281 (multiple-value-bind (creation-form init-form
)
283 (sb!xc
:make-load-form value
(make-null-lexenv))
285 (compiler-error condition
)))
286 (declare (ignore init-form
))
288 (:sb-just-dump-it-normally
289 ;; FIXME: Why is this needed? If the constant
290 ;; is deemed fopcompilable, then when we dump
291 ;; it we bind *dump-only-valid-structures* to
293 (fasl-validate-structure value
*compile-object
*)
294 ;; The above FIXME notwithstanding,
295 ;; there's never a need to grovel a layout.
296 (do-instance-tagged-slot (i value
)
297 (grovel (%instance-ref value i
))))
300 (return-from constant-fopcompilable-p nil
)))))
302 (return-from constant-fopcompilable-p nil
))))))
306 ;;; FOR-VALUE-P is true if the value will be used (i.e., pushed onto
307 ;;; FOP stack), or NIL if any value will be discarded. FOPCOMPILABLE-P
308 ;;; has already ensured that the form can be fopcompiled.
310 ;;; See the expansion problem FIXME above fopcompilable-p.
311 (defun fopcompile (form path for-value-p
&optional
(expand t
))
312 (let ((path (or (get-source-path form
) (cons form path
))))
313 (flet ((expand (form)
315 (%macroexpand form
*lexenv
*)
319 (expand-compiler-macro form
)
321 (cond ((self-evaluating-p form
)
322 (fopcompile-constant form for-value-p
))
324 (multiple-value-bind (macroexpansion macroexpanded-p
)
328 (fopcompile macroexpansion path for-value-p
)
329 (let ((kind (info :variable
:kind form
)))
333 (fopcompile `(symbol-value ',form
) path for-value-p
))
335 ((member kind
'(:global
:constant
))
336 ;; Global variable or constant.
337 (fopcompile `(symbol-global-value ',form
) path for-value-p
))
340 (let* ((lambda-var (cdr (assoc form
(lexenv-vars *lexenv
*))))
341 (handle (when lambda-var
342 (lambda-var-fop-value lambda-var
))))
344 (setf (lambda-var-ever-used lambda-var
) t
)
346 (sb!fasl
::dump-push handle
*compile-object
*)))
348 ;; Undefined variable. Signal a warning, and
349 ;; treat it as a special variable reference, like
350 ;; the real compiler does -- do not elide even if
351 ;; the value is unused.
352 (note-undefined-reference form
:variable
)
353 (fopcompile `(symbol-value ',form
)
355 for-value-p
))))))))))
357 (let ((macroexpansion (expand-cm form
)))
358 (if (neq macroexpansion form
)
359 ;; could expand into an atom, so start from the top
360 (return-from fopcompile
361 (fopcompile macroexpansion path for-value-p
))))
362 (multiple-value-bind (macroexpansion macroexpanded-p
)
365 (fopcompile macroexpansion path for-value-p
)
366 (destructuring-bind (operator &rest args
) form
368 ;; The QUOTE special operator is worth handling: very
369 ;; easy and very common at toplevel.
371 (fopcompile-constant (second form
) for-value-p
))
372 ;; A FUNCTION needs to be compiled properly, but doesn't
373 ;; need to prevent the fopcompilation of the whole form.
374 ;; We just compile it, and emit an instruction for pushing
375 ;; the function handle on the FOP stack.
377 (fopcompile-function (second form
) path for-value-p
))
378 ;; KLUDGE! SB!C:SOURCE-LOCATION calls are normally handled
379 ;; by a compiler-macro. But if SPACE > DEBUG we choose not
380 ;; to record locations, which is strange because the main
381 ;; compiler does not have similar logic afaict.
383 ;; FIXME: since the fopcompiler expands compiler-macros,
384 ;; this case should probably be killed. It can't execute.
385 (if (policy *policy
* (and (> space
1)
387 (fopcompile-constant nil for-value-p
)
388 (fopcompile (let ((*current-path
* path
))
389 (make-definition-source-location))
393 (fopcompile-if args path for-value-p
))
395 (if (and for-value-p
(endp args
))
396 (fopcompile nil path t
)
397 (loop for
(arg . next
) on args
403 (if (and for-value-p
(endp args
))
404 (fopcompile nil path t
)
405 (loop for
(name value . next
) on args by
#'cddr
406 do
(fopcompile `(set ',name
,value
) path
411 (destructuring-bind (situations &body body
) args
412 (if (or (member :execute situations
)
413 (member 'eval situations
))
414 (fopcompile (cons 'progn body
) path for-value-p
)
415 (fopcompile nil path for-value-p
))))
417 (let ((orig-lexenv *lexenv
*)
418 (*lexenv
* (make-lexenv :default
*lexenv
*))
420 (loop for binding in
(car args
)
421 for name
= (if (consp binding
)
424 for value
= (if (consp binding
)
428 (let ((*lexenv
* (if (eql operator
'let
)
431 (fopcompile value path t
))
432 (let* ((obj (sb!fasl
::dump-pop
*compile-object
*))
433 (var (make-lambda-var
439 :vars
(list (cons name var
))))))
440 (fopcompile (cons 'progn
(cdr args
)) path for-value-p
)
442 (and *source-info
* path
))
443 (let* ((tlf (source-path-tlf-number path
))
444 (file-info (source-info-file-info *source-info
*))
445 (*compiler-error-context
*
446 (make-compiler-error-context
447 :original-source
(stringify-form form
)
448 :file-name
(file-info-name file-info
)
450 (nth-value 1 (find-source-root tlf
*source-info
*))
451 :original-source-path
(source-path-original-source path
)
453 (note-unreferenced-vars vars
*policy
*)))))
454 ;; Otherwise it must be an ordinary funcall.
457 ;; Special hack: there's already a fop for
458 ;; find-undeleted-package-or-lose, so use it.
459 ;; (We could theoretically do the same for
460 ;; other operations, but I don't see any good
461 ;; candidates in a quick read-through of
462 ;; src/code/fop.lisp.)
464 'sb
!int
:find-undeleted-package-or-lose
)
467 (fopcompile (first args
) path t
)
468 (sb!fasl
::dump-fop
'sb
!fasl
::fop-package
471 (when (eq (info :function
:where-from operator
) :assumed
)
472 (note-undefined-reference operator
:function
))
473 (fopcompile-constant operator t
)
475 (fopcompile arg path t
))
477 (sb!fasl
::dump-fop
'sb
!fasl
::fop-funcall
479 (sb!fasl
::dump-fop
'sb
!fasl
::fop-funcall-for-effect
481 (let ((n-args (length args
)))
482 ;; stub: FOP-FUNCALL isn't going to be usable
483 ;; to compile more than this, since its count
484 ;; is a single byte. Maybe we should just punt
485 ;; to the ordinary compiler in that case?
486 (aver (<= n-args
255))
487 (sb!fasl
::dump-byte n-args
*compile-object
*))))))))))
489 (bug "looks unFOPCOMPILEable: ~S" form
))))))
491 (defun fopcompile-function (form path for-value-p
)
492 (flet ((dump-fdefinition (name)
493 (fopcompile `(fdefinition ',name
) path for-value-p
)))
496 ;; Lambda forms are compiled with the real compiler
497 ((lambda-form-p form
)
498 (let* ((handle (%compile form
502 (sb!fasl
::dump-push handle
*compile-object
*))))
503 ;; While function names are translated to a call to FDEFINITION.
504 ((legal-fun-name-p form
)
505 (dump-fdefinition form
))
507 (compiler-error "~S is not a legal function name." form
)))
508 (dump-fdefinition form
))))
510 (defun fopcompile-if (args path for-value-p
)
511 (destructuring-bind (condition then
&optional else
)
513 (let ((else-label (incf *fopcompile-label-counter
*))
514 (end-label (incf *fopcompile-label-counter
*)))
515 (sb!fasl
::dump-integer else-label
*compile-object
*)
516 (fopcompile condition path t
)
517 ;; If condition was false, skip to the ELSE
518 (sb!fasl
::dump-fop
'sb
!fasl
::fop-skip-if-false
*compile-object
*)
519 (fopcompile then path for-value-p
)
520 ;; The THEN branch will have produced a value even if we were
521 ;; currently skipping to the ELSE branch (or over this whole
522 ;; IF). This is done to ensure that the stack effects are
523 ;; balanced properly when dealing with operations that are
524 ;; executed even when skipping over code. But this particular
525 ;; value will be bogus, so we drop it.
527 (sb!fasl
::dump-fop
'sb
!fasl
::fop-drop-if-skipping
*compile-object
*))
528 ;; Now skip to the END
529 (sb!fasl
::dump-integer end-label
*compile-object
*)
530 (sb!fasl
::dump-fop
'sb
!fasl
::fop-skip
*compile-object
*)
531 ;; Start of the ELSE branch
532 (sb!fasl
::dump-integer else-label
*compile-object
*)
533 (sb!fasl
::dump-fop
'sb
!fasl
::fop-maybe-stop-skipping
*compile-object
*)
534 (fopcompile else path for-value-p
)
537 (sb!fasl
::dump-fop
'sb
!fasl
::fop-drop-if-skipping
*compile-object
*))
539 (sb!fasl
::dump-integer end-label
*compile-object
*)
540 (sb!fasl
::dump-fop
'sb
!fasl
::fop-maybe-stop-skipping
*compile-object
*)
541 ;; If we're still skipping, we must've triggered both of the
542 ;; drop-if-skipping fops. To keep the stack balanced, push a
543 ;; dummy value if needed.
545 (sb!fasl
::dump-fop
'sb
!fasl
::fop-push-nil-if-skipping
546 *compile-object
*)))))
548 (defun fopcompile-constant (form for-value-p
)
550 ;; FIXME: Without this binding the dumper chokes on unvalidated
551 ;; structures: CONSTANT-FOPCOMPILABLE-P validates the structure
552 ;; about to be dumped, not its load-form. Compare and contrast
553 ;; with EMIT-MAKE-LOAD-FORM.
554 (let ((sb!fasl
::*dump-only-valid-structures
* nil
))
555 (dump-object form
*compile-object
*))))
557 ;; Return CLASS if CREATION-FORM is `(allocate-instance (find-class ',CLASS))
558 (defun canonical-instance-maker-form-p (creation-form)
559 (let ((arg (and (typep creation-form
560 '(cons (eql allocate-instance
) (cons t null
)))
561 (cadr creation-form
))))
562 (when (and arg
(typep arg
'(cons (eql find-class
) (cons t null
))))
563 (let ((class (cadr arg
)))
564 (when (typep class
'(cons (eql quote
) (cons symbol null
)))
567 ;; If FORM can be implemented by FOP-ALLOCATE-INSTANCE,
568 ;; then fopcompile it and return a table index, otherwise return NIL.
569 (defun fopcompile-allocate-instance (form)
570 (let ((class-name (canonical-instance-maker-form-p form
)))
572 (let ((file *compile-object
*))
573 (dump-object class-name file
)
574 (sb!fasl
::dump-fop
'sb
!fasl
::fop-allocate-instance file
)
575 (let ((index (sb!fasl
::fasl-output-table-free file
)))
576 (setf (sb!fasl
::fasl-output-table-free file
) (1+ index
))
579 ;; If FORM is one that we recognize as coming from MAKE-LOAD-FORM-SAVING-SLOTS,
580 ;; then return 3 values: the instance being affected, a slot name, and a value.
581 ;; Otherwise return three NILs.
582 (defun trivial-load-form-initform-args (form)
583 (multiple-value-bind (args const
)
584 ;; these expressions suck, but here goes...
588 (cons (cons (eql slot-value
)
590 (cons (cons (eql quote
) (cons symbol null
))
592 (cons (cons (eql quote
) (cons t null
)) null
))))
593 (values (cdadr form
) (second (third form
))))
596 (eql slot-makunbound
)
598 (cons (cons (eql quote
) (cons symbol null
)) null
))))
599 ;; FIXME: could define SB-PCL:+SLOT-UNBOUND+ much earlier,
600 ;; and put the symbol in the kernel package or something.
601 (values (cdr form
) 'sb
!pcl
::..slot-unbound..
)))
603 (values (car args
) (cadadr args
) const
)
604 (values nil nil nil
))))
606 ;; If FORMS contains exactly one PROGN with an expected shape,
607 ;; then dump it using fops and return T. Otherwise return NIL.
608 (defun fopcompile-constant-init-forms (forms)
609 ;; It should be possible to extend this to allow FORMS to have
610 ;; any number of forms in the requisite shape.
611 (when (and (singleton-p forms
)
613 '(cons (eql progn
) (satisfies list-length
))))
614 (let ((forms (cdar forms
))
619 (let ((file *compile-object
*))
620 (mapc (lambda (x) (dump-object x file
)) (nreverse values
))
621 (dump-object (cons (length slot-names
) (nreverse slot-names
))
623 (dump-object instance file
)
624 (sb!fasl
::dump-fop
'sb
!fasl
::fop-initialize-instance file
)
626 (multiple-value-bind (obj slot val
)
627 (trivial-load-form-initform-args form
)
630 (typep (setq instance obj
) 'instance
))
632 ;; invoke recursive MAKE-LOAD-FORM stuff as necessary
634 (push slot slot-names
)
635 (push val values
))))))