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 ;;; True if the current contour of FOPCOMPILABLE-P has a LET or LET*
15 ;;; with a non-nil bindings list, false otherwise. The effect of this
17 (defvar *fop-complex-lexenv-p* nil)
19 ;;; SBCL has no proper byte compiler (having ditched the rather
20 ;;; ambitious and slightly flaky byte compiler inherited from CMU CL)
21 ;;; but its FOPs are a sort of byte code which is expressive enough
22 ;;; that we can compile some simple toplevel forms directly to them,
23 ;;; including very common operations like the forms that DEFVARs and
24 ;;; DECLAIMs macroexpand into.
25 (defun fopcompilable-p (form)
26 ;; We'd like to be able to handle
27 ;; -- simple funcalls, nested recursively, e.g.
28 ;; (SET '*PACKAGE* (FIND-PACKAGE "CL-USER"))
29 ;; -- common self-evaluating forms like strings and keywords and
30 ;; fixnums, which are important for terminating
31 ;; the recursion of the simple funcalls above
32 ;; -- quoted lists (which are important for PROCLAIMs, which are
33 ;; common toplevel forms)
34 ;; -- fopcompilable stuff wrapped around non-fopcompilable expressions,
36 ;; (%DEFUN 'FOO (LAMBDA () ...) ...)
37 ;; -- the IF special form, to support things like (DEFVAR *X* 0)
38 ;; expanding into (UNLESS (BOUNDP '*X*) (SET '*X* 0))
40 ;; Special forms which we don't currently handle, but might consider
41 ;; supporting in the future are LOCALLY (with declarations),
42 ;; MACROLET, SYMBOL-MACROLET and THE.
46 (or (and (self-evaluating-p form)
47 (constant-fopcompilable-p form))
49 (multiple-value-bind (macroexpansion macroexpanded-p)
52 (fopcompilable-p macroexpansion)
53 ;; Punt on :ALIEN variables
54 (let ((kind (info :variable :kind form)))
55 (or (eq kind :special)
56 ;; Not really a global, but a variable for
57 ;; which no information exists.
59 (eq kind :constant))))))
61 (ignore-errors (list-length form))
62 (multiple-value-bind (macroexpansion macroexpanded-p)
65 (fopcompilable-p macroexpansion)
66 (destructuring-bind (operator &rest args) form
68 ;; Special operators that we know how to cope with
70 (every #'fopcompilable-p args))
72 (and (= (length args) 1)
73 (constant-fopcompilable-p (car args))))
75 (and (= (length args) 1)
76 ;; #'(LAMBDA ...), #'(NAMED-LAMBDA ...), etc. These
77 ;; are not fopcompileable as such, but we can compile
78 ;; the lambdas with the real compiler, and the rest
79 ;; of the expression with the fop-compiler.
80 (or (and (lambda-form-p (car args))
81 ;; The lambda might be closing over some
82 ;; variable, punt. As a further improvement,
83 ;; we could analyze the lambda body to
84 ;; see whether it really closes over any
85 ;; variables. One place where even simple
86 ;; analysis would be useful are the PCL
87 ;; slot-definition type-check-functions
89 (not *fop-complex-lexenv-p*))
90 ;; #'FOO, #'(SETF FOO), etc
91 (legal-fun-name-p (car args)))))
93 (and (<= 2 (length args) 3)
94 (every #'fopcompilable-p args)))
95 ;; Allow SETQ only on special variables
97 (loop for (name value) on args by #'cddr
98 unless (and (symbolp name)
99 (let ((kind (info :variable :kind name)))
101 (fopcompilable-p value))
104 ;; The real toplevel form processing has already been
105 ;; done, so EVAL-WHEN handling will be easy.
107 (and (>= (length args) 1)
108 (eq (set-difference (car args)
116 (every #'fopcompilable-p (cdr args))))
117 ;; A LET or LET* that introduces only lexical
118 ;; bindings might be fopcompilable, depending on
119 ;; whether something closes over the bindings.
120 ;; (And whether there are declarations in the body,
123 (and (>= (length args) 1)
124 (loop for binding in (car args)
125 for complexp = *fop-complex-lexenv-p* then
126 (if (eq operator 'let)
129 for name = (if (consp binding)
132 for value = (if (consp binding)
135 ;; Only allow binding lexicals,
136 ;; since special bindings can't be
137 ;; easily expressed with fops.
138 always (and (eq (info :variable :kind name)
140 (let ((*fop-complex-lexenv-p*
142 (fopcompilable-p value))))
143 (let ((*fop-complex-lexenv-p*
144 (or *fop-complex-lexenv-p*
145 (not (null (car args))))))
146 (every #'fopcompilable-p (cdr args)))))
148 (every #'fopcompilable-p args))
150 ;; ordinary function calls
151 (and (symbolp operator)
152 ;; If a LET/LOCALLY tries to introduce
153 ;; declarations, we'll detect it here, and
154 ;; disallow fopcompilation. This is safe,
155 ;; since defining a function/macro named
156 ;; DECLARE would violate a package lock.
157 (not (eq operator 'declare))
158 (not (special-operator-p operator))
159 (not (macro-function operator))
160 ;; We can't FOP-FUNCALL with more than 255
161 ;; parameters. (We could theoretically use
162 ;; APPLY, but then we'd need to construct
163 ;; the parameter list for APPLY without
164 ;; calling LIST, which is probably more
165 ;; trouble than it's worth).
166 (<= (length args) 255)
167 (every #'fopcompilable-p args))))))))))
169 (defun lambda-form-p (form)
172 '(lambda named-lambda instance-lambda lambda-with-lexenv))))
174 ;;; Check that a literal form is fopcompilable. It would not for example
175 ;;; when the form contains structures with funny MAKE-LOAD-FORMS.
176 (defun constant-fopcompilable-p (constant)
177 (let ((things-processed nil)
179 (declare (type (or list hash-table) things-processed)
180 (type (integer 0 #.(1+ list-to-hash-table-threshold)) count)
182 (labels ((grovel (value)
183 ;; Unless VALUE is an object which which obviously
184 ;; can't contain other objects
191 (etypecase things-processed
193 (when (member value things-processed :test #'eq)
194 (return-from grovel nil))
195 (push value things-processed)
197 (when (> count list-to-hash-table-threshold)
198 (let ((things things-processed))
199 (setf things-processed
200 (make-hash-table :test 'eq))
201 (dolist (thing things)
202 (setf (gethash thing things-processed) t)))))
204 (when (gethash value things-processed)
205 (return-from grovel nil))
206 (setf (gethash value things-processed) t)))
210 (grovel (cdr value)))
212 (dotimes (i (length value))
213 (grovel (svref value i))))
215 (dotimes (i (length value))
216 (grovel (aref value i))))
218 ;; Even though the (ARRAY T) branch does the exact
219 ;; same thing as this branch we do this separately
220 ;; so that the compiler can use faster versions of
221 ;; array-total-size and row-major-aref.
222 (dotimes (i (array-total-size value))
223 (grovel (row-major-aref value i))))
225 (dotimes (i (array-total-size value))
226 (grovel (row-major-aref value i))))
228 (multiple-value-bind (creation-form init-form)
230 (sb!xc:make-load-form value (make-null-lexenv))
232 (compiler-error condition)))
233 (declare (ignore init-form))
235 (:sb-just-dump-it-normally
236 ;; FIXME: Why is this needed? If the constant
237 ;; is deemed fopcompilable, then when we dump
238 ;; it we bind *dump-only-valid-structures* to
240 (fasl-validate-structure value *compile-object*)
241 (dotimes (i (- (%instance-length value)
242 (layout-n-untagged-slots
243 (%instance-ref value 0))))
244 (grovel (%instance-ref value i))))
247 (return-from constant-fopcompilable-p nil)))))
249 (return-from constant-fopcompilable-p nil))))))
253 ;;; An alist mapping lexical varible names to FOP table handles.
254 (defvar *fop-lexenv* nil)
256 ;;; FOR-VALUE-P is true if the value will be used (i.e., pushed onto
257 ;;; FOP stack), or NIL if any value will be discarded. FOPCOMPILABLE-P
258 ;;; has already ensured that the form can be fopcompiled.
259 (defun fopcompile (form path for-value-p)
260 (cond ((self-evaluating-p form)
261 (fopcompile-constant form for-value-p))
263 (multiple-value-bind (macroexpansion macroexpanded-p)
267 (fopcompile macroexpansion path for-value-p)
268 (let ((kind (info :variable :kind form)))
269 (if (member kind '(:special :constant))
271 (fopcompile `(symbol-value ',form) path for-value-p)
274 (let ((handle (cdr (assoc form *fop-lexenv*))))
276 (sb!fasl::dump-push handle
279 ;; Undefined variable. Signal a warning, and
280 ;; treat it as a special variable reference,
281 ;; like the real compiler does.
282 (note-undefined-reference form :variable)
283 (fopcompile `(symbol-value ',form)
285 for-value-p))))))))))
287 (multiple-value-bind (macroexpansion macroexpanded-p)
290 (fopcompile macroexpansion path for-value-p)
291 (destructuring-bind (operator &rest args) form
293 ;; The QUOTE special operator is worth handling: very
294 ;; easy and very common at toplevel.
296 (fopcompile-constant (second form) for-value-p))
297 ;; A FUNCTION needs to be compiled properly, but doesn't
298 ;; need to prevent the fopcompilation of the whole form.
299 ;; We just compile it, and emit an instruction for pushing
300 ;; the function handle on the FOP stack.
302 (fopcompile-function (second form) path for-value-p))
303 ;; KLUDGE! SB!C:SOURCE-LOCATION calls are normally handled
304 ;; by a compiler-macro. Doing general compiler-macro
305 ;; expansion in the fopcompiler is probably not sensible,
306 ;; so we'll just special-case it.
308 (if (policy *policy* (and (> space 1)
310 (fopcompile-constant nil for-value-p)
311 (fopcompile (let ((*current-path* path))
312 (make-definition-source-location))
316 (fopcompile-if args path for-value-p))
318 (loop for (arg . next) on args
324 (loop for (name value . next) on args by #'cddr
325 do (fopcompile `(set ',name ,value) path
330 (destructuring-bind (situations &body body) args
331 (if (or (member :execute situations)
332 (member 'eval situations))
333 (fopcompile (cons 'progn body) path for-value-p)
334 (fopcompile nil path for-value-p))))
336 (let ((orig-lexenv *fop-lexenv*)
337 (*fop-lexenv* *fop-lexenv*))
338 (loop for binding in (car args)
339 for name = (if (consp binding)
342 for value = (if (consp binding)
345 do (let ((*fop-lexenv*
346 (if (eql operator 'let)
349 (fopcompile value path t))
354 (fopcompile (cons 'progn (cdr args)) path for-value-p)))
355 ;; Otherwise it must be an ordinary funcall.
358 ;; Special hack: there's already a fop for
359 ;; find-undeleted-package-or-lose, so use it.
360 ;; (We could theoretically do the same for
361 ;; other operations, but I don't see any good
362 ;; candidates in a quick read-through of
363 ;; src/code/fop.lisp.)
365 'sb!int:find-undeleted-package-or-lose)
368 (fopcompile (first args) path t)
369 (sb!fasl::dump-fop 'sb!fasl::fop-package
372 (fopcompile-constant operator t)
374 (fopcompile arg path t))
376 (sb!fasl::dump-fop 'sb!fasl::fop-funcall
378 (sb!fasl::dump-fop 'sb!fasl::fop-funcall-for-effect
380 (let ((n-args (length args)))
381 ;; stub: FOP-FUNCALL isn't going to be usable
382 ;; to compile more than this, since its count
383 ;; is a single byte. Maybe we should just punt
384 ;; to the ordinary compiler in that case?
385 (aver (<= n-args 255))
386 (sb!fasl::dump-byte n-args *compile-object*))))))))))
388 (bug "looks unFOPCOMPILEable: ~S" form))))
390 (defun fopcompile-function (form path for-value-p)
391 (flet ((dump-fdefinition (name)
392 (fopcompile `(fdefinition ',name) path for-value-p)))
395 ;; Lambda forms are compiled with the real compiler
396 ((lambda-form-p form)
397 (let* ((handle (%compile form
401 (sb!fasl::dump-push handle *compile-object*))))
402 ;; While function names are translated to a call to FDEFINITION.
403 ((legal-fun-name-p form)
404 (dump-fdefinition form))
406 (compiler-error "~S is not a legal function name." form)))
407 (dump-fdefinition form))))
409 (defun fopcompile-if (args path for-value-p)
410 (destructuring-bind (condition then &optional else)
412 (let ((else-label (incf *fopcompile-label-counter*))
413 (end-label (incf *fopcompile-label-counter*)))
414 (sb!fasl::dump-integer else-label *compile-object*)
415 (fopcompile condition path t)
416 ;; If condition was false, skip to the ELSE
417 (sb!fasl::dump-fop 'sb!fasl::fop-skip-if-false *compile-object*)
418 (fopcompile then path for-value-p)
419 ;; The THEN branch will have produced a value even if we were
420 ;; currently skipping to the ELSE branch (or over this whole
421 ;; IF). This is done to ensure that the stack effects are
422 ;; balanced properly when dealing with operations that are
423 ;; executed even when skipping over code. But this particular
424 ;; value will be bogus, so we drop it.
426 (sb!fasl::dump-fop 'sb!fasl::fop-drop-if-skipping *compile-object*))
427 ;; Now skip to the END
428 (sb!fasl::dump-integer end-label *compile-object*)
429 (sb!fasl::dump-fop 'sb!fasl::fop-skip *compile-object*)
430 ;; Start of the ELSE branch
431 (sb!fasl::dump-integer else-label *compile-object*)
432 (sb!fasl::dump-fop 'sb!fasl::fop-maybe-stop-skipping *compile-object*)
433 (fopcompile else path for-value-p)
436 (sb!fasl::dump-fop 'sb!fasl::fop-drop-if-skipping *compile-object*))
438 (sb!fasl::dump-integer end-label *compile-object*)
439 (sb!fasl::dump-fop 'sb!fasl::fop-maybe-stop-skipping *compile-object*)
440 ;; If we're still skipping, we must've triggered both of the
441 ;; drop-if-skipping fops. To keep the stack balanced, push a
442 ;; dummy value if needed.
444 (sb!fasl::dump-fop 'sb!fasl::fop-push-nil-if-skipping
445 *compile-object*)))))
447 (defun fopcompile-constant (form for-value-p)
449 ;; FIXME: Without this binding the dumper chokes on unvalidated
450 ;; structures: CONSTANT-FOPCOMPILABLE-P validates the structure
451 ;; about to be dumped, not its load-form. Compare and contrast
452 ;; with EMIT-MAKE-LOAD-FORM.
453 (let ((sb!fasl::*dump-only-valid-structures* nil))
454 (dump-object form *compile-object*))))