ab432921b54d0aa63dc54a7e2ade258835f894d5
[sbcl.git] / src / compiler / generic / genesis.lisp
1 ;;;; "cold" core image builder: This is how we create a target Lisp
2 ;;;; system from scratch, by converting from fasl files to an image
3 ;;;; file in the cross-compilation host, without the help of the
4 ;;;; target Lisp system.
5 ;;;;
6 ;;;; As explained by Rob MacLachlan on the CMU CL mailing list Wed, 06
7 ;;;; Jan 1999 11:05:02 -0500, this cold load generator more or less
8 ;;;; fakes up static function linking. I.e. it makes sure that all the
9 ;;;; DEFUN-defined functions in the fasl files it reads are bound to the
10 ;;;; corresponding symbols before execution starts. It doesn't do
11 ;;;; anything to initialize variable values; instead it just arranges
12 ;;;; for !COLD-INIT to be called at cold load time. !COLD-INIT is
13 ;;;; responsible for explicitly initializing anything which has to be
14 ;;;; initialized early before it transfers control to the ordinary
15 ;;;; top-level forms.
16 ;;;;
17 ;;;; (In CMU CL, and in SBCL as of 0.6.9 anyway, functions not defined
18 ;;;; by DEFUN aren't set up specially by GENESIS. In particular,
19 ;;;; structure slot accessors are not set up. Slot accessors are
20 ;;;; available at cold init time because they're usually compiled
21 ;;;; inline. They're not available as out-of-line functions until the
22 ;;;; toplevel forms installing them have run.)
23
24 ;;;; This software is part of the SBCL system. See the README file for
25 ;;;; more information.
26 ;;;;
27 ;;;; This software is derived from the CMU CL system, which was
28 ;;;; written at Carnegie Mellon University and released into the
29 ;;;; public domain. The software is in the public domain and is
30 ;;;; provided with absolutely no warranty. See the COPYING and CREDITS
31 ;;;; files for more information.
32
33 (in-package "SB!IMPL")
34
35 ;;; a magic number used to identify our core files
36 (defconstant core-magic
37   (logior (ash (char-code #\S) 24)
38           (ash (char-code #\B) 16)
39           (ash (char-code #\C) 8)
40           (char-code #\L)))
41
42 ;;; the current version of SBCL core files
43 ;;;
44 ;;; FIXME: This is left over from CMU CL, and not well thought out.
45 ;;; It's good to make sure that the runtime doesn't try to run core
46 ;;; files from the wrong version, but a single number is not the ideal
47 ;;; way to do this in high level data like this (as opposed to e.g. in
48 ;;; IP packets), and in fact the CMU CL version number never ended up
49 ;;; being incremented past 0. A better approach might be to use a
50 ;;; string which is set from CVS data.
51 ;;;
52 ;;; 0: inherited from CMU CL
53 ;;; 1: rearranged static symbols for sbcl-0.6.8
54 ;;; 2: eliminated non-ANSI %DEFCONSTANT/%%DEFCONSTANT support,
55 ;;;    deleted a slot from DEBUG-SOURCE structure
56 (defconstant sbcl-core-version-integer 2)
57
58 (defun round-up (number size)
59   #!+sb-doc
60   "Round NUMBER up to be an integral multiple of SIZE."
61   (* size (ceiling number size)))
62 \f
63 ;;;; representation of spaces in the core
64
65 (defvar *dynamic*)
66 (defconstant dynamic-space-id 1)
67
68 (defvar *static*)
69 (defconstant static-space-id 2)
70
71 (defvar *read-only*)
72 (defconstant read-only-space-id 3)
73
74 (defconstant descriptor-low-bits 16
75   "the number of bits in the low half of the descriptor")
76 (defconstant target-space-alignment (ash 1 descriptor-low-bits)
77   "the alignment requirement for spaces in the target.
78   Must be at least (ASH 1 DESCRIPTOR-LOW-BITS)")
79
80 ;;; a GENESIS-time representation of a memory space (e.g. read-only space,
81 ;;; dynamic space, or static space)
82 (defstruct (gspace (:constructor %make-gspace)
83                    (:copier nil))
84   ;; name and identifier for this GSPACE
85   (name (required-argument) :type symbol :read-only t)
86   (identifier (required-argument) :type fixnum :read-only t)
87   ;; the word address where the data will be loaded
88   (word-address (required-argument) :type unsigned-byte :read-only t)
89   ;; the data themselves. (Note that in CMU CL this was a pair
90   ;; of fields SAP and WORDS-ALLOCATED, but that wasn't very portable.)
91   (bytes (make-array target-space-alignment :element-type '(unsigned-byte 8))
92          :type (simple-array (unsigned-byte 8) 1))
93   ;; the index of the next unwritten word (i.e. chunk of
94   ;; SB!VM:WORD-BYTES bytes) in BYTES, or equivalently the number of
95   ;; words actually written in BYTES. In order to convert to an actual
96   ;; index into BYTES, thus must be multiplied by SB!VM:WORD-BYTES.
97   (free-word-index 0))
98
99 (defun gspace-byte-address (gspace)
100   (ash (gspace-word-address gspace) sb!vm:word-shift))
101
102 (def!method print-object ((gspace gspace) stream)
103   (print-unreadable-object (gspace stream :type t)
104     (format stream "~S" (gspace-name gspace))))
105
106 (defun make-gspace (name identifier byte-address)
107   (unless (zerop (rem byte-address target-space-alignment))
108     (error "The byte address #X~X is not aligned on a #X~X-byte boundary."
109            byte-address
110            target-space-alignment))
111   (%make-gspace :name name
112                 :identifier identifier
113                 :word-address (ash byte-address (- sb!vm:word-shift))))
114
115 ;;; KLUDGE: Doing it this way seems to partly replicate the
116 ;;; functionality of Common Lisp adjustable arrays. Is there any way
117 ;;; to do this stuff in one line of code by using standard Common Lisp
118 ;;; stuff? -- WHN 19990816
119 (defun expand-gspace-bytes (gspace)
120   (let* ((old-bytes (gspace-bytes gspace))
121          (old-length (length old-bytes))
122          (new-length (* 2 old-length))
123          (new-bytes (make-array new-length :element-type '(unsigned-byte 8))))
124     (replace new-bytes old-bytes :end1 old-length)
125     (setf (gspace-bytes gspace)
126           new-bytes))
127   (values))
128 \f
129 ;;;; representation of descriptors
130
131 (defstruct (descriptor
132             (:constructor make-descriptor
133                           (high low &optional gspace word-offset))
134             (:copier nil))
135   ;; the GSPACE that this descriptor is allocated in, or NIL if not set yet.
136   (gspace nil :type (or gspace null))
137   ;; the offset in words from the start of GSPACE, or NIL if not set yet
138   (word-offset nil :type (or (unsigned-byte #.sb!vm:word-bits) null))
139   ;; the high and low halves of the descriptor KLUDGE: Judging from
140   ;; the comments in genesis.lisp of the CMU CL old-rt compiler, this
141   ;; split dates back from a very early version of genesis where
142   ;; 32-bit integers were represented as conses of two 16-bit
143   ;; integers. In any system with nice (UNSIGNED-BYTE 32) structure
144   ;; slots, like CMU CL >= 17 or any version of SBCL, there seems to
145   ;; be no reason to persist in this. -- WHN 19990917
146   high low)
147 (def!method print-object ((des descriptor) stream)
148   (let ((lowtag (descriptor-lowtag des)))
149     (print-unreadable-object (des stream :type t)
150       (cond ((or (= lowtag sb!vm:even-fixnum-type)
151                  (= lowtag sb!vm:odd-fixnum-type))
152              (let ((unsigned (logior (ash (descriptor-high des)
153                                           (1+ (- descriptor-low-bits
154                                                  sb!vm:lowtag-bits)))
155                                      (ash (descriptor-low des)
156                                           (- 1 sb!vm:lowtag-bits)))))
157                (format stream
158                        "for fixnum: ~D"
159                        (if (> unsigned #x1FFFFFFF)
160                            (- unsigned #x40000000)
161                            unsigned))))
162             ((or (= lowtag sb!vm:other-immediate-0-type)
163                  (= lowtag sb!vm:other-immediate-1-type))
164              (format stream
165                      "for other immediate: #X~X, type #b~8,'0B"
166                      (ash (descriptor-bits des) (- sb!vm:type-bits))
167                      (logand (descriptor-low des) sb!vm:type-mask)))
168             (t
169              (format stream
170                      "for pointer: #X~X, lowtag #b~3,'0B, ~A"
171                      (logior (ash (descriptor-high des) descriptor-low-bits)
172                              (logandc2 (descriptor-low des) sb!vm:lowtag-mask))
173                      lowtag
174                      (let ((gspace (descriptor-gspace des)))
175                        (if gspace
176                            (gspace-name gspace)
177                            "unknown"))))))))
178
179 (defun allocate-descriptor (gspace length lowtag)
180   #!+sb-doc
181   "Return a descriptor for a block of LENGTH bytes out of GSPACE. The free
182   word index is boosted as necessary, and if additional memory is needed, we
183   grow the GSPACE. The descriptor returned is a pointer of type LOWTAG."
184   (let* ((bytes (round-up length (ash 1 sb!vm:lowtag-bits)))
185          (old-free-word-index (gspace-free-word-index gspace))
186          (new-free-word-index (+ old-free-word-index
187                                  (ash bytes (- sb!vm:word-shift)))))
188     ;; Grow GSPACE as necessary until it's big enough to handle
189     ;; NEW-FREE-WORD-INDEX.
190     (do ()
191         ((>= (length (gspace-bytes gspace))
192              (* new-free-word-index sb!vm:word-bytes)))
193       (expand-gspace-bytes gspace))
194     ;; Now that GSPACE is big enough, we can meaningfully grab a chunk of it.
195     (setf (gspace-free-word-index gspace) new-free-word-index)
196     (let ((ptr (+ (gspace-word-address gspace) old-free-word-index)))
197       (make-descriptor (ash ptr (- sb!vm:word-shift descriptor-low-bits))
198                        (logior (ash (logand ptr
199                                             (1- (ash 1
200                                                      (- descriptor-low-bits
201                                                         sb!vm:word-shift))))
202                                     sb!vm:word-shift)
203                                lowtag)
204                        gspace
205                        old-free-word-index))))
206
207 (defun descriptor-lowtag (des)
208   #!+sb-doc
209   "the lowtag bits for DES"
210   (logand (descriptor-low des) sb!vm:lowtag-mask))
211
212 (defun descriptor-bits (des)
213   (logior (ash (descriptor-high des) descriptor-low-bits)
214           (descriptor-low des)))
215
216 (defun descriptor-fixnum (des)
217   (let ((bits (descriptor-bits des)))
218     (if (logbitp (1- sb!vm:word-bits) bits)
219       ;; KLUDGE: The (- SB!VM:WORD-BITS 2) term here looks right to
220       ;; me, and it works, but in CMU CL it was (1- SB!VM:WORD-BITS),
221       ;; and although that doesn't make sense for me, or work for me,
222       ;; it's hard to see how it could have been wrong, since CMU CL
223       ;; genesis worked. It would be nice to understand how this came
224       ;; to be.. -- WHN 19990901
225       (logior (ash bits -2) (ash -1 (- sb!vm:word-bits 2)))
226       (ash bits -2))))
227
228 ;;; common idioms
229 (defun descriptor-bytes (des)
230   (gspace-bytes (descriptor-intuit-gspace des)))
231 (defun descriptor-byte-offset (des)
232   (ash (descriptor-word-offset des) sb!vm:word-shift))
233
234 ;;; If DESCRIPTOR-GSPACE is already set, just return that. Otherwise,
235 ;;; figure out a GSPACE which corresponds to DES, set it into
236 ;;; (DESCRIPTOR-GSPACE DES), set a consistent value into
237 ;;; (DESCRIPTOR-WORD-OFFSET DES), and return the GSPACE.
238 (declaim (ftype (function (descriptor) gspace) descriptor-intuit-gspace))
239 (defun descriptor-intuit-gspace (des)
240   (if (descriptor-gspace des)
241     (descriptor-gspace des)
242     ;; KLUDGE: It's not completely clear to me what's going on here;
243     ;; this is a literal translation from of some rather mysterious
244     ;; code from CMU CL's DESCRIPTOR-SAP function. Some explanation
245     ;; would be nice. -- WHN 19990817
246     (let ((lowtag (descriptor-lowtag des))
247           (high (descriptor-high des))
248           (low (descriptor-low des)))
249       (if (or (eql lowtag sb!vm:function-pointer-type)
250               (eql lowtag sb!vm:instance-pointer-type)
251               (eql lowtag sb!vm:list-pointer-type)
252               (eql lowtag sb!vm:other-pointer-type))
253         (dolist (gspace (list *dynamic* *static* *read-only*)
254                         (error "couldn't find a GSPACE for ~S" des))
255           ;; This code relies on the fact that GSPACEs are aligned such that
256           ;; the descriptor-low-bits low bits are zero.
257           (when (and (>= high (ash (gspace-word-address gspace)
258                                    (- sb!vm:word-shift descriptor-low-bits)))
259                      (<= high (ash (+ (gspace-word-address gspace)
260                                       (gspace-free-word-index gspace))
261                                    (- sb!vm:word-shift descriptor-low-bits))))
262             (setf (descriptor-gspace des) gspace)
263             (setf (descriptor-word-offset des)
264                   (+ (ash (- high (ash (gspace-word-address gspace)
265                                        (- sb!vm:word-shift
266                                           descriptor-low-bits)))
267                           (- descriptor-low-bits sb!vm:word-shift))
268                      (ash (logandc2 low sb!vm:lowtag-mask)
269                           (- sb!vm:word-shift))))
270             (return gspace)))
271         (error "don't even know how to look for a GSPACE for ~S" des)))))
272
273 (defun make-random-descriptor (value)
274   (make-descriptor (logand (ash value (- descriptor-low-bits))
275                            (1- (ash 1
276                                     (- sb!vm:word-bits descriptor-low-bits))))
277                    (logand value (1- (ash 1 descriptor-low-bits)))))
278
279 (defun make-fixnum-descriptor (num)
280   (when (>= (integer-length num)
281             (1+ (- sb!vm:word-bits sb!vm:lowtag-bits)))
282     (error "~D is too big for a fixnum." num))
283   (make-random-descriptor (ash num (1- sb!vm:lowtag-bits))))
284
285 (defun make-other-immediate-descriptor (data type)
286   (make-descriptor (ash data (- sb!vm:type-bits descriptor-low-bits))
287                    (logior (logand (ash data (- descriptor-low-bits
288                                                 sb!vm:type-bits))
289                                    (1- (ash 1 descriptor-low-bits)))
290                            type)))
291
292 (defun make-character-descriptor (data)
293   (make-other-immediate-descriptor data sb!vm:base-char-type))
294
295 (defun descriptor-beyond (des offset type)
296   (let* ((low (logior (+ (logandc2 (descriptor-low des) sb!vm:lowtag-mask)
297                          offset)
298                       type))
299          (high (+ (descriptor-high des)
300                   (ash low (- descriptor-low-bits)))))
301     (make-descriptor high (logand low (1- (ash 1 descriptor-low-bits))))))
302 \f
303 ;;;; miscellaneous variables and other noise
304
305 ;;; a numeric value to be returned for undefined foreign symbols, or NIL if
306 ;;; undefined foreign symbols are to be treated as an error.
307 ;;; (In the first pass of GENESIS, needed to create a header file before
308 ;;; the C runtime can be built, various foreign symbols will necessarily
309 ;;; be undefined, but we don't need actual values for them anyway, and
310 ;;; we can just use 0 or some other placeholder. In the second pass of
311 ;;; GENESIS, all foreign symbols should be defined, so any undefined
312 ;;; foreign symbol is a problem.)
313 ;;;
314 ;;; KLUDGE: It would probably be cleaner to rewrite GENESIS so that it
315 ;;; never tries to look up foreign symbols in the first place unless
316 ;;; it's actually creating a core file (as in the second pass) instead
317 ;;; of using this hack to allow it to go through the motions without
318 ;;; causing an error. -- WHN 20000825
319 (defvar *foreign-symbol-placeholder-value*)
320
321 ;;; a handle on the trap object
322 (defvar *unbound-marker*)
323 ;; was:  (make-other-immediate-descriptor 0 sb!vm:unbound-marker-type)
324
325 ;;; a handle on the NIL object
326 (defvar *nil-descriptor*)
327
328 ;;; the head of a list of TOPLEVEL-THINGs describing stuff to be done
329 ;;; when the target Lisp starts up
330 ;;;
331 ;;; Each TOPLEVEL-THING can be a function to be executed or a fixup or
332 ;;; loadtime value, represented by (CONS KEYWORD ..). The FILENAME
333 ;;; tells which fasl file each list element came from, for debugging
334 ;;; purposes.
335 (defvar *current-reversed-cold-toplevels*)
336
337 ;;; the name of the object file currently being cold loaded (as a string, not a
338 ;;; pathname), or NIL if we're not currently cold loading any object file
339 (defvar *cold-load-filename* nil)
340 (declaim (type (or string null) *cold-load-filename*))
341
342 ;;; This is vestigial support for the CMU CL byte-swapping code. CMU
343 ;;; CL code tested for whether it needed to swap bytes in GENESIS by
344 ;;; comparing the byte order of *BACKEND* to the byte order of
345 ;;; *NATIVE-BACKEND*, a concept which doesn't exist in SBCL. Instead,
346 ;;; in SBCL byte order swapping would need to be explicitly requested
347 ;;; with a keyword argument to GENESIS.
348 ;;;
349 ;;; I'm not sure whether this is a problem or not, and I don't have a
350 ;;; machine with different byte order to test to find out for sure.
351 ;;; The version of the system which is fed to the cross-compiler is
352 ;;; now written in a subset of Common Lisp which doesn't require
353 ;;; dumping a lot of things in such a way that machine byte order
354 ;;; matters. (Mostly this is a matter of not using any specialized
355 ;;; array type unless there's portable, high-level code to dump it.)
356 ;;; If it *is* a problem, and you're trying to resurrect this code,
357 ;;; please test particularly carefully, since I haven't had a chance
358 ;;; to test the byte-swapping code at all. -- WHN 19990816
359 ;;;
360 ;;; When this variable is non-NIL, byte-swapping is enabled wherever
361 ;;; classic GENESIS would have done it. I.e. the value of this variable
362 ;;; is the logical complement of
363 ;;;    (EQ (SB!C:BACKEND-BYTE-ORDER SB!C:*NATIVE-BACKEND*)
364 ;;;     (SB!C:BACKEND-BYTE-ORDER SB!C:*BACKEND*))
365 ;;; from CMU CL.
366 (defvar *genesis-byte-order-swap-p*)
367 \f
368 ;;;; miscellaneous stuff to read and write the core memory
369
370 ;;; FIXME: should be DEFINE-MODIFY-MACRO
371 (defmacro cold-push (thing list)
372   #!+sb-doc
373   "Push THING onto the given cold-load LIST."
374   `(setq ,list (cold-cons ,thing ,list)))
375
376 (defun maybe-byte-swap (word)
377   (declare (type (unsigned-byte 32) word))
378   (assert (= sb!vm:word-bits 32))
379   (assert (= sb!vm:byte-bits 8))
380   (if (not *genesis-byte-order-swap-p*)
381       word
382       (logior (ash (ldb (byte 8 0) word) 24)
383               (ash (ldb (byte 8 8) word) 16)
384               (ash (ldb (byte 8 16) word) 8)
385               (ldb (byte 8 24) word))))
386
387 (defun maybe-byte-swap-short (short)
388   (declare (type (unsigned-byte 16) short))
389   (assert (= sb!vm:word-bits 32))
390   (assert (= sb!vm:byte-bits 8))
391   (if (not *genesis-byte-order-swap-p*)
392       short
393       (logior (ash (ldb (byte 8 0) short) 8)
394               (ldb (byte 8 8) short))))
395
396 ;;; like SAP-REF-32, except that instead of a SAP we use a byte vector
397 (defun byte-vector-ref-32 (byte-vector byte-index)
398   (assert (= sb!vm:word-bits 32))
399   (assert (= sb!vm:byte-bits 8))
400   (ecase sb!c:*backend-byte-order*
401     (:little-endian
402      (logior (ash (aref byte-vector (+ byte-index 0)) 0)
403              (ash (aref byte-vector (+ byte-index 1)) 8)
404              (ash (aref byte-vector (+ byte-index 2)) 16)
405              (ash (aref byte-vector (+ byte-index 3)) 24)))
406     (:big-endian
407      (error "stub: no big-endian ports of SBCL (yet?)"))))
408 (defun (setf byte-vector-ref-32) (new-value byte-vector byte-index)
409   (assert (= sb!vm:word-bits 32))
410   (assert (= sb!vm:byte-bits 8))
411   (ecase sb!c:*backend-byte-order*
412     (:little-endian
413      (setf (aref byte-vector (+ byte-index 0)) (ldb (byte 8 0) new-value)
414            (aref byte-vector (+ byte-index 1)) (ldb (byte 8 8) new-value)
415            (aref byte-vector (+ byte-index 2)) (ldb (byte 8 16) new-value)
416            (aref byte-vector (+ byte-index 3)) (ldb (byte 8 24) new-value)))
417     (:big-endian
418      (error "stub: no big-endian ports of SBCL (yet?)")))
419   new-value)
420
421 (declaim (ftype (function (descriptor sb!vm:word) descriptor) read-wordindexed))
422 (defun read-wordindexed (address index)
423   #!+sb-doc
424   "Return the value which is displaced by INDEX words from ADDRESS."
425   (let* ((gspace (descriptor-intuit-gspace address))
426          (bytes (gspace-bytes gspace))
427          (byte-index (ash (+ index (descriptor-word-offset address))
428                           sb!vm:word-shift))
429          ;; KLUDGE: Do we really need to do byte swap here? It seems
430          ;; as though we shouldn't.. (This attempts to be a literal
431          ;; translation of CMU CL code, and I don't have a big-endian
432          ;; machine to test it.) -- WHN 19990817
433          (value (maybe-byte-swap (byte-vector-ref-32 bytes byte-index))))
434     (make-random-descriptor value)))
435
436 (declaim (ftype (function (descriptor) descriptor) read-memory))
437 (defun read-memory (address)
438   #!+sb-doc
439   "Return the value at ADDRESS."
440   (read-wordindexed address 0))
441
442 ;;; (Note: In CMU CL, this function expected a SAP-typed ADDRESS
443 ;;; value, instead of the SAPINT we use here.)
444 (declaim (ftype (function (sb!vm:word descriptor) (values)) note-load-time-value-reference))
445 (defun note-load-time-value-reference (address marker)
446   (cold-push (cold-cons
447               (cold-intern :load-time-value-fixup)
448               (cold-cons (sapint-to-core address)
449                          (cold-cons
450                           (number-to-core (descriptor-word-offset marker))
451                           *nil-descriptor*)))
452              *current-reversed-cold-toplevels*)
453   (values))
454
455 (declaim (ftype (function (descriptor sb!vm:word descriptor)) write-wordindexed))
456 (defun write-wordindexed (address index value)
457   #!+sb-doc
458   "Write VALUE displaced INDEX words from ADDRESS."
459   ;; KLUDGE: There is an algorithm (used in DESCRIPTOR-INTUIT-GSPACE)
460   ;; for calculating the value of the GSPACE slot from scratch. It
461   ;; doesn't work for all values, only some of them, but mightn't it
462   ;; be reasonable to see whether it works on VALUE before we give up
463   ;; because (DESCRIPTOR-GSPACE VALUE) isn't set? (Or failing that,
464   ;; perhaps write a comment somewhere explaining why it's not a good
465   ;; idea?) -- WHN 19990817
466   (if (and (null (descriptor-gspace value))
467            (not (null (descriptor-word-offset value))))
468     (note-load-time-value-reference (+ (logandc2 (descriptor-bits address)
469                                                  sb!vm:lowtag-mask)
470                                        (ash index sb!vm:word-shift))
471                                     value)
472     ;; Note: There's a MAYBE-BYTE-SWAP in here in CMU CL, which I
473     ;; think is unnecessary now that we're doing the write
474     ;; byte-by-byte at high level. (I can't test this, though..) --
475     ;; WHN 19990817
476     (let* ((bytes (gspace-bytes (descriptor-intuit-gspace address)))
477            (byte-index (ash (+ index (descriptor-word-offset address))
478                                sb!vm:word-shift)))
479       (setf (byte-vector-ref-32 bytes byte-index)
480             (maybe-byte-swap (descriptor-bits value))))))
481
482 (declaim (ftype (function (descriptor descriptor)) write-memory))
483 (defun write-memory (address value)
484   #!+sb-doc
485   "Write VALUE (a DESCRIPTOR) at ADDRESS (also a DESCRIPTOR)."
486   (write-wordindexed address 0 value))
487 \f
488 ;;;; allocating images of primitive objects in the cold core
489
490 ;;; There are three kinds of blocks of memory in the type system:
491 ;;; * Boxed objects (cons cells, structures, etc): These objects have no
492 ;;;   header as all slots are descriptors.
493 ;;; * Unboxed objects (bignums): There is a single header word that contains
494 ;;;   the length.
495 ;;; * Vector objects: There is a header word with the type, then a word for
496 ;;;   the length, then the data.
497 (defun allocate-boxed-object (gspace length lowtag)
498   #!+sb-doc
499   "Allocate LENGTH words in GSPACE and return a new descriptor of type LOWTAG
500   pointing to them."
501   (allocate-descriptor gspace (ash length sb!vm:word-shift) lowtag))
502 (defun allocate-unboxed-object (gspace element-bits length type)
503   #!+sb-doc
504   "Allocate LENGTH units of ELEMENT-BITS bits plus a header word in GSPACE and
505   return an ``other-pointer'' descriptor to them. Initialize the header word
506   with the resultant length and TYPE."
507   (let* ((bytes (/ (* element-bits length) sb!vm:byte-bits))
508          (des (allocate-descriptor gspace
509                                    (+ bytes sb!vm:word-bytes)
510                                    sb!vm:other-pointer-type)))
511     (write-memory des
512                   (make-other-immediate-descriptor (ash bytes
513                                                         (- sb!vm:word-shift))
514                                                    type))
515     des))
516 (defun allocate-vector-object (gspace element-bits length type)
517   #!+sb-doc
518   "Allocate LENGTH units of ELEMENT-BITS size plus a header plus a length slot in
519   GSPACE and return an ``other-pointer'' descriptor to them. Initialize the
520   header word with TYPE and the length slot with LENGTH."
521   ;; FIXME: Here and in ALLOCATE-UNBOXED-OBJECT, BYTES is calculated using
522   ;; #'/ instead of #'CEILING, which seems wrong.
523   (let* ((bytes (/ (* element-bits length) sb!vm:byte-bits))
524          (des (allocate-descriptor gspace (+ bytes (* 2 sb!vm:word-bytes))
525                                           sb!vm:other-pointer-type)))
526     (write-memory des (make-other-immediate-descriptor 0 type))
527     (write-wordindexed des
528                        sb!vm:vector-length-slot
529                        (make-fixnum-descriptor length))
530     des))
531 \f
532 ;;;; copying simple objects into the cold core
533
534 (defun string-to-core (string &optional (gspace *dynamic*))
535   #!+sb-doc
536   "Copy string into the cold core and return a descriptor to it."
537   ;; (Remember that the system convention for storage of strings leaves an
538   ;; extra null byte at the end to aid in call-out to C.)
539   (let* ((length (length string))
540          (des (allocate-vector-object gspace
541                                       sb!vm:byte-bits
542                                       (1+ length)
543                                       sb!vm:simple-string-type))
544          (bytes (gspace-bytes gspace))
545          (offset (+ (* sb!vm:vector-data-offset sb!vm:word-bytes)
546                     (descriptor-byte-offset des))))
547     (write-wordindexed des
548                        sb!vm:vector-length-slot
549                        (make-fixnum-descriptor length))
550     (dotimes (i length)
551       (setf (aref bytes (+ offset i))
552             ;; KLUDGE: There's no guarantee that the character
553             ;; encoding here will be the same as the character
554             ;; encoding on the target machine, so using CHAR-CODE as
555             ;; we do, or a bitwise copy as CMU CL code did, is sleazy.
556             ;; (To make this more portable, perhaps we could use
557             ;; indices into the sequence which is used to test whether
558             ;; a character is a STANDARD-CHAR?) -- WHN 19990817
559             (char-code (aref string i))))
560     (setf (aref bytes (+ offset length))
561           0) ; null string-termination character for C
562     des))
563
564 (defun bignum-to-core (n)
565   #!+sb-doc
566   "Copy a bignum to the cold core."
567   (let* ((words (ceiling (1+ (integer-length n)) sb!vm:word-bits))
568          (handle (allocate-unboxed-object *dynamic*
569                                           sb!vm:word-bits
570                                           words
571                                           sb!vm:bignum-type)))
572     (declare (fixnum words))
573     (do ((index 1 (1+ index))
574          (remainder n (ash remainder (- sb!vm:word-bits))))
575         ((> index words)
576          (unless (zerop (integer-length remainder))
577            ;; FIXME: Shouldn't this be a fatal error?
578            (warn "~D words of ~D were written, but ~D bits were left over."
579                  words n remainder)))
580       (let ((word (ldb (byte sb!vm:word-bits 0) remainder)))
581         (write-wordindexed handle index
582                            (make-descriptor (ash word (- descriptor-low-bits))
583                                             (ldb (byte descriptor-low-bits 0)
584                                                  word)))))
585     handle))
586
587 (defun number-pair-to-core (first second type)
588   #!+sb-doc
589   "Makes a number pair of TYPE (ratio or complex) and fills it in."
590   (let ((des (allocate-unboxed-object *dynamic* sb!vm:word-bits 2 type)))
591     (write-wordindexed des 1 first)
592     (write-wordindexed des 2 second)
593     des))
594
595 (defun float-to-core (x)
596   (etypecase x
597     (single-float
598      (let ((des (allocate-unboxed-object *dynamic*
599                                          sb!vm:word-bits
600                                          (1- sb!vm:single-float-size)
601                                          sb!vm:single-float-type)))
602        (write-wordindexed des
603                           sb!vm:single-float-value-slot
604                           (make-random-descriptor (single-float-bits x)))
605        des))
606     (double-float
607      (let ((des (allocate-unboxed-object *dynamic*
608                                          sb!vm:word-bits
609                                          (1- sb!vm:double-float-size)
610                                          sb!vm:double-float-type))
611            (high-bits (make-random-descriptor (double-float-high-bits x)))
612            (low-bits (make-random-descriptor (double-float-low-bits x))))
613        (ecase sb!c:*backend-byte-order*
614          (:little-endian
615           (write-wordindexed des sb!vm:double-float-value-slot low-bits)
616           (write-wordindexed des (1+ sb!vm:double-float-value-slot) high-bits))
617          (:big-endian
618           (write-wordindexed des sb!vm:double-float-value-slot high-bits)
619           (write-wordindexed des (1+ sb!vm:double-float-value-slot) low-bits)))
620        des))
621     #!+(and long-float x86)
622     (long-float
623      (let ((des (allocate-unboxed-object *dynamic*
624                                          sb!vm:word-bits
625                                          (1- sb!vm:long-float-size)
626                                          sb!vm:long-float-type))
627            (exp-bits (make-random-descriptor (long-float-exp-bits x)))
628            (high-bits (make-random-descriptor (long-float-high-bits x)))
629            (low-bits (make-random-descriptor (long-float-low-bits x))))
630        (ecase sb!c:*backend-byte-order*
631          (:little-endian
632           (write-wordindexed des sb!vm:long-float-value-slot low-bits)
633           (write-wordindexed des (1+ sb!vm:long-float-value-slot) high-bits)
634           (write-wordindexed des (+ 2 sb!vm:long-float-value-slot) exp-bits))
635          (:big-endian
636           (error "LONG-FLOAT is not supported for big-endian byte order.")))
637        des))))
638
639 (defun complex-single-float-to-core (num)
640   (declare (type (complex single-float) num))
641   (let ((des (allocate-unboxed-object *dynamic* sb!vm:word-bits
642                                       (1- sb!vm:complex-single-float-size)
643                                       sb!vm:complex-single-float-type)))
644     (write-wordindexed des sb!vm:complex-single-float-real-slot
645                    (make-random-descriptor (single-float-bits (realpart num))))
646     (write-wordindexed des sb!vm:complex-single-float-imag-slot
647                    (make-random-descriptor (single-float-bits (imagpart num))))
648     des))
649
650 (defun complex-double-float-to-core (num)
651   (declare (type (complex double-float) num))
652   (let ((des (allocate-unboxed-object *dynamic* sb!vm:word-bits
653                                       (1- sb!vm:complex-double-float-size)
654                                       sb!vm:complex-double-float-type)))
655     (let* ((real (realpart num))
656            (high-bits (make-random-descriptor (double-float-high-bits real)))
657            (low-bits (make-random-descriptor (double-float-low-bits real))))
658       (ecase sb!c:*backend-byte-order*
659         (:little-endian
660          (write-wordindexed des sb!vm:complex-double-float-real-slot low-bits)
661          (write-wordindexed des (1+ sb!vm:complex-double-float-real-slot) high-bits))
662         (:big-endian
663          (write-wordindexed des sb!vm:complex-double-float-real-slot high-bits)
664          (write-wordindexed des (1+ sb!vm:complex-double-float-real-slot) low-bits))))
665     (let* ((imag (imagpart num))
666            (high-bits (make-random-descriptor (double-float-high-bits imag)))
667            (low-bits (make-random-descriptor (double-float-low-bits imag))))
668       (ecase sb!c:*backend-byte-order*
669         (:little-endian
670          (write-wordindexed des sb!vm:complex-double-float-imag-slot low-bits)
671          (write-wordindexed des (1+ sb!vm:complex-double-float-imag-slot) high-bits))
672         (:big-endian
673          (write-wordindexed des sb!vm:complex-double-float-imag-slot high-bits)
674          (write-wordindexed des (1+ sb!vm:complex-double-float-imag-slot) low-bits))))
675     des))
676
677 (defun number-to-core (number)
678   #!+sb-doc
679   "Copy the given number to the core, or flame out if we can't deal with it."
680   (typecase number
681     (integer (if (< (integer-length number) 30)
682                  (make-fixnum-descriptor number)
683                  (bignum-to-core number)))
684     (ratio (number-pair-to-core (number-to-core (numerator number))
685                                 (number-to-core (denominator number))
686                                 sb!vm:ratio-type))
687     ((complex single-float) (complex-single-float-to-core number))
688     ((complex double-float) (complex-double-float-to-core number))
689     #!+long-float
690     ((complex long-float)
691      (error "~S isn't a cold-loadable number at all!" number))
692     (complex (number-pair-to-core (number-to-core (realpart number))
693                                   (number-to-core (imagpart number))
694                                   sb!vm:complex-type))
695     (float (float-to-core number))
696     (t (error "~S isn't a cold-loadable number at all!" number))))
697
698 (declaim (ftype (function (sb!vm:word) descriptor) sap-to-core))
699 (defun sapint-to-core (sapint)
700   (let ((des (allocate-unboxed-object *dynamic*
701                                       sb!vm:word-bits
702                                       (1- sb!vm:sap-size)
703                                       sb!vm:sap-type)))
704     (write-wordindexed des
705                        sb!vm:sap-pointer-slot
706                        (make-random-descriptor sapint))
707     des))
708
709 ;;; Allocate a cons cell in GSPACE and fill it in with CAR and CDR.
710 (defun cold-cons (car cdr &optional (gspace *dynamic*))
711   (let ((dest (allocate-boxed-object gspace 2 sb!vm:list-pointer-type)))
712     (write-memory dest car)
713     (write-wordindexed dest 1 cdr)
714     dest))
715
716 ;;; Make a simple-vector that holds the specified OBJECTS, and return its
717 ;;; descriptor.
718 (defun vector-in-core (&rest objects)
719   (let* ((size (length objects))
720          (result (allocate-vector-object *dynamic* sb!vm:word-bits size
721                                          sb!vm:simple-vector-type)))
722     (dotimes (index size)
723       (write-wordindexed result (+ index sb!vm:vector-data-offset)
724                          (pop objects)))
725     result))
726 \f
727 ;;;; symbol magic
728
729 ;;; FIXME: This should be a keyword argument of ALLOCATE-SYMBOL.
730 (defvar *cold-symbol-allocation-gspace* nil)
731
732 ;;; Allocate (and initialize) a symbol.
733 (defun allocate-symbol (name)
734   (declare (simple-string name))
735   (let ((symbol (allocate-unboxed-object (or *cold-symbol-allocation-gspace*
736                                              *dynamic*)
737                                          sb!vm:word-bits
738                                          (1- sb!vm:symbol-size)
739                                          sb!vm:symbol-header-type)))
740     (write-wordindexed symbol sb!vm:symbol-value-slot *unbound-marker*)
741     #!+x86
742     (write-wordindexed symbol
743                        sb!vm:symbol-hash-slot
744                        (make-fixnum-descriptor
745                         (1+ (random sb!vm:*target-most-positive-fixnum*))))
746     (write-wordindexed symbol sb!vm:symbol-plist-slot *nil-descriptor*)
747     (write-wordindexed symbol sb!vm:symbol-name-slot
748                        (string-to-core name *dynamic*))
749     (write-wordindexed symbol sb!vm:symbol-package-slot *nil-descriptor*)
750     symbol))
751
752 ;;; Set the cold symbol value of SYMBOL-OR-SYMBOL-DES, which can be either a
753 ;;; descriptor of a cold symbol or (in an abbreviation for the
754 ;;; most common usage pattern) an ordinary symbol, which will be
755 ;;; automatically cold-interned.
756 (declaim (ftype (function ((or descriptor symbol) descriptor)) cold-set))
757 (defun cold-set (symbol-or-symbol-des value)
758   (let ((symbol-des (etypecase symbol-or-symbol-des
759                       (descriptor symbol-or-symbol-des)
760                       (symbol (cold-intern symbol-or-symbol-des)))))
761     (write-wordindexed symbol-des sb!vm:symbol-value-slot value)))
762 \f
763 ;;;; layouts and type system pre-initialization
764
765 ;;; Since we want to be able to dump structure constants and
766 ;;; predicates with reference layouts, we need to create layouts at
767 ;;; cold-load time. We use the name to intern layouts by, and dump a
768 ;;; list of all cold layouts in *!INITIAL-LAYOUTS* so that type system
769 ;;; initialization can find them. The only thing that's tricky [sic --
770 ;;; WHN 19990816] is initializing layout's layout, which must point to
771 ;;; itself.
772
773 ;;; a map from class names to lists of
774 ;;;    `(,descriptor ,name ,length ,inherits ,depth)
775 ;;; KLUDGE: It would be more understandable and maintainable to use
776 ;;; DEFSTRUCT (:TYPE LIST) here. -- WHN 19990823
777 (defvar *cold-layouts* (make-hash-table :test 'equal))
778
779 ;;; a map from DESCRIPTOR-BITS of cold layouts to the name, for inverting
780 ;;; mapping
781 (defvar *cold-layout-names* (make-hash-table :test 'eql))
782
783 ;;; FIXME: *COLD-LAYOUTS* and *COLD-LAYOUT-NAMES* should be
784 ;;; initialized by binding in GENESIS.
785
786 ;;; the descriptor for layout's layout (needed when making layouts)
787 (defvar *layout-layout*)
788
789 ;;; FIXME: This information should probably be pulled out of the
790 ;;; cross-compiler's tables at genesis time instead of inserted by
791 ;;; hand here as a bare numeric constant.
792 (defconstant target-layout-length 16)
793
794 ;;; Return a list of names created from the cold layout INHERITS data
795 ;;; in X.
796 (defun listify-cold-inherits (x)
797   (let ((len (descriptor-fixnum (read-wordindexed x
798                                                   sb!vm:vector-length-slot))))
799     (collect ((res))
800       (dotimes (index len)
801         (let* ((des (read-wordindexed x (+ sb!vm:vector-data-offset index)))
802                (found (gethash (descriptor-bits des) *cold-layout-names*)))
803           (if found
804             (res found)
805             (error "unknown descriptor at index ~S (bits = ~8,'0X)"
806                    index
807                    (descriptor-bits des)))))
808       (res))))
809
810 (declaim (ftype (function (symbol descriptor descriptor descriptor) descriptor)
811                 make-cold-layout))
812 (defun make-cold-layout (name length inherits depthoid)
813   (let ((result (allocate-boxed-object *dynamic*
814                                        ;; KLUDGE: Why 1+? -- WHN 19990901
815                                        (1+ target-layout-length)
816                                        sb!vm:instance-pointer-type)))
817     (write-memory result
818                   (make-other-immediate-descriptor target-layout-length
819                                                    sb!vm:instance-header-type))
820
821     ;; KLUDGE: The offsets into LAYOUT below should probably be pulled out
822     ;; of the cross-compiler's tables at genesis time instead of inserted
823     ;; by hand as bare numeric constants. -- WHN ca. 19990901
824
825     ;; Set slot 0 = the layout of the layout.
826     (write-wordindexed result sb!vm:instance-slots-offset *layout-layout*)
827
828     ;; Set the immediately following slots = CLOS hash values.
829     ;;
830     ;; Note: CMU CL didn't set these in genesis, but instead arranged
831     ;; for them to be set at cold init time. That resulted in slightly
832     ;; kludgy-looking code, but there were at least two things to be
833     ;; said for it:
834     ;;   1. It put the hash values under the control of the target Lisp's
835     ;;      RANDOM function, so that CLOS behavior would be nearly
836     ;;      deterministic (instead of depending on the implementation of
837     ;;      RANDOM in the cross-compilation host, and the state of its
838     ;;      RNG when genesis begins).
839     ;;   2. It automatically ensured that all hash values in the target Lisp
840     ;;      were part of the same sequence, so that we didn't have to worry
841     ;;      about the possibility of the first hash value set in genesis
842     ;;      being precisely equal to the some hash value set in cold init time
843     ;;      (because the target Lisp RNG has advanced to precisely the same
844     ;;      state that the host Lisp RNG was in earlier).
845     ;; Point 1 should not be an issue in practice because of the way we do our
846     ;; build procedure in two steps, so that the SBCL that we end up with has
847     ;; been created by another SBCL (whose RNG is under our control).
848     ;; Point 2 is more of an issue. If ANSI had provided a way to feed
849     ;; entropy into an RNG, we would have no problem: we'd just feed
850     ;; some specialized genesis-time-only pattern into the RNG state
851     ;; before using it. However, they didn't, so we have a slight
852     ;; problem. We address it by generating the hash values using a
853     ;; different algorithm than we use in ordinary operation.
854     (dotimes (i sb!kernel:layout-clos-hash-length)
855       (let (;; The expression here is pretty arbitrary, we just want
856             ;; to make sure that it's not something which is (1)
857             ;; evenly distributed and (2) not foreordained to arise in
858             ;; the target Lisp's (RANDOM-LAYOUT-CLOS-HASH) sequence
859             ;; and show up as the CLOS-HASH value of some other
860             ;; LAYOUT.
861             ;;
862             ;; FIXME: This expression here can generate a zero value,
863             ;; and the CMU CL code goes out of its way to generate
864             ;; strictly positive values (even though the field is
865             ;; declared as an INDEX). Check that it's really OK to
866             ;; have zero values in the CLOS-HASH slots.
867             (hash-value (mod (logxor (logand   (random-layout-clos-hash) 15253)
868                                      (logandc2 (random-layout-clos-hash) 15253)
869                                      1)
870                              ;; (The MOD here is defensive programming
871                              ;; to make sure we never write an
872                              ;; out-of-range value even if some joker
873                              ;; sets LAYOUT-CLOS-HASH-MAX to other
874                              ;; than 2^n-1 at some time in the
875                              ;; future.)
876                              (1+ sb!kernel:layout-clos-hash-max))))
877         (write-wordindexed result
878                            (+ i sb!vm:instance-slots-offset 1)
879                            (make-fixnum-descriptor hash-value))))
880
881     ;; Set other slot values.
882     (let ((base (+ sb!vm:instance-slots-offset
883                    sb!kernel:layout-clos-hash-length
884                    1)))
885       ;; (Offset 0 is CLASS, "the class this is a layout for", which
886       ;; is uninitialized at this point.)
887       (write-wordindexed result (+ base 1) *nil-descriptor*) ; marked invalid
888       (write-wordindexed result (+ base 2) inherits)
889       (write-wordindexed result (+ base 3) depthoid)
890       (write-wordindexed result (+ base 4) length)
891       (write-wordindexed result (+ base 5) *nil-descriptor*) ; info
892       (write-wordindexed result (+ base 6) *nil-descriptor*)) ; pure
893
894     (setf (gethash name *cold-layouts*)
895           (list result
896                 name
897                 (descriptor-fixnum length)
898                 (listify-cold-inherits inherits)
899                 (descriptor-fixnum depthoid)))
900     (setf (gethash (descriptor-bits result) *cold-layout-names*) name)
901
902     result))
903
904 (defun initialize-layouts ()
905
906   (clrhash *cold-layouts*)
907
908   ;; We initially create the layout of LAYOUT itself with NIL as the LAYOUT and
909   ;; #() as INHERITS,
910   (setq *layout-layout* *nil-descriptor*)
911   (setq *layout-layout*
912         (make-cold-layout 'layout
913                           (number-to-core target-layout-length)
914                           (vector-in-core)
915                           ;; FIXME: hard-coded LAYOUT-DEPTHOID of LAYOUT..
916                           (number-to-core 4)))
917   (write-wordindexed *layout-layout*
918                      sb!vm:instance-slots-offset
919                      *layout-layout*)
920
921   ;; Then we create the layouts that we'll need to make a correct INHERITS
922   ;; vector for the layout of LAYOUT itself..
923   ;;
924   ;; FIXME: The various LENGTH and DEPTHOID numbers should be taken from
925   ;; the compiler's tables, not set by hand.
926   (let* ((t-layout
927           (make-cold-layout 't
928                             (number-to-core 0)
929                             (vector-in-core)
930                             (number-to-core 0)))
931          (i-layout
932           (make-cold-layout 'instance
933                             (number-to-core 0)
934                             (vector-in-core t-layout)
935                             (number-to-core 1)))
936          (so-layout
937           (make-cold-layout 'structure-object
938                             (number-to-core 1)
939                             (vector-in-core t-layout i-layout)
940                             (number-to-core 2)))
941          (bso-layout
942           (make-cold-layout 'structure!object
943                             (number-to-core 1)
944                             (vector-in-core t-layout i-layout so-layout)
945                             (number-to-core 3)))
946          (layout-inherits (vector-in-core t-layout
947                                           i-layout
948                                           so-layout
949                                           bso-layout)))
950
951     ;; ..and return to backpatch the layout of LAYOUT.
952     (setf (fourth (gethash 'layout *cold-layouts*))
953           (listify-cold-inherits layout-inherits))
954     (write-wordindexed *layout-layout*
955                        ;; FIXME: hardcoded offset into layout struct
956                        (+ sb!vm:instance-slots-offset
957                           layout-clos-hash-length
958                           1
959                           2)
960                        layout-inherits)))
961 \f
962 ;;;; interning symbols in the cold image
963
964 ;;; In order to avoid having to know about the package format, we
965 ;;; build a data structure in *COLD-PACKAGE-SYMBOLS* that holds all
966 ;;; interned symbols along with info about their packages. The data
967 ;;; structure is a list of sublists, where the sublists have the
968 ;;; following format:
969 ;;;   (<make-package-arglist>
970 ;;;    <internal-symbols>
971 ;;;    <external-symbols>
972 ;;;    <imported-internal-symbols>
973 ;;;    <imported-external-symbols>
974 ;;;    <shadowing-symbols>)
975 ;;;
976 ;;; KLUDGE: It would be nice to implement the sublists as instances of
977 ;;; a DEFSTRUCT (:TYPE LIST). (They'd still be lists, but at least we'd be
978 ;;; using mnemonically-named operators to access them, instead of trying
979 ;;; to remember what THIRD and FIFTH mean, and hoping that we never
980 ;;; need to change the list layout..) -- WHN 19990825
981
982 ;;; an alist from packages to lists of that package's symbols to be dumped
983 (defvar *cold-package-symbols*)
984 (declaim (type list *cold-package-symbols*))
985
986 ;;; a map from descriptors to symbols, so that we can back up. The key is the
987 ;;; address in the target core.
988 (defvar *cold-symbols*)
989 (declaim (type hash-table *cold-symbols*))
990
991 ;;; Return a handle on an interned symbol. If necessary allocate the
992 ;;; symbol and record which package the symbol was referenced in. When
993 ;;; we allocate the symbol, make sure we record a reference to the
994 ;;; symbol in the home package so that the package gets set.
995 (defun cold-intern (symbol &optional (package (symbol-package symbol)))
996
997   ;; Anything on the cross-compilation host which refers to the target
998   ;; machinery through the host SB-XC package can be translated to
999   ;; something on the target which refers to the same machinery
1000   ;; through the target COMMON-LISP package.
1001   (let ((p (find-package "SB-XC")))
1002     (when (eq package p)
1003       (setf package *cl-package*))
1004     (when (eq (symbol-package symbol) p)
1005       (setf symbol (intern (symbol-name symbol) *cl-package*))))
1006
1007   (let (;; Information about each cold-interned symbol is stored
1008         ;; in COLD-INTERN-INFO.
1009         ;;   (CAR COLD-INTERN-INFO) = descriptor of symbol
1010         ;;   (CDR COLD-INTERN-INFO) = list of packages, other than symbol's
1011         ;;                          own package, referring to symbol
1012         ;; (*COLD-PACKAGE-SYMBOLS* and *COLD-SYMBOLS* store basically the same
1013         ;; information, but with the mapping running the opposite way.)
1014         (cold-intern-info (get symbol 'cold-intern-info)))
1015     (unless cold-intern-info
1016       (cond ((eq (symbol-package symbol) package)
1017              (let ((handle (allocate-symbol (symbol-name symbol))))
1018                (setf (gethash (descriptor-bits handle) *cold-symbols*) symbol)
1019                (when (eq package *keyword-package*)
1020                  (cold-set handle handle))
1021                (setq cold-intern-info
1022                      (setf (get symbol 'cold-intern-info) (cons handle nil)))))
1023             (t
1024              (cold-intern symbol)
1025              (setq cold-intern-info (get symbol 'cold-intern-info)))))
1026     (unless (or (null package)
1027                 (member package (cdr cold-intern-info)))
1028       (push package (cdr cold-intern-info))
1029       (let* ((old-cps-entry (assoc package *cold-package-symbols*))
1030              (cps-entry (or old-cps-entry
1031                             (car (push (list package)
1032                                        *cold-package-symbols*)))))
1033         (unless old-cps-entry
1034           (/show "created *COLD-PACKAGE-SYMBOLS* entry for" package symbol))
1035         (push symbol (rest cps-entry))))
1036     (car cold-intern-info)))
1037
1038 ;;; Construct and return a value for use as *NIL-DESCRIPTOR*.
1039 (defun make-nil-descriptor ()
1040   (let* ((des (allocate-unboxed-object
1041                *static*
1042                sb!vm:word-bits
1043                sb!vm:symbol-size
1044                0))
1045          (result (make-descriptor (descriptor-high des)
1046                                   (+ (descriptor-low des)
1047                                      (* 2 sb!vm:word-bytes)
1048                                      (- sb!vm:list-pointer-type
1049                                         sb!vm:other-pointer-type)))))
1050     (write-wordindexed des
1051                        1
1052                        (make-other-immediate-descriptor
1053                         0
1054                         sb!vm:symbol-header-type))
1055     (write-wordindexed des
1056                        (+ 1 sb!vm:symbol-value-slot)
1057                        result)
1058     (write-wordindexed des
1059                        (+ 2 sb!vm:symbol-value-slot)
1060                        result)
1061     (write-wordindexed des
1062                        (+ 1 sb!vm:symbol-plist-slot)
1063                        result)
1064     (write-wordindexed des
1065                        (+ 1 sb!vm:symbol-name-slot)
1066                        ;; This is *DYNAMIC*, and DES is *STATIC*,
1067                        ;; because that's the way CMU CL did it; I'm
1068                        ;; not sure whether there's an underlying
1069                        ;; reason. -- WHN 1990826
1070                        (string-to-core "NIL" *dynamic*))
1071     (write-wordindexed des
1072                        (+ 1 sb!vm:symbol-package-slot)
1073                        result)
1074     (setf (get nil 'cold-intern-info)
1075           (cons result nil))
1076     (cold-intern nil)
1077     result))
1078
1079 ;;; Since the initial symbols must be allocated before we can intern
1080 ;;; anything else, we intern those here. We also set the value of T.
1081 (defun initialize-non-nil-symbols ()
1082   #!+sb-doc
1083   "Initialize the cold load symbol-hacking data structures."
1084   (let ((*cold-symbol-allocation-gspace* *static*))
1085     ;; Intern the others.
1086     (dolist (symbol sb!vm:*static-symbols*)
1087       (let* ((des (cold-intern symbol))
1088              (offset-wanted (sb!vm:static-symbol-offset symbol))
1089              (offset-found (- (descriptor-low des)
1090                               (descriptor-low *nil-descriptor*))))
1091         (unless (= offset-wanted offset-found)
1092           ;; FIXME: should be fatal
1093           (warn "Offset from ~S to ~S is ~D, not ~D"
1094                 symbol
1095                 nil
1096                 offset-found
1097                 offset-wanted))))
1098     ;; Establish the value of T.
1099     (let ((t-symbol (cold-intern t)))
1100       (cold-set t-symbol t-symbol))))
1101
1102 ;;; a helper function for FINISH-SYMBOLS: Return a cold alist suitable
1103 ;;; to be stored in *!INITIAL-LAYOUTS*.
1104 (defun cold-list-all-layouts ()
1105   (let ((result *nil-descriptor*))
1106     (maphash (lambda (key stuff)
1107                (cold-push (cold-cons (cold-intern key)
1108                                      (first stuff))
1109                           result))
1110              *cold-layouts*)
1111     result))
1112
1113 ;;; Establish initial values for magic symbols.
1114 ;;;
1115 ;;; Scan over all the symbols referenced in each package in
1116 ;;; *COLD-PACKAGE-SYMBOLS* making that for each one there's an
1117 ;;; appropriate entry in the *!INITIAL-SYMBOLS* data structure to
1118 ;;; intern it.
1119 (defun finish-symbols ()
1120
1121   ;; FIXME: Why use SETQ (setting symbol value) instead of just using
1122   ;; the function values for these things?? I.e. why do we need this
1123   ;; section at all? Is it because all the FDEFINITION stuff gets in
1124   ;; the way of reading function values and is too hairy to rely on at
1125   ;; cold boot? FIXME: 5/6 of these are in *STATIC-SYMBOLS* in
1126   ;; parms.lisp, but %HANDLE-FUNCTION-END-BREAKPOINT is not. Why?
1127   ;; Explain.
1128   (macrolet ((frob (symbol)
1129                `(cold-set ',symbol
1130                           (cold-fdefinition-object (cold-intern ',symbol)))))
1131     (frob !cold-init)
1132     (frob sb!impl::maybe-gc)
1133     (frob internal-error)
1134     (frob sb!di::handle-breakpoint)
1135     (frob sb!di::handle-function-end-breakpoint)
1136     (frob sb!impl::fdefinition-object))
1137
1138   (cold-set '*current-catch-block*          (make-fixnum-descriptor 0))
1139   (cold-set '*current-unwind-protect-block* (make-fixnum-descriptor 0))
1140   (cold-set '*eval-stack-top*               (make-fixnum-descriptor 0))
1141
1142   (cold-set '*free-interrupt-context-index* (make-fixnum-descriptor 0))
1143
1144   ;; FIXME: *!INITIAL-LAYOUTS* should be exported from SB!KERNEL, or
1145   ;; perhaps from SB-LD.
1146   (cold-set 'sb!kernel::*!initial-layouts* (cold-list-all-layouts))
1147
1148   (/show "dumping packages" (mapcar #'car *cold-package-symbols*))
1149   (let ((initial-symbols *nil-descriptor*))
1150     (dolist (cold-package-symbols-entry *cold-package-symbols*)
1151       (let* ((cold-package (car cold-package-symbols-entry))
1152              (symbols (cdr cold-package-symbols-entry))
1153              (shadows (package-shadowing-symbols cold-package))
1154              (internal *nil-descriptor*)
1155              (external *nil-descriptor*)
1156              (imported-internal *nil-descriptor*)
1157              (imported-external *nil-descriptor*)
1158              (shadowing *nil-descriptor*))
1159         (/show "dumping" cold-package symbols)
1160
1161         ;; FIXME: Add assertions here to make sure that inappropriate stuff
1162         ;; isn't being dumped:
1163         ;;   * the CL-USER package
1164         ;;   * the SB-COLD package
1165         ;;   * any internal symbols in the CL package
1166         ;;   * basically any package other than CL, KEYWORD, or the packages
1167         ;;     in package-data-list.lisp-expr
1168         ;; and that the structure of the KEYWORD package (e.g. whether
1169         ;; any symbols are internal to it) matches what we want in the
1170         ;; target SBCL.
1171
1172         ;; FIXME: It seems possible that by looking at the contents of
1173         ;; packages in the target SBCL we could find which symbols in
1174         ;; package-data-lisp.lisp-expr are now obsolete. (If I
1175         ;; understand correctly, only symbols which actually have
1176         ;; definitions or which are otherwise referred to actually end
1177         ;; up in the target packages.)
1178
1179         (dolist (symbol symbols)
1180           (let ((handle (car (get symbol 'cold-intern-info)))
1181                 (imported-p (not (eq (symbol-package symbol) cold-package))))
1182             (multiple-value-bind (found where)
1183                 (find-symbol (symbol-name symbol) cold-package)
1184               (unless (and where (eq found symbol))
1185                 (error "The symbol ~S is not available in ~S."
1186                        symbol
1187                        cold-package))
1188               (when (memq symbol shadows)
1189                 (cold-push handle shadowing))
1190               (case where
1191                 (:internal (if imported-p
1192                                (cold-push handle imported-internal)
1193                                (cold-push handle internal)))
1194                 (:external (if imported-p
1195                                (cold-push handle imported-external)
1196                                (cold-push handle external)))))))
1197         (let ((r *nil-descriptor*))
1198           (cold-push shadowing r)
1199           (cold-push imported-external r)
1200           (cold-push imported-internal r)
1201           (cold-push external r)
1202           (cold-push internal r)
1203           (cold-push (make-make-package-args cold-package) r)
1204           ;; FIXME: It would be more space-efficient to use vectors
1205           ;; instead of lists here, and space-efficiency here would be
1206           ;; nice, since it would reduce the peak memory usage in
1207           ;; genesis and cold init.
1208           (cold-push r initial-symbols))))
1209     (cold-set '*!initial-symbols* initial-symbols))
1210
1211   (cold-set '*!initial-fdefn-objects* (list-all-fdefn-objects))
1212
1213   (cold-set '*!reversed-cold-toplevels* *current-reversed-cold-toplevels*)
1214
1215   #!+x86
1216   (progn
1217     (cold-set 'sb!vm::*fp-constant-0d0* (number-to-core 0d0))
1218     (cold-set 'sb!vm::*fp-constant-1d0* (number-to-core 1d0))
1219     (cold-set 'sb!vm::*fp-constant-0s0* (number-to-core 0s0))
1220     (cold-set 'sb!vm::*fp-constant-1s0* (number-to-core 1s0))
1221     #!+long-float
1222     (progn
1223       (cold-set 'sb!vm::*fp-constant-0l0* (number-to-core 0L0))
1224       (cold-set 'sb!vm::*fp-constant-1l0* (number-to-core 1L0))
1225       ;; FIXME: Why is initialization of PI conditional on LONG-FLOAT?
1226       ;; (ditto LG2, LN2, L2E, etc.)
1227       (cold-set 'sb!vm::*fp-constant-pi* (number-to-core pi))
1228       (cold-set 'sb!vm::*fp-constant-l2t* (number-to-core (log 10L0 2L0)))
1229       (cold-set 'sb!vm::*fp-constant-l2e*
1230             (number-to-core (log 2.718281828459045235360287471352662L0 2L0)))
1231       (cold-set 'sb!vm::*fp-constant-lg2* (number-to-core (log 2L0 10L0)))
1232       (cold-set 'sb!vm::*fp-constant-ln2*
1233             (number-to-core
1234              (log 2L0 2.718281828459045235360287471352662L0))))
1235     #!+gencgc
1236     (cold-set 'sb!vm::*SCAVENGE-READ-ONLY-GSPACE* *nil-descriptor*)))
1237
1238 ;;; Make a cold list that can be used as the arg list to MAKE-PACKAGE in order
1239 ;;; to make a package that is similar to PKG.
1240 (defun make-make-package-args (pkg)
1241   (let* ((use *nil-descriptor*)
1242          (cold-nicknames *nil-descriptor*)
1243          (res *nil-descriptor*))
1244     (dolist (u (package-use-list pkg))
1245       (when (assoc u *cold-package-symbols*)
1246         (cold-push (string-to-core (package-name u)) use)))
1247     (let* ((pkg-name (package-name pkg))
1248            ;; Make the package nickname lists for the standard packages
1249            ;; be the minimum specified by ANSI, regardless of what value
1250            ;; the cross-compilation host happens to use.
1251            (warm-nicknames (cond ((string= pkg-name "COMMON-LISP")
1252                                   '("CL"))
1253                                  ((string= pkg-name "COMMON-LISP-USER")
1254                                   '("CL-USER"))
1255                                  ((string= pkg-name "KEYWORD")
1256                                   '())
1257                                  ;; For packages other than the
1258                                  ;; standard packages, the nickname
1259                                  ;; list was specified by our package
1260                                  ;; setup code, not by properties of
1261                                  ;; what cross-compilation host we
1262                                  ;; happened to use, and we can just
1263                                  ;; propagate it into the target.
1264                                  (t
1265                                   (package-nicknames pkg)))))
1266       (dolist (warm-nickname warm-nicknames)
1267         (cold-push (string-to-core warm-nickname) cold-nicknames)))
1268
1269     (cold-push (number-to-core (truncate (package-internal-symbol-count pkg)
1270                                          0.8))
1271                res)
1272     (cold-push (cold-intern :internal-symbols) res)
1273     (cold-push (number-to-core (truncate (package-external-symbol-count pkg)
1274                                          0.8))
1275                res)
1276     (cold-push (cold-intern :external-symbols) res)
1277
1278     (cold-push cold-nicknames res)
1279     (cold-push (cold-intern :nicknames) res)
1280
1281     (cold-push use res)
1282     (cold-push (cold-intern :use) res)
1283
1284     (cold-push (string-to-core (package-name pkg)) res)
1285     res))
1286 \f
1287 ;;;; fdefinition objects
1288
1289 ;;; a hash table mapping from fdefinition names to descriptors of cold
1290 ;;; objects. Note: Since fdefinition names can be lists like '(SETF
1291 ;;; FOO), and we want to have only one entry per name, this must be an
1292 ;;; 'EQUAL hash table, not the default 'EQL.
1293 (defvar *cold-fdefn-objects*)
1294
1295 (defvar *cold-fdefn-gspace* nil)
1296
1297 ;;; Given a cold representation of an FDEFN name, return a warm representation.
1298 ;;;
1299 ;;; Note: Despite the name, this actually has little to do with
1300 ;;; FDEFNs, it's just a function for warming up values, and the only
1301 ;;; values it knows how to warm up are symbols and lists. (The
1302 ;;; connection to FDEFNs is that symbols and lists are the only
1303 ;;; possible names for functions.)
1304 (declaim (ftype (function (descriptor) (or symbol list)) warm-fdefn-name))
1305 (defun warm-fdefn-name (des)
1306   (ecase (descriptor-lowtag des)
1307     (#.sb!vm:list-pointer-type ; FIXME: no #.
1308      (if (= (descriptor-bits des) (descriptor-bits *nil-descriptor*))
1309          nil
1310          ;; FIXME: If we cold-intern this again, we might get a different
1311          ;; name. Check to make sure that any hash tables along the way
1312          ;; are 'EQUAL not 'EQL.
1313          (cons (warm-fdefn-name (read-wordindexed des sb!vm:cons-car-slot))
1314                (warm-fdefn-name (read-wordindexed des sb!vm:cons-cdr-slot)))))
1315     (#.sb!vm:other-pointer-type ; FIXME: no #.
1316      (or (gethash (descriptor-bits des) *cold-symbols*)
1317          (descriptor-bits des)))))
1318
1319 (defun cold-fdefinition-object (cold-name &optional leave-fn-raw)
1320   (declare (type descriptor cold-name))
1321   (let ((warm-name (warm-fdefn-name cold-name)))
1322     (or (gethash warm-name *cold-fdefn-objects*)
1323         (let ((fdefn (allocate-boxed-object (or *cold-fdefn-gspace* *dynamic*)
1324                                             (1- sb!vm:fdefn-size)
1325                                             sb!vm:other-pointer-type)))
1326
1327           (setf (gethash warm-name *cold-fdefn-objects*) fdefn)
1328           (write-memory fdefn (make-other-immediate-descriptor
1329                                (1- sb!vm:fdefn-size) sb!vm:fdefn-type))
1330           (write-wordindexed fdefn sb!vm:fdefn-name-slot cold-name)
1331           (unless leave-fn-raw
1332             (write-wordindexed fdefn sb!vm:fdefn-function-slot
1333                                *nil-descriptor*)
1334             (write-wordindexed fdefn
1335                                sb!vm:fdefn-raw-addr-slot
1336                                (make-random-descriptor
1337                                 (lookup-foreign-symbol "undefined_tramp"))))
1338           fdefn))))
1339
1340 (defun cold-fset (cold-name defn)
1341   (declare (type descriptor cold-name))
1342   (let ((fdefn (cold-fdefinition-object cold-name t))
1343         (type (logand (descriptor-low (read-memory defn)) sb!vm:type-mask)))
1344     (write-wordindexed fdefn sb!vm:fdefn-function-slot defn)
1345     (write-wordindexed fdefn
1346                        sb!vm:fdefn-raw-addr-slot
1347                        (ecase type
1348                          (#.sb!vm:function-header-type
1349                           #!+sparc
1350                           defn
1351                           #!-sparc
1352                           (make-random-descriptor
1353                            (+ (logandc2 (descriptor-bits defn)
1354                                         sb!vm:lowtag-mask)
1355                               (ash sb!vm:function-code-offset
1356                                    sb!vm:word-shift))))
1357                          (#.sb!vm:closure-header-type
1358                           (make-random-descriptor
1359                            (lookup-foreign-symbol "closure_tramp")))))
1360     fdefn))
1361
1362 (defun initialize-static-fns ()
1363   (let ((*cold-fdefn-gspace* *static*))
1364     (dolist (sym sb!vm:*static-functions*)
1365       (let* ((fdefn (cold-fdefinition-object (cold-intern sym)))
1366              (offset (- (+ (- (descriptor-low fdefn)
1367                               sb!vm:other-pointer-type)
1368                            (* sb!vm:fdefn-raw-addr-slot sb!vm:word-bytes))
1369                         (descriptor-low *nil-descriptor*)))
1370              (desired (sb!vm:static-function-offset sym)))
1371         (unless (= offset desired)
1372           ;; FIXME: should be fatal
1373           (warn "Offset from FDEFN ~S to ~S is ~D, not ~D."
1374                 sym nil offset desired))))))
1375
1376 (defun list-all-fdefn-objects ()
1377   (let ((result *nil-descriptor*))
1378     (maphash #'(lambda (key value)
1379                  (declare (ignore key))
1380                  (cold-push value result))
1381              *cold-fdefn-objects*)
1382     result))
1383 \f
1384 ;;;; fixups and related stuff
1385
1386 ;;; an EQUAL hash table
1387 (defvar *cold-foreign-symbol-table*)
1388 (declaim (type hash-table *cold-foreign-symbol-table*))
1389
1390 (defun load-foreign-symbol-table (filename)
1391   (with-open-file (file filename)
1392     (loop
1393       (let ((line (read-line file nil nil)))
1394         (unless line
1395           (return))
1396         ;; UNIX symbol tables might have tabs in them, and tabs are
1397         ;; not in Common Lisp STANDARD-CHAR, so there seems to be no
1398         ;; nice portable way to deal with them within Lisp, alas.
1399         ;; Fortunately, it's easy to use UNIX command line tools like
1400         ;; sed to remove the problem, so it's not too painful for us
1401         ;; to push responsibility for converting tabs to spaces out to
1402         ;; the caller.
1403         ;;
1404         ;; Other non-STANDARD-CHARs are problematic for the same reason.
1405         ;; Make sure that there aren't any..
1406         (let ((ch (find-if (lambda (char)
1407                              (not (typep char 'standard-char)))
1408                           line)))
1409           (when ch
1410             (error "non-STANDARD-CHAR ~S found in foreign symbol table:~%~S"
1411                    ch
1412                    line)))
1413         (setf line (string-trim '(#\space) line))
1414         (let ((p1 (position #\space line :from-end nil))
1415               (p2 (position #\space line :from-end t)))
1416           (if (not (and p1 p2 (< p1 p2)))
1417               ;; KLUDGE: It's too messy to try to understand all
1418               ;; possible output from nm, so we just punt the lines we
1419               ;; don't recognize. We realize that there's some chance
1420               ;; that might get us in trouble someday, so we warn
1421               ;; about it.
1422               (warn "ignoring unrecognized line ~S in ~A" line filename)
1423               (multiple-value-bind (value name)
1424                   (if (string= "0x" line :end2 2)
1425                       (values (parse-integer line :start 2 :end p1 :radix 16)
1426                               (subseq line (1+ p2)))
1427                       (values (parse-integer line :end p1 :radix 16)
1428                               (subseq line (1+ p2))))
1429                 (multiple-value-bind (old-value found)
1430                     (gethash name *cold-foreign-symbol-table*)
1431                   (when (and found
1432                              (not (= old-value value)))
1433                     (warn "redefining ~S from #X~X to #X~X"
1434                           name old-value value)))
1435                 (setf (gethash name *cold-foreign-symbol-table*) value))))))
1436     (values)))
1437
1438 (defun lookup-foreign-symbol (name)
1439   #!+x86
1440   (let ((prefixes
1441          #!+linux #(;; FIXME: How many of these are actually
1442                     ;; needed? The first four are taken from rather
1443                     ;; disorganized CMU CL code, which could easily
1444                     ;; have had redundant values in it..
1445                     "_"
1446                     "__"
1447                     "__libc_"
1448                     "ldso_stub__"
1449                     ;; ..and the fifth seems to match most
1450                     ;; actual symbols, at least in RedHat 6.2.
1451                     "")
1452          #!+freebsd #("" "ldso_stub__")
1453          #!+openbsd #("_")))
1454     (or (some (lambda (prefix)
1455                 (gethash (concatenate 'string prefix name)
1456                          *cold-foreign-symbol-table*
1457                          nil))
1458               prefixes)
1459         *foreign-symbol-placeholder-value*
1460         (progn
1461           (format *error-output* "~&The foreign symbol table is:~%")
1462           (maphash (lambda (k v)
1463                      (format *error-output* "~&~S = #X~8X~%" k v))
1464                    *cold-foreign-symbol-table*)
1465           (format *error-output* "~&The prefix table is: ~S~%" prefixes)
1466           (error "The foreign symbol ~S is undefined." name))))
1467   #!-x86 (error "non-x86 unsupported in SBCL (but see old CMU CL code)"))
1468
1469 (defvar *cold-assembler-routines*)
1470
1471 (defvar *cold-assembler-fixups*)
1472
1473 (defun record-cold-assembler-routine (name address)
1474   (/xhow "in RECORD-COLD-ASSEMBLER-ROUTINE" name address)
1475   (push (cons name address)
1476         *cold-assembler-routines*))
1477
1478 (defun record-cold-assembler-fixup (routine
1479                                     code-object
1480                                     offset
1481                                     &optional
1482                                     (kind :both))
1483   (push (list routine code-object offset kind)
1484         *cold-assembler-fixups*))
1485
1486 (defun lookup-assembler-reference (symbol)
1487   (let ((value (cdr (assoc symbol *cold-assembler-routines*))))
1488     ;; FIXME: Should this be ERROR instead of WARN?
1489     (unless value
1490       (warn "Assembler routine ~S not defined." symbol))
1491     value))
1492
1493 ;;; The x86 port needs to store code fixups along with code objects if
1494 ;;; they are to be moved, so fixups for code objects in the dynamic
1495 ;;; heap need to be noted.
1496 #!+x86
1497 (defvar *load-time-code-fixups*)
1498
1499 #!+x86
1500 (defun note-load-time-code-fixup (code-object offset value kind)
1501   ;; If CODE-OBJECT might be moved
1502   (when (= (gspace-identifier (descriptor-intuit-gspace code-object))
1503            dynamic-space-id)
1504     ;; FIXME: pushed thing should be a structure, not just a list
1505     (push (list code-object offset value kind) *load-time-code-fixups*))
1506   (values))
1507
1508 #!+x86
1509 (defun output-load-time-code-fixups ()
1510   (dolist (fixups *load-time-code-fixups*)
1511     (let ((code-object (first fixups))
1512           (offset (second fixups))
1513           (value (third fixups))
1514           (kind (fourth fixups)))
1515       (cold-push (cold-cons
1516                   (cold-intern :load-time-code-fixup)
1517                   (cold-cons
1518                    code-object
1519                    (cold-cons
1520                     (number-to-core offset)
1521                     (cold-cons
1522                      (number-to-core value)
1523                      (cold-cons
1524                       (cold-intern kind)
1525                       *nil-descriptor*)))))
1526                  *current-reversed-cold-toplevels*))))
1527
1528 ;;; Given a pointer to a code object and an offset relative to the
1529 ;;; tail of the code object's header, return an offset relative to the
1530 ;;; (beginning of the) code object.
1531 ;;;
1532 ;;; FIXME: It might be clearer to reexpress
1533 ;;;    (LET ((X (CALC-OFFSET CODE-OBJECT OFFSET0))) ..)
1534 ;;; as
1535 ;;;    (LET ((X (+ OFFSET0 (CODE-OBJECT-HEADER-N-BYTES CODE-OBJECT)))) ..).
1536 (declaim (ftype (function (descriptor sb!vm:word)) calc-offset))
1537 (defun calc-offset (code-object offset-from-tail-of-header)
1538   (let* ((header (read-memory code-object))
1539          (header-n-words (ash (descriptor-bits header) (- sb!vm:type-bits)))
1540          (header-n-bytes (ash header-n-words sb!vm:word-shift))
1541          (result (+ offset-from-tail-of-header header-n-bytes)))
1542     result))
1543
1544 (declaim (ftype (function (descriptor sb!vm:word sb!vm:word keyword))
1545                 do-cold-fixup))
1546 (defun do-cold-fixup (code-object after-header value kind)
1547   (let* ((offset-within-code-object (calc-offset code-object after-header))
1548          (gspace-bytes (descriptor-bytes code-object))
1549          (gspace-byte-offset (+ (descriptor-byte-offset code-object)
1550                                 offset-within-code-object))
1551          (gspace-byte-address (gspace-byte-address
1552                                (descriptor-gspace code-object))))
1553     (ecase sb!c:*backend-fasl-file-implementation*
1554       ;; Classic CMU CL supported these, and I haven't gone out of my way
1555       ;; to break them, but I have no way of testing them.. -- WHN 19990817
1556       #|
1557       (#.sb!c:pmax-fasl-file-implementation
1558        (ecase kind
1559          (:jump
1560           (assert (zerop (ash value -28)))
1561           (setf (ldb (byte 26 0) (sap-ref-32 sap 0))
1562                 (ash value -2)))
1563          (:lui
1564           (setf (sap-ref-16 sap 0)
1565                 (+ (ash value -16)
1566                    (if (logbitp 15 value) 1 0))))
1567          (:addi
1568           (setf (sap-ref-16 sap 0)
1569                 (ldb (byte 16 0) value)))))
1570       (#.sb!c:sparc-fasl-file-implementation
1571        (let ((inst (maybe-byte-swap (sap-ref-32 sap 0))))
1572          (ecase kind
1573            (:call
1574             (error "Can't deal with call fixups yet."))
1575            (:sethi
1576             (setf inst
1577                   (dpb (ldb (byte 22 10) value)
1578                        (byte 22 0)
1579                        inst)))
1580            (:add
1581             (setf inst
1582                   (dpb (ldb (byte 10 0) value)
1583                        (byte 10 0)
1584                        inst))))
1585          (setf (sap-ref-32 sap 0)
1586                (maybe-byte-swap inst))))
1587       ((#.sb!c:rt-fasl-file-implementation
1588         #.sb!c:rt-afpa-fasl-file-implementation)
1589        (ecase kind
1590          (:cal
1591           (setf (sap-ref-16 sap 2)
1592                 (maybe-byte-swap-short
1593                  (ldb (byte 16 0) value))))
1594          (:cau
1595           (let ((high (ldb (byte 16 16) value)))
1596             (setf (sap-ref-16 sap 2)
1597                   (maybe-byte-swap-short
1598                    (if (logbitp 15 value) (1+ high) high)))))
1599          (:ba
1600           (unless (zerop (ash value -24))
1601             (warn "#X~8,'0X out of range for branch-absolute." value))
1602           (let ((inst (maybe-byte-swap-short (sap-ref-16 sap 0))))
1603             (setf (sap-ref-16 sap 0)
1604                   (maybe-byte-swap-short
1605                    (dpb (ldb (byte 8 16) value)
1606                         (byte 8 0)
1607                         inst))))
1608           (setf (sap-ref-16 sap 2)
1609                 (maybe-byte-swap-short (ldb (byte 16 0) value))))))
1610       |#
1611       (:x86
1612        (let* ((un-fixed-up (byte-vector-ref-32 gspace-bytes
1613                                                gspace-byte-offset))
1614               (code-object-start-addr (logandc2 (descriptor-bits code-object)
1615                                                 sb!vm:lowtag-mask)))
1616          (assert (= code-object-start-addr
1617                     (+ gspace-byte-address
1618                        (descriptor-byte-offset code-object))))
1619          (ecase kind
1620            (:absolute
1621             (let ((fixed-up (+ value un-fixed-up)))
1622               (setf (byte-vector-ref-32 gspace-bytes gspace-byte-offset)
1623                     fixed-up)
1624               ;; comment from CMU CL sources:
1625               ;;
1626               ;; Note absolute fixups that point within the object.
1627               ;; KLUDGE: There seems to be an implicit assumption in
1628               ;; the old CMU CL code here, that if it doesn't point
1629               ;; before the object, it must point within the object
1630               ;; (not beyond it). It would be good to add an
1631               ;; explanation of why that's true, or an assertion that
1632               ;; it's really true, or both.
1633               (unless (< fixed-up code-object-start-addr)
1634                 (note-load-time-code-fixup code-object
1635                                            after-header
1636                                            value
1637                                            kind))))
1638            (:relative ; (used for arguments to X86 relative CALL instruction)
1639             (let ((fixed-up (- (+ value un-fixed-up)
1640                                gspace-byte-address
1641                                gspace-byte-offset
1642                                sb!vm:word-bytes))) ; length of CALL argument
1643               (setf (byte-vector-ref-32 gspace-bytes gspace-byte-offset)
1644                     fixed-up)
1645               ;; Note relative fixups that point outside the code
1646               ;; object, which is to say all relative fixups, since
1647               ;; relative addressing within a code object never needs
1648               ;; a fixup.
1649               (note-load-time-code-fixup code-object
1650                                          after-header
1651                                          value
1652                                          kind))))))
1653       ;; CMU CL supported these, and I haven't gone out of my way to break
1654       ;; them, but I have no way of testing them.. -- WHN 19990817
1655       #|
1656       (#.sb!c:hppa-fasl-file-implementation
1657        (let ((inst (maybe-byte-swap (sap-ref-32 sap 0))))
1658          (setf (sap-ref-32 sap 0)
1659                (maybe-byte-swap
1660                 (ecase kind
1661                   (:load
1662                    (logior (ash (ldb (byte 11 0) value) 1)
1663                            (logand inst #xffffc000)))
1664                   (:load-short
1665                    (let ((low-bits (ldb (byte 11 0) value)))
1666                      (assert (<= 0 low-bits (1- (ash 1 4))))
1667                      (logior (ash low-bits 17)
1668                              (logand inst #xffe0ffff))))
1669                   (:hi
1670                    (logior (ash (ldb (byte 5 13) value) 16)
1671                            (ash (ldb (byte 2 18) value) 14)
1672                            (ash (ldb (byte 2 11) value) 12)
1673                            (ash (ldb (byte 11 20) value) 1)
1674                            (ldb (byte 1 31) value)
1675                            (logand inst #xffe00000)))
1676                   (:branch
1677                    (let ((bits (ldb (byte 9 2) value)))
1678                      (assert (zerop (ldb (byte 2 0) value)))
1679                      (logior (ash bits 3)
1680                              (logand inst #xffe0e002)))))))))
1681       (#.sb!c:alpha-fasl-file-implementation
1682        (ecase kind
1683          (:jmp-hint
1684           (assert (zerop (ldb (byte 2 0) value)))
1685           #+nil
1686           (setf (sap-ref-16 sap 0)
1687                 (logior (sap-ref-16 sap 0) (ldb (byte 14 0) (ash value -2)))))
1688          (:bits-63-48
1689           (let* ((value (if (logbitp 15 value) (+ value (ash 1 16)) value))
1690                  (value (if (logbitp 31 value) (+ value (ash 1 32)) value))
1691                  (value (if (logbitp 47 value) (+ value (ash 1 48)) value)))
1692             (setf (sap-ref-8 sap 0) (ldb (byte 8 48) value))
1693             (setf (sap-ref-8 sap 1) (ldb (byte 8 56) value))))
1694          (:bits-47-32
1695           (let* ((value (if (logbitp 15 value) (+ value (ash 1 16)) value))
1696                  (value (if (logbitp 31 value) (+ value (ash 1 32)) value)))
1697             (setf (sap-ref-8 sap 0) (ldb (byte 8 32) value))
1698             (setf (sap-ref-8 sap 1) (ldb (byte 8 40) value))))
1699          (:ldah
1700           (let ((value (if (logbitp 15 value) (+ value (ash 1 16)) value)))
1701             (setf (sap-ref-8 sap 0) (ldb (byte 8 16) value))
1702             (setf (sap-ref-8 sap 1) (ldb (byte 8 24) value))))
1703          (:lda
1704           (setf (sap-ref-8 sap 0) (ldb (byte 8 0) value))
1705           (setf (sap-ref-8 sap 1) (ldb (byte 8 8) value)))))
1706       (#.sb!c:sgi-fasl-file-implementation
1707        (ecase kind
1708          (:jump
1709           (assert (zerop (ash value -28)))
1710           (setf (ldb (byte 26 0) (sap-ref-32 sap 0))
1711                 (ash value -2)))
1712          (:lui
1713           (setf (sap-ref-16 sap 2)
1714                 (+ (ash value -16)
1715                    (if (logbitp 15 value) 1 0))))
1716          (:addi
1717           (setf (sap-ref-16 sap 2)
1718                 (ldb (byte 16 0) value)))))
1719       |#
1720       ))
1721   (values))
1722
1723 (defun resolve-assembler-fixups ()
1724   (dolist (fixup *cold-assembler-fixups*)
1725     (let* ((routine (car fixup))
1726            (value (lookup-assembler-reference routine)))
1727       (when value
1728         (do-cold-fixup (second fixup) (third fixup) value (fourth fixup))))))
1729
1730 (defun linkage-info-to-core ()
1731   (let ((result *nil-descriptor*))
1732     (maphash #'(lambda (symbol value)
1733                  (cold-push (cold-cons (string-to-core symbol)
1734                                        (number-to-core value))
1735                             result))
1736              *cold-foreign-symbol-table*)
1737     (cold-set (cold-intern '*!initial-foreign-symbols*) result))
1738   (let ((result *nil-descriptor*))
1739     (dolist (rtn *cold-assembler-routines*)
1740       (cold-push (cold-cons (cold-intern (car rtn))
1741                             (number-to-core (cdr rtn)))
1742                  result))
1743     (cold-set (cold-intern '*!initial-assembler-routines*) result)))
1744 \f
1745 ;;;; general machinery for cold-loading FASL files
1746
1747 (defvar *cold-fop-functions* (replace (make-array 256) *fop-functions*)
1748   #!+sb-doc
1749   "FOP functions for cold loading")
1750
1751 (defvar *normal-fop-functions*)
1752
1753 ;;; Cause a fop to have a special definition for cold load.
1754 ;;; 
1755 ;;; This is similar to DEFINE-FOP, but unlike DEFINE-FOP, this version
1756 ;;;   (1) looks up the code for this name (created by a previous
1757 ;;        DEFINE-FOP) instead of creating a code, and
1758 ;;;   (2) stores its definition in the *COLD-FOP-FUNCTIONS* vector,
1759 ;;;       instead of storing in the *FOP-FUNCTIONS* vector.
1760 (defmacro define-cold-fop ((name &optional (pushp t)) &rest forms)
1761   (check-type pushp (member nil t :nope))
1762   (let ((code (get name 'fop-code))
1763         (fname (symbolicate "COLD-" name)))
1764     (unless code
1765       (error "~S is not a defined FOP." name))
1766     `(progn
1767        (defun ,fname ()
1768          ,@(if (eq pushp :nope)
1769              forms
1770              `((with-fop-stack ,pushp ,@forms))))
1771        (setf (svref *cold-fop-functions* ,code) #',fname))))
1772
1773 (defmacro clone-cold-fop ((name &optional (pushp t)) (small-name) &rest forms)
1774   (check-type pushp (member nil t :nope))
1775   `(progn
1776     (macrolet ((clone-arg () '(read-arg 4)))
1777       (define-cold-fop (,name ,pushp) ,@forms))
1778     (macrolet ((clone-arg () '(read-arg 1)))
1779       (define-cold-fop (,small-name ,pushp) ,@forms))))
1780
1781 ;;; Cause a fop to be undefined in cold load.
1782 (defmacro not-cold-fop (name)
1783   `(define-cold-fop (,name)
1784      (error "The fop ~S is not supported in cold load." ',name)))
1785
1786 ;;; COLD-LOAD loads stuff into the core image being built by calling
1787 ;;; FASLOAD with the fop function table rebound to a table of cold
1788 ;;; loading functions.
1789 (defun cold-load (filename)
1790   #!+sb-doc
1791   "Load the file named by FILENAME into the cold load image being built."
1792   (let* ((*normal-fop-functions* *fop-functions*)
1793          (*fop-functions* *cold-fop-functions*)
1794          (*cold-load-filename* (etypecase filename
1795                                  (string filename)
1796                                  (pathname (namestring filename)))))
1797     (with-open-file (s filename :element-type '(unsigned-byte 8))
1798       (fasload s nil nil))))
1799 \f
1800 ;;;; miscellaneous cold fops
1801
1802 (define-cold-fop (fop-misc-trap) *unbound-marker*)
1803
1804 (define-cold-fop (fop-character)
1805   (make-character-descriptor (read-arg 3)))
1806 (define-cold-fop (fop-short-character)
1807   (make-character-descriptor (read-arg 1)))
1808
1809 (define-cold-fop (fop-empty-list) *nil-descriptor*)
1810 (define-cold-fop (fop-truth) (cold-intern t))
1811
1812 (define-cold-fop (fop-normal-load :nope)
1813   (setq *fop-functions* *normal-fop-functions*))
1814
1815 (define-fop (fop-maybe-cold-load 82 :nope)
1816   (when *cold-load-filename*
1817     (setq *fop-functions* *cold-fop-functions*)))
1818
1819 (define-cold-fop (fop-maybe-cold-load :nope))
1820
1821 (clone-cold-fop (fop-struct)
1822                 (fop-small-struct)
1823   (let* ((size (clone-arg))
1824          (result (allocate-boxed-object *dynamic*
1825                                         (1+ size)
1826                                         sb!vm:instance-pointer-type)))
1827     (write-memory result (make-other-immediate-descriptor
1828                           size
1829                           sb!vm:instance-header-type))
1830     (do ((index (1- size) (1- index)))
1831         ((minusp index))
1832       (declare (fixnum index))
1833       (write-wordindexed result
1834                          (+ index sb!vm:instance-slots-offset)
1835                          (pop-stack)))
1836     result))
1837
1838 (define-cold-fop (fop-layout)
1839   (let* ((length-des (pop-stack))
1840          (depthoid-des (pop-stack))
1841          (cold-inherits (pop-stack))
1842          (name (pop-stack))
1843          (old (gethash name *cold-layouts*)))
1844     (declare (type descriptor length-des depthoid-des cold-inherits))
1845     (declare (type symbol name))
1846     ;; If a layout of this name has been defined already
1847     (if old
1848       ;; Enforce consistency between the previous definition and the
1849       ;; current definition, then return the previous definition.
1850       (destructuring-bind
1851           ;; FIXME: This would be more maintainable if we used
1852           ;; DEFSTRUCT (:TYPE LIST) to define COLD-LAYOUT. -- WHN 19990825
1853           (old-layout-descriptor
1854            old-name
1855            old-length
1856            old-inherits-list
1857            old-depthoid)
1858           old
1859         (declare (type descriptor old-layout-descriptor))
1860         (declare (type index old-length))
1861         (declare (type fixnum old-depthoid))
1862         (declare (type list old-inherits-list))
1863         (assert (eq name old-name))
1864         (let ((length (descriptor-fixnum length-des))
1865               (inherits-list (listify-cold-inherits cold-inherits))
1866               (depthoid (descriptor-fixnum depthoid-des)))
1867           (unless (= length old-length)
1868             (error "cold loading a reference to class ~S when the compile~%~
1869                    time length was ~S and current length is ~S"
1870                    name
1871                    length
1872                    old-length))
1873           (unless (equal inherits-list old-inherits-list)
1874             (error "cold loading a reference to class ~S when the compile~%~
1875                    time inherits were ~S~%~
1876                    and current inherits are ~S"
1877                    name
1878                    inherits-list
1879                    old-inherits-list))
1880           (unless (= depthoid old-depthoid)
1881             (error "cold loading a reference to class ~S when the compile~%~
1882                    time inheritance depthoid was ~S and current inheritance~%~
1883                    depthoid is ~S"
1884                    name
1885                    depthoid
1886                    old-depthoid)))
1887         old-layout-descriptor)
1888       ;; Make a new definition from scratch.
1889       (make-cold-layout name length-des cold-inherits depthoid-des))))
1890 \f
1891 ;;;; cold fops for loading symbols
1892
1893 ;;; Load a symbol SIZE characters long from *FASL-FILE* and intern
1894 ;;; that symbol in PACKAGE.
1895 (defun cold-load-symbol (size package)
1896   (let ((string (make-string size)))
1897     (read-string-as-bytes *fasl-file* string)
1898     (cold-intern (intern string package) package)))
1899
1900 (macrolet ((frob (name pname-len package-len)
1901              `(define-cold-fop (,name)
1902                 (let ((index (read-arg ,package-len)))
1903                   (push-fop-table
1904                    (cold-load-symbol (read-arg ,pname-len)
1905                                      (svref *current-fop-table* index)))))))
1906   (frob fop-symbol-in-package-save 4 4)
1907   (frob fop-small-symbol-in-package-save 1 4)
1908   (frob fop-symbol-in-byte-package-save 4 1)
1909   (frob fop-small-symbol-in-byte-package-save 1 1))
1910
1911 (clone-cold-fop (fop-lisp-symbol-save)
1912                 (fop-lisp-small-symbol-save)
1913   (push-fop-table (cold-load-symbol (clone-arg) *cl-package*)))
1914
1915 (clone-cold-fop (fop-keyword-symbol-save)
1916                 (fop-keyword-small-symbol-save)
1917   (push-fop-table (cold-load-symbol (clone-arg) *keyword-package*)))
1918
1919 (clone-cold-fop (fop-uninterned-symbol-save)
1920                 (fop-uninterned-small-symbol-save)
1921   (let* ((size (clone-arg))
1922          (name (make-string size)))
1923     (read-string-as-bytes *fasl-file* name)
1924     (let ((symbol (allocate-symbol name)))
1925       (push-fop-table symbol))))
1926 \f
1927 ;;;; cold fops for loading lists
1928
1929 ;;; Make a list of the top LENGTH things on the fop stack. The last
1930 ;;; cdr of the list is set to LAST.
1931 (defmacro cold-stack-list (length last)
1932   `(do* ((index ,length (1- index))
1933          (result ,last (cold-cons (pop-stack) result)))
1934         ((= index 0) result)
1935      (declare (fixnum index))))
1936
1937 (define-cold-fop (fop-list)
1938   (cold-stack-list (read-arg 1) *nil-descriptor*))
1939 (define-cold-fop (fop-list*)
1940   (cold-stack-list (read-arg 1) (pop-stack)))
1941 (define-cold-fop (fop-list-1)
1942   (cold-stack-list 1 *nil-descriptor*))
1943 (define-cold-fop (fop-list-2)
1944   (cold-stack-list 2 *nil-descriptor*))
1945 (define-cold-fop (fop-list-3)
1946   (cold-stack-list 3 *nil-descriptor*))
1947 (define-cold-fop (fop-list-4)
1948   (cold-stack-list 4 *nil-descriptor*))
1949 (define-cold-fop (fop-list-5)
1950   (cold-stack-list 5 *nil-descriptor*))
1951 (define-cold-fop (fop-list-6)
1952   (cold-stack-list 6 *nil-descriptor*))
1953 (define-cold-fop (fop-list-7)
1954   (cold-stack-list 7 *nil-descriptor*))
1955 (define-cold-fop (fop-list-8)
1956   (cold-stack-list 8 *nil-descriptor*))
1957 (define-cold-fop (fop-list*-1)
1958   (cold-stack-list 1 (pop-stack)))
1959 (define-cold-fop (fop-list*-2)
1960   (cold-stack-list 2 (pop-stack)))
1961 (define-cold-fop (fop-list*-3)
1962   (cold-stack-list 3 (pop-stack)))
1963 (define-cold-fop (fop-list*-4)
1964   (cold-stack-list 4 (pop-stack)))
1965 (define-cold-fop (fop-list*-5)
1966   (cold-stack-list 5 (pop-stack)))
1967 (define-cold-fop (fop-list*-6)
1968   (cold-stack-list 6 (pop-stack)))
1969 (define-cold-fop (fop-list*-7)
1970   (cold-stack-list 7 (pop-stack)))
1971 (define-cold-fop (fop-list*-8)
1972   (cold-stack-list 8 (pop-stack)))
1973 \f
1974 ;;;; cold fops for loading vectors
1975
1976 (clone-cold-fop (fop-string)
1977                 (fop-small-string)
1978   (let* ((len (clone-arg))
1979          (string (make-string len)))
1980     (read-string-as-bytes *fasl-file* string)
1981     (string-to-core string)))
1982
1983 (clone-cold-fop (fop-vector)
1984                 (fop-small-vector)
1985   (let* ((size (clone-arg))
1986          (result (allocate-vector-object *dynamic*
1987                                          sb!vm:word-bits
1988                                          size
1989                                          sb!vm:simple-vector-type)))
1990     (do ((index (1- size) (1- index)))
1991         ((minusp index))
1992       (declare (fixnum index))
1993       (write-wordindexed result
1994                          (+ index sb!vm:vector-data-offset)
1995                          (pop-stack)))
1996     result))
1997
1998 (define-cold-fop (fop-int-vector)
1999   (let* ((len (read-arg 4))
2000          (sizebits (read-arg 1))
2001          (type (case sizebits
2002                  (1 sb!vm:simple-bit-vector-type)
2003                  (2 sb!vm:simple-array-unsigned-byte-2-type)
2004                  (4 sb!vm:simple-array-unsigned-byte-4-type)
2005                  (8 sb!vm:simple-array-unsigned-byte-8-type)
2006                  (16 sb!vm:simple-array-unsigned-byte-16-type)
2007                  (32 sb!vm:simple-array-unsigned-byte-32-type)
2008                  (t (error "losing element size: ~D" sizebits))))
2009          (result (allocate-vector-object *dynamic* sizebits len type))
2010          (start (+ (descriptor-byte-offset result)
2011                    (ash sb!vm:vector-data-offset sb!vm:word-shift)))
2012          (end (+ start
2013                  (ceiling (* len sizebits)
2014                           sb!vm:byte-bits))))
2015     (read-sequence-or-die (descriptor-bytes result)
2016                           *fasl-file*
2017                           :start start
2018                           :end end)
2019     result))
2020
2021 (define-cold-fop (fop-single-float-vector)
2022   (let* ((len (read-arg 4))
2023          (result (allocate-vector-object *dynamic*
2024                                          sb!vm:word-bits
2025                                          len
2026                                          sb!vm:simple-array-single-float-type))
2027          (start (+ (descriptor-byte-offset result)
2028                    (ash sb!vm:vector-data-offset sb!vm:word-shift)))
2029          (end (+ start (* len sb!vm:word-bytes))))
2030     (read-sequence-or-die (descriptor-bytes result)
2031                           *fasl-file*
2032                           :start start
2033                           :end end)
2034     result))
2035
2036 (not-cold-fop fop-double-float-vector)
2037 #!+long-float (not-cold-fop fop-long-float-vector)
2038 (not-cold-fop fop-complex-single-float-vector)
2039 (not-cold-fop fop-complex-double-float-vector)
2040 #!+long-float (not-cold-fop fop-complex-long-float-vector)
2041
2042 (define-cold-fop (fop-array)
2043   (let* ((rank (read-arg 4))
2044          (data-vector (pop-stack))
2045          (result (allocate-boxed-object *dynamic*
2046                                         (+ sb!vm:array-dimensions-offset rank)
2047                                         sb!vm:other-pointer-type)))
2048     (write-memory result
2049                   (make-other-immediate-descriptor rank
2050                                                    sb!vm:simple-array-type))
2051     (write-wordindexed result sb!vm:array-fill-pointer-slot *nil-descriptor*)
2052     (write-wordindexed result sb!vm:array-data-slot data-vector)
2053     (write-wordindexed result sb!vm:array-displacement-slot *nil-descriptor*)
2054     (write-wordindexed result sb!vm:array-displaced-p-slot *nil-descriptor*)
2055     (let ((total-elements 1))
2056       (dotimes (axis rank)
2057         (let ((dim (pop-stack)))
2058           (unless (or (= (descriptor-lowtag dim) sb!vm:even-fixnum-type)
2059                       (= (descriptor-lowtag dim) sb!vm:odd-fixnum-type))
2060             (error "non-fixnum dimension? (~S)" dim))
2061           (setf total-elements
2062                 (* total-elements
2063                    (logior (ash (descriptor-high dim)
2064                                 (- descriptor-low-bits (1- sb!vm:lowtag-bits)))
2065                            (ash (descriptor-low dim)
2066                                 (- 1 sb!vm:lowtag-bits)))))
2067           (write-wordindexed result
2068                              (+ sb!vm:array-dimensions-offset axis)
2069                              dim)))
2070       (write-wordindexed result
2071                          sb!vm:array-elements-slot
2072                          (make-fixnum-descriptor total-elements)))
2073     result))
2074 \f
2075 ;;;; cold fops for loading numbers
2076
2077 (defmacro define-cold-number-fop (fop)
2078   `(define-cold-fop (,fop :nope)
2079      ;; Invoke the ordinary warm version of this fop to push the
2080      ;; number.
2081      (,fop)
2082      ;; Replace the warm fop result with the cold image of the warm
2083      ;; fop result.
2084      (with-fop-stack t
2085        (let ((number (pop-stack)))
2086          (number-to-core number)))))
2087
2088 (define-cold-number-fop fop-single-float)
2089 (define-cold-number-fop fop-double-float)
2090 (define-cold-number-fop fop-integer)
2091 (define-cold-number-fop fop-small-integer)
2092 (define-cold-number-fop fop-word-integer)
2093 (define-cold-number-fop fop-byte-integer)
2094 (define-cold-number-fop fop-complex-single-float)
2095 (define-cold-number-fop fop-complex-double-float)
2096
2097 #!+long-float
2098 (define-cold-fop (fop-long-float)
2099   (ecase sb!c:*backend-fasl-file-implementation*
2100     (:x86 ; 80 bit long-float format
2101      (prepare-for-fast-read-byte *fasl-file*
2102        (let* ((des (allocate-unboxed-object *dynamic* sb!vm:word-bits
2103                                             (1- sb!vm:long-float-size)
2104                                             sb!vm:long-float-type))
2105               (low-bits (make-random-descriptor (fast-read-u-integer 4)))
2106               (high-bits (make-random-descriptor (fast-read-u-integer 4)))
2107               (exp-bits (make-random-descriptor (fast-read-s-integer 2))))
2108          (done-with-fast-read-byte)
2109          (write-wordindexed des sb!vm:long-float-value-slot low-bits)
2110          (write-wordindexed des (1+ sb!vm:long-float-value-slot) high-bits)
2111          (write-wordindexed des (+ 2 sb!vm:long-float-value-slot) exp-bits)
2112          des)))
2113     ;; This was supported in CMU CL, but isn't currently supported in
2114     ;; SBCL.
2115     #+nil
2116     (#.sb!c:sparc-fasl-file-implementation ; 128 bit long-float format
2117      (prepare-for-fast-read-byte *fasl-file*
2118        (let* ((des (allocate-unboxed-object *dynamic* sb!vm:word-bits
2119                                             (1- sb!vm:long-float-size)
2120                                             sb!vm:long-float-type))
2121               (low-bits (make-random-descriptor (fast-read-u-integer 4)))
2122               (mid-bits (make-random-descriptor (fast-read-u-integer 4)))
2123               (high-bits (make-random-descriptor (fast-read-u-integer 4)))
2124               (exp-bits (make-random-descriptor (fast-read-s-integer 4))))
2125          (done-with-fast-read-byte)
2126          (write-wordindexed des sb!vm:long-float-value-slot exp-bits)
2127          (write-wordindexed des (1+ sb!vm:long-float-value-slot) high-bits)
2128          (write-wordindexed des (+ 2 sb!vm:long-float-value-slot) mid-bits)
2129          (write-wordindexed des (+ 3 sb!vm:long-float-value-slot) low-bits)
2130          des)))))
2131
2132 #!+long-float
2133 (define-cold-fop (fop-complex-long-float)
2134   (ecase sb!c:*backend-fasl-file-implementation*
2135     (:x86 ; 80 bit long-float format
2136      (prepare-for-fast-read-byte *fasl-file*
2137        (let* ((des (allocate-unboxed-object *dynamic* sb!vm:word-bits
2138                                             (1- sb!vm:complex-long-float-size)
2139                                             sb!vm:complex-long-float-type))
2140               (real-low-bits (make-random-descriptor (fast-read-u-integer 4)))
2141               (real-high-bits (make-random-descriptor (fast-read-u-integer 4)))
2142               (real-exp-bits (make-random-descriptor (fast-read-s-integer 2)))
2143               (imag-low-bits (make-random-descriptor (fast-read-u-integer 4)))
2144               (imag-high-bits (make-random-descriptor (fast-read-u-integer 4)))
2145               (imag-exp-bits (make-random-descriptor (fast-read-s-integer 2))))
2146          (done-with-fast-read-byte)
2147          (write-wordindexed des
2148                             sb!vm:complex-long-float-real-slot
2149                             real-low-bits)
2150          (write-wordindexed des
2151                             (1+ sb!vm:complex-long-float-real-slot)
2152                             real-high-bits)
2153          (write-wordindexed des
2154                             (+ 2 sb!vm:complex-long-float-real-slot)
2155                             real-exp-bits)
2156          (write-wordindexed des
2157                             sb!vm:complex-long-float-imag-slot
2158                             imag-low-bits)
2159          (write-wordindexed des
2160                             (1+ sb!vm:complex-long-float-imag-slot)
2161                             imag-high-bits)
2162          (write-wordindexed des
2163                             (+ 2 sb!vm:complex-long-float-imag-slot)
2164                             imag-exp-bits)
2165          des)))
2166     ;; This was supported in CMU CL, but isn't currently supported in SBCL.
2167     #+nil
2168     (#.sb!c:sparc-fasl-file-implementation ; 128 bit long-float format
2169      (prepare-for-fast-read-byte *fasl-file*
2170        (let* ((des (allocate-unboxed-object *dynamic* sb!vm:word-bits
2171                                             (1- sb!vm:complex-long-float-size)
2172                                             sb!vm:complex-long-float-type))
2173               (real-low-bits (make-random-descriptor (fast-read-u-integer 4)))
2174               (real-mid-bits (make-random-descriptor (fast-read-u-integer 4)))
2175               (real-high-bits (make-random-descriptor (fast-read-u-integer 4)))
2176               (real-exp-bits (make-random-descriptor (fast-read-s-integer 4)))
2177               (imag-low-bits (make-random-descriptor (fast-read-u-integer 4)))
2178               (imag-mid-bits (make-random-descriptor (fast-read-u-integer 4)))
2179               (imag-high-bits (make-random-descriptor (fast-read-u-integer 4)))
2180               (imag-exp-bits (make-random-descriptor (fast-read-s-integer 4))))
2181          (done-with-fast-read-byte)
2182          (write-wordindexed des
2183                             sb!vm:complex-long-float-real-slot
2184                             real-exp-bits)
2185          (write-wordindexed des
2186                             (1+ sb!vm:complex-long-float-real-slot)
2187                             real-high-bits)
2188          (write-wordindexed des
2189                             (+ 2 sb!vm:complex-long-float-real-slot)
2190                             real-mid-bits)
2191          (write-wordindexed des
2192                             (+ 3 sb!vm:complex-long-float-real-slot)
2193                             real-low-bits)
2194          (write-wordindexed des
2195                             sb!vm:complex-long-float-real-slot
2196                             imag-exp-bits)
2197          (write-wordindexed des
2198                             (1+ sb!vm:complex-long-float-real-slot)
2199                             imag-high-bits)
2200          (write-wordindexed des
2201                             (+ 2 sb!vm:complex-long-float-real-slot)
2202                             imag-mid-bits)
2203          (write-wordindexed des
2204                             (+ 3 sb!vm:complex-long-float-real-slot)
2205                             imag-low-bits)
2206          des)))))
2207
2208 (define-cold-fop (fop-ratio)
2209   (let ((den (pop-stack)))
2210     (number-pair-to-core (pop-stack) den sb!vm:ratio-type)))
2211
2212 (define-cold-fop (fop-complex)
2213   (let ((im (pop-stack)))
2214     (number-pair-to-core (pop-stack) im sb!vm:complex-type)))
2215 \f
2216 ;;;; cold fops for calling (or not calling)
2217
2218 (not-cold-fop fop-eval)
2219 (not-cold-fop fop-eval-for-effect)
2220
2221 (defvar *load-time-value-counter*)
2222
2223 (define-cold-fop (fop-funcall)
2224   (unless (= (read-arg 1) 0)
2225     (error "You can't FOP-FUNCALL arbitrary stuff in cold load."))
2226   (let ((counter *load-time-value-counter*))
2227     (cold-push (cold-cons
2228                 (cold-intern :load-time-value)
2229                 (cold-cons
2230                  (pop-stack)
2231                  (cold-cons
2232                   (number-to-core counter)
2233                   *nil-descriptor*)))
2234                *current-reversed-cold-toplevels*)
2235     (setf *load-time-value-counter* (1+ counter))
2236     (make-descriptor 0 0 nil counter)))
2237
2238 (defun finalize-load-time-value-noise ()
2239   (cold-set (cold-intern 'sb!impl::*!load-time-values*)
2240             (allocate-vector-object *dynamic*
2241                                     sb!vm:word-bits
2242                                     *load-time-value-counter*
2243                                     sb!vm:simple-vector-type)))
2244
2245 (define-cold-fop (fop-funcall-for-effect nil)
2246   (if (= (read-arg 1) 0)
2247       (cold-push (pop-stack)
2248                  *current-reversed-cold-toplevels*)
2249       (error "You can't FOP-FUNCALL arbitrary stuff in cold load.")))
2250 \f
2251 ;;;; cold fops for fixing up circularities
2252
2253 (define-cold-fop (fop-rplaca nil)
2254   (let ((obj (svref *current-fop-table* (read-arg 4)))
2255         (idx (read-arg 4)))
2256     (write-memory (cold-nthcdr idx obj) (pop-stack))))
2257
2258 (define-cold-fop (fop-rplacd nil)
2259   (let ((obj (svref *current-fop-table* (read-arg 4)))
2260         (idx (read-arg 4)))
2261     (write-wordindexed (cold-nthcdr idx obj) 1 (pop-stack))))
2262
2263 (define-cold-fop (fop-svset nil)
2264   (let ((obj (svref *current-fop-table* (read-arg 4)))
2265         (idx (read-arg 4)))
2266     (write-wordindexed obj
2267                    (+ idx
2268                       (ecase (descriptor-lowtag obj)
2269                         (#.sb!vm:instance-pointer-type 1)
2270                         (#.sb!vm:other-pointer-type 2)))
2271                    (pop-stack))))
2272
2273 (define-cold-fop (fop-structset nil)
2274   (let ((obj (svref *current-fop-table* (read-arg 4)))
2275         (idx (read-arg 4)))
2276     (write-wordindexed obj (1+ idx) (pop-stack))))
2277
2278 (define-cold-fop (fop-nthcdr t)
2279   (cold-nthcdr (read-arg 4) (pop-stack)))
2280
2281 (defun cold-nthcdr (index obj)
2282   (dotimes (i index)
2283     (setq obj (read-wordindexed obj 1)))
2284   obj)
2285 \f
2286 ;;;; cold fops for loading code objects and functions
2287
2288 (define-cold-fop (fop-fset nil)
2289   (let ((fn (pop-stack))
2290         (name (pop-stack)))
2291     (cold-fset name fn)))
2292
2293 (define-cold-fop (fop-fdefinition)
2294   (cold-fdefinition-object (pop-stack)))
2295
2296 (define-cold-fop (fop-sanctify-for-execution)
2297   (pop-stack))
2298
2299 (not-cold-fop fop-make-byte-compiled-function)
2300
2301 ;;; Setting this variable shows what code looks like before any
2302 ;;; fixups (or function headers) are applied.
2303 #!+sb-show (defvar *show-pre-fixup-code-p* nil)
2304
2305 ;;; FIXME: The logic here should be converted into a function
2306 ;;; COLD-CODE-FOP-GUTS (NCONST CODE-SIZE) called by DEFINE-COLD-FOP
2307 ;;; FOP-CODE and DEFINE-COLD-FOP FOP-SMALL-CODE, so that
2308 ;;; variable-capture nastiness like (LET ((NCONST ,NCONST) ..) ..)
2309 ;;; doesn't keep me awake at night.
2310 (defmacro define-cold-code-fop (name nconst code-size)
2311   `(define-cold-fop (,name)
2312      (let* ((nconst ,nconst)
2313             (code-size ,code-size)
2314             (raw-header-n-words (+ sb!vm:code-trace-table-offset-slot nconst))
2315             (header-n-words
2316              ;; Note: we round the number of constants up to ensure
2317              ;; that the code vector will be properly aligned.
2318              (round-up raw-header-n-words 2))
2319             (des (allocate-descriptor
2320                   ;; In the X86 with CGC, code can't be relocated, so
2321                   ;; we have to put it into static space. In all other
2322                   ;; configurations, code can go into dynamic space.
2323                   #!+(and x86 cgc) *static* ; KLUDGE: Why? -- WHN 19990907
2324                   #!-(and x86 cgc) *dynamic*
2325                   (+ (ash header-n-words sb!vm:word-shift) code-size)
2326                   sb!vm:other-pointer-type)))
2327        (write-memory des
2328                      (make-other-immediate-descriptor header-n-words
2329                                                       sb!vm:code-header-type))
2330        (write-wordindexed des
2331                           sb!vm:code-code-size-slot
2332                           (make-fixnum-descriptor
2333                            (ash (+ code-size (1- (ash 1 sb!vm:word-shift)))
2334                                 (- sb!vm:word-shift))))
2335        (write-wordindexed des sb!vm:code-entry-points-slot *nil-descriptor*)
2336        (write-wordindexed des sb!vm:code-debug-info-slot (pop-stack))
2337        (when (oddp raw-header-n-words)
2338          (write-wordindexed des
2339                             raw-header-n-words
2340                             (make-random-descriptor 0)))
2341        (do ((index (1- raw-header-n-words) (1- index)))
2342            ((< index sb!vm:code-trace-table-offset-slot))
2343          (write-wordindexed des index (pop-stack)))
2344        (let* ((start (+ (descriptor-byte-offset des)
2345                         (ash header-n-words sb!vm:word-shift)))
2346               (end (+ start code-size)))
2347          (read-sequence-or-die (descriptor-bytes des)
2348                                *fasl-file*
2349                                :start start
2350                                :end end)
2351          #!+sb-show
2352          (when *show-pre-fixup-code-p*
2353            (format *trace-output*
2354                    "~&/raw code from code-fop ~D ~D:~%"
2355                    nconst
2356                    code-size)
2357            (do ((i start (+ i sb!vm:word-bytes)))
2358                ((>= i end))
2359              (format *trace-output*
2360                      "/#X~8,'0x: #X~8,'0x~%"
2361                      (+ i (gspace-byte-address (descriptor-gspace des)))
2362                      (byte-vector-ref-32 (descriptor-bytes des) i)))))
2363        des)))
2364
2365 (define-cold-code-fop fop-code (read-arg 4) (read-arg 4))
2366
2367 (define-cold-code-fop fop-small-code (read-arg 1) (read-arg 2))
2368
2369 (clone-cold-fop (fop-alter-code nil)
2370                 (fop-byte-alter-code)
2371   (let ((slot (clone-arg))
2372         (value (pop-stack))
2373         (code (pop-stack)))
2374     (write-wordindexed code slot value)))
2375
2376 (define-cold-fop (fop-function-entry)
2377   (let* ((type (pop-stack))
2378          (arglist (pop-stack))
2379          (name (pop-stack))
2380          (code-object (pop-stack))
2381          (offset (calc-offset code-object (read-arg 4)))
2382          (fn (descriptor-beyond code-object
2383                                 offset
2384                                 sb!vm:function-pointer-type))
2385          (next (read-wordindexed code-object sb!vm:code-entry-points-slot)))
2386     (unless (zerop (logand offset sb!vm:lowtag-mask))
2387       ;; FIXME: This should probably become a fatal error.
2388       (warn "unaligned function entry: ~S at #X~X" name offset))
2389     (write-wordindexed code-object sb!vm:code-entry-points-slot fn)
2390     (write-memory fn
2391                   (make-other-immediate-descriptor (ash offset
2392                                                         (- sb!vm:word-shift))
2393                                                    sb!vm:function-header-type))
2394     (write-wordindexed fn
2395                        sb!vm:function-self-slot
2396                        ;; KLUDGE: Wiring decisions like this in at
2397                        ;; this level ("if it's an x86") instead of a
2398                        ;; higher level of abstraction ("if it has such
2399                        ;; and such relocation peculiarities (which
2400                        ;; happen to be confined to the x86)") is bad.
2401                        ;; It would be nice if the code were instead
2402                        ;; conditional on some more descriptive
2403                        ;; feature, :STICKY-CODE or
2404                        ;; :LOAD-GC-INTERACTION or something.
2405                        ;;
2406                        ;; FIXME: The X86 definition of the function
2407                        ;; self slot breaks everything object.tex says
2408                        ;; about it. (As far as I can tell, the X86
2409                        ;; definition makes it a pointer to the actual
2410                        ;; code instead of a pointer back to the object
2411                        ;; itself.) Ask on the mailing list whether
2412                        ;; this is documented somewhere, and if not,
2413                        ;; try to reverse engineer some documentation
2414                        ;; before release.
2415                        #!-x86
2416                        ;; a pointer back to the function object, as
2417                        ;; described in CMU CL
2418                        ;; src/docs/internals/object.tex
2419                        fn
2420                        #!+x86
2421                        ;; KLUDGE: a pointer to the actual code of the
2422                        ;; object, as described nowhere that I can find
2423                        ;; -- WHN 19990907
2424                        (make-random-descriptor
2425                         (+ (descriptor-bits fn)
2426                            (- (ash sb!vm:function-code-offset sb!vm:word-shift)
2427                               ;; FIXME: We should mask out the type
2428                               ;; bits, not assume we know what they
2429                               ;; are and subtract them out this way.
2430                               sb!vm:function-pointer-type))))
2431     (write-wordindexed fn sb!vm:function-next-slot next)
2432     (write-wordindexed fn sb!vm:function-name-slot name)
2433     (write-wordindexed fn sb!vm:function-arglist-slot arglist)
2434     (write-wordindexed fn sb!vm:function-type-slot type)
2435     fn))
2436
2437 (define-cold-fop (fop-foreign-fixup)
2438   (let* ((kind (pop-stack))
2439          (code-object (pop-stack))
2440          (len (read-arg 1))
2441          (sym (make-string len)))
2442     (read-string-as-bytes *fasl-file* sym)
2443     (let ((offset (read-arg 4))
2444           (value (lookup-foreign-symbol sym)))
2445       (do-cold-fixup code-object offset value kind))
2446     code-object))
2447
2448 (define-cold-fop (fop-assembler-code)
2449   (let* ((length (read-arg 4))
2450          (header-n-words
2451           ;; Note: we round the number of constants up to ensure that
2452           ;; the code vector will be properly aligned.
2453           (round-up sb!vm:code-constants-offset 2))
2454          (des (allocate-descriptor *read-only*
2455                                    (+ (ash header-n-words sb!vm:word-shift)
2456                                       length)
2457                                    sb!vm:other-pointer-type)))
2458     (write-memory des
2459                   (make-other-immediate-descriptor header-n-words
2460                                                    sb!vm:code-header-type))
2461     (write-wordindexed des
2462                        sb!vm:code-code-size-slot
2463                        (make-fixnum-descriptor
2464                         (ash (+ length (1- (ash 1 sb!vm:word-shift)))
2465                              (- sb!vm:word-shift))))
2466     (write-wordindexed des sb!vm:code-entry-points-slot *nil-descriptor*)
2467     (write-wordindexed des sb!vm:code-debug-info-slot *nil-descriptor*)
2468
2469     (let* ((start (+ (descriptor-byte-offset des)
2470                      (ash header-n-words sb!vm:word-shift)))
2471            (end (+ start length)))
2472       (read-sequence-or-die (descriptor-bytes des)
2473                             *fasl-file*
2474                             :start start
2475                             :end end))
2476     des))
2477
2478 (define-cold-fop (fop-assembler-routine)
2479   (let* ((routine (pop-stack))
2480          (des (pop-stack))
2481          (offset (calc-offset des (read-arg 4))))
2482     (record-cold-assembler-routine
2483      routine
2484      (+ (logandc2 (descriptor-bits des) sb!vm:lowtag-mask) offset))
2485     des))
2486
2487 (define-cold-fop (fop-assembler-fixup)
2488   (let* ((routine (pop-stack))
2489          (kind (pop-stack))
2490          (code-object (pop-stack))
2491          (offset (read-arg 4)))
2492     (record-cold-assembler-fixup routine code-object offset kind)
2493     code-object))
2494
2495 (define-cold-fop (fop-code-object-fixup)
2496   (let* ((kind (pop-stack))
2497          (code-object (pop-stack))
2498          (offset (read-arg 4))
2499          (value (descriptor-bits code-object)))
2500     (do-cold-fixup code-object offset value kind)
2501     code-object))
2502 \f
2503 ;;;; emitting C header file
2504
2505 (defun tail-comp (string tail)
2506   (and (>= (length string) (length tail))
2507        (string= string tail :start1 (- (length string) (length tail)))))
2508
2509 (defun head-comp (string head)
2510   (and (>= (length string) (length head))
2511        (string= string head :end1 (length head))))
2512
2513 (defun write-c-header ()
2514
2515   ;; writing beginning boilerplate
2516   (format t "/*~%")
2517   (dolist (line
2518            '("This is a machine-generated file. Do not edit it by hand."
2519              ""
2520              "This file contains low-level information about the"
2521              "internals of a particular version and configuration"
2522              "of SBCL. It is used by the C compiler to create a runtime"
2523              "support environment, an executable program in the host"
2524              "operating system's native format, which can then be used to"
2525              "load and run 'core' files, which are basically programs"
2526              "in SBCL's own format."))
2527     (format t " * ~A~%" line))
2528   (format t " */~%")
2529   (terpri)
2530   (format t "#ifndef _SBCL_H_~%#define _SBCL_H_~%")
2531   (terpri)
2532
2533   ;; writing miscellaneous constants
2534   (format t "#define SBCL_CORE_VERSION_INTEGER ~D~%" sbcl-core-version-integer)
2535   (format t
2536           "#define SBCL_VERSION_STRING ~S~%"
2537           (sb!xc:lisp-implementation-version))
2538   (format t "#define CORE_MAGIC 0x~X~%" core-magic)
2539   (terpri)
2540   ;; FIXME: Other things from core.h should be defined here too:
2541   ;; #define CORE_END 3840
2542   ;; #define CORE_NDIRECTORY 3861
2543   ;; #define CORE_VALIDATE 3845
2544   ;; #define CORE_VERSION 3860
2545   ;; #define CORE_MACHINE_STATE 3862
2546   ;; (Except that some of them are obsolete and should be deleted instead.)
2547   ;; also
2548   ;; #define DYNAMIC_SPACE_ID (1)
2549   ;; #define STATIC_SPACE_ID (2)
2550   ;; #define READ_ONLY_SPACE_ID (3)
2551
2552   ;; writing entire families of named constants from SB!VM
2553   (let ((constants nil))
2554     (do-external-symbols (symbol (find-package "SB!VM"))
2555       (when (constantp symbol)
2556         (let ((name (symbol-name symbol)))
2557           (labels (;; shared machinery
2558                    (record (string priority)
2559                      (push (list string
2560                                  priority
2561                                  (symbol-value symbol)
2562                                  (documentation symbol 'variable))
2563                            constants))
2564                    ;; machinery for old-style CMU CL Lisp-to-C naming
2565                    (record-with-munged-name (prefix string priority)
2566                      (record (concatenate
2567                               'simple-string
2568                               prefix
2569                               (delete #\- (string-capitalize string)))
2570                              priority))
2571                    (test-tail (tail prefix priority)
2572                      (when (tail-comp name tail)
2573                        (record-with-munged-name prefix
2574                                                 (subseq name 0
2575                                                         (- (length name)
2576                                                            (length tail)))
2577                                                 priority)))
2578                    (test-head (head prefix priority)
2579                      (when (head-comp name head)
2580                        (record-with-munged-name prefix
2581                                                 (subseq name (length head))
2582                                                 priority)))
2583                    ;; machinery for new-style SBCL Lisp-to-C naming
2584                    (record-with-translated-name (priority)
2585                      (record (substitute #\_ #\- name)
2586                              priority)))
2587             ;; This style of munging of names is used in the code
2588             ;; inherited from CMU CL.
2589             (test-tail "-TYPE" "type_" 0)
2590             (test-tail "-FLAG" "flag_" 1)
2591             (test-tail "-TRAP" "trap_" 2)
2592             (test-tail "-SUBTYPE" "subtype_" 3)
2593             (test-head "TRACE-TABLE-" "tracetab_" 4)
2594             (test-tail "-SC-NUMBER" "sc_" 5)
2595             ;; This simpler style of translation of names seems less
2596             ;; confusing, and is used for newer code.
2597             (when (some (lambda (suffix) (tail-comp name suffix))
2598                         #("-START" "-END"))
2599               (record-with-translated-name 6))))))
2600     (setf constants
2601           (sort constants
2602                 #'(lambda (const1 const2)
2603                     (if (= (second const1) (second const2))
2604                       (< (third const1) (third const2))
2605                       (< (second const1) (second const2))))))
2606     (let ((prev-priority (second (car constants))))
2607       (dolist (const constants)
2608         (destructuring-bind (name priority value doc) const
2609           (unless (= prev-priority priority)
2610             (terpri)
2611             (setf prev-priority priority))
2612           (format t "#define ~A " name)
2613           (format t 
2614                   ;; KLUDGE: As of sbcl-0.6.7.14, we're dumping two
2615                   ;; different kinds of values here, (1) small codes
2616                   ;; and (2) machine addresses. The small codes can be
2617                   ;; dumped as bare integer values. The large machine
2618                   ;; addresses might cause problems if they're large
2619                   ;; and represented as (signed) C integers, so we
2620                   ;; want to force them to be unsigned. We do that by
2621                   ;; wrapping them in the LISPOBJ macro. (We could do
2622                   ;; it with a bare "(unsigned)" cast, except that
2623                   ;; this header file is used not only in C files, but
2624                   ;; also in assembly files, which don't understand
2625                   ;; the cast syntax. The LISPOBJ macro goes away in
2626                   ;; assembly files, but that shouldn't matter because
2627                   ;; we don't do arithmetic on address constants in
2628                   ;; assembly files. See? It really is a kludge..) --
2629                   ;; WHN 2000-10-18
2630                   (let (;; cutoff for treatment as a small code
2631                         (cutoff (expt 2 16)))
2632                     (cond ((minusp value)
2633                            (error "stub: negative values unsupported"))
2634                           ((< value cutoff)
2635                            "~D")
2636                           (t
2637                            "LISPOBJ(~D)")))
2638                   value)
2639           (format t " /* 0x~X */~@[  /* ~A */~]~%" value doc))))
2640     (terpri))
2641
2642   ;; writing codes/strings for internal errors
2643   (format t "#define ERRORS { \\~%")
2644   ;; FIXME: Is this just DO-VECTOR?
2645   (let ((internal-errors sb!c:*backend-internal-errors*))
2646     (dotimes (i (length internal-errors))
2647       (format t "    ~S, /*~D*/ \\~%" (cdr (aref internal-errors i)) i)))
2648   (format t "    NULL \\~%}~%")
2649   (terpri)
2650
2651   ;; writing primitive object layouts
2652   (let ((structs (sort (copy-list sb!vm:*primitive-objects*) #'string<
2653                        :key #'(lambda (obj)
2654                                 (symbol-name
2655                                  (sb!vm:primitive-object-name obj))))))
2656     (format t "#ifndef LANGUAGE_ASSEMBLY~2%")
2657     (format t "#define LISPOBJ(x) ((lispobj)x)~2%")
2658     (dolist (obj structs)
2659       (format t
2660               "struct ~A {~%"
2661               (nsubstitute #\_ #\-
2662               (string-downcase (string (sb!vm:primitive-object-name obj)))))
2663       (when (sb!vm:primitive-object-header obj)
2664         (format t "    lispobj header;~%"))
2665       (dolist (slot (sb!vm:primitive-object-slots obj))
2666         (format t "    ~A ~A~@[[1]~];~%"
2667         (getf (sb!vm:slot-options slot) :c-type "lispobj")
2668         (nsubstitute #\_ #\-
2669                      (string-downcase (string (sb!vm:slot-name slot))))
2670         (sb!vm:slot-rest-p slot)))
2671       (format t "};~2%"))
2672     (format t "#else /* LANGUAGE_ASSEMBLY */~2%")
2673     (format t "#define LISPOBJ(thing) thing~2%")
2674     (dolist (obj structs)
2675       (let ((name (sb!vm:primitive-object-name obj))
2676       (lowtag (eval (sb!vm:primitive-object-lowtag obj))))
2677         (when lowtag
2678         (dolist (slot (sb!vm:primitive-object-slots obj))
2679           (format t "#define ~A_~A_OFFSET ~D~%"
2680                   (substitute #\_ #\- (string name))
2681                   (substitute #\_ #\- (string (sb!vm:slot-name slot)))
2682                   (- (* (sb!vm:slot-offset slot) sb!vm:word-bytes) lowtag)))
2683         (terpri))))
2684     (format t "#endif /* LANGUAGE_ASSEMBLY */~2%"))
2685
2686   ;; writing static symbol offsets
2687   (dolist (symbol (cons nil sb!vm:*static-symbols*))
2688     ;; FIXME: It would be nice to use longer names NIL and (particularly) T
2689     ;; in #define statements.
2690     (format t "#define ~A LISPOBJ(0x~X)~%"
2691             (nsubstitute #\_ #\-
2692                          (remove-if #'(lambda (char)
2693                                         (member char '(#\% #\* #\. #\!)))
2694                                     (symbol-name symbol)))
2695             (if *static*                ; if we ran GENESIS
2696               ;; We actually ran GENESIS, use the real value.
2697               (descriptor-bits (cold-intern symbol))
2698               ;; We didn't run GENESIS, so guess at the address.
2699               (+ sb!vm:static-space-start
2700                  sb!vm:word-bytes
2701                  sb!vm:other-pointer-type
2702                  (if symbol (sb!vm:static-symbol-offset symbol) 0)))))
2703
2704   ;; Voila.
2705   (format t "~%#endif~%"))
2706 \f
2707 ;;;; writing map file
2708
2709 ;;; Write a map file describing the cold load. Some of this
2710 ;;; information is subject to change due to relocating GC, but even so
2711 ;;; it can be very handy when attempting to troubleshoot the early
2712 ;;; stages of cold load.
2713 (defun write-map ()
2714   (let ((*print-pretty* nil)
2715         (*print-case* :upcase))
2716     (format t "assembler routines defined in core image:~2%")
2717     (dolist (routine (sort (copy-list *cold-assembler-routines*) #'<
2718                            :key #'cdr))
2719       (format t "#X~8,'0X: ~S~%" (cdr routine) (car routine)))
2720     (let ((funs nil)
2721           (undefs nil))
2722       (maphash #'(lambda (name fdefn)
2723                    (let ((fun (read-wordindexed fdefn
2724                                                 sb!vm:fdefn-function-slot)))
2725                      (if (= (descriptor-bits fun)
2726                             (descriptor-bits *nil-descriptor*))
2727                          (push name undefs)
2728                          (let ((addr (read-wordindexed fdefn
2729                                                        sb!vm:fdefn-raw-addr-slot)))
2730                            (push (cons name (descriptor-bits addr))
2731                                  funs)))))
2732                *cold-fdefn-objects*)
2733       (format t "~%~|~%initially defined functions:~2%")
2734       (dolist (info (sort funs #'< :key #'cdr))
2735         (format t "0x~8,'0X: ~S   #X~8,'0X~%" (cdr info) (car info)
2736                 (- (cdr info) #x17)))
2737       (format t
2738 "~%~|
2739 (a note about initially undefined function references: These functions
2740 are referred to by code which is installed by GENESIS, but they are not
2741 installed by GENESIS. This is not necessarily a problem; functions can
2742 be defined later, by cold init toplevel forms, or in files compiled and
2743 loaded at warm init, or elsewhere. As long as they are defined before
2744 they are called, everything should be OK. Things are also OK if the
2745 cross-compiler knew their inline definition and used that everywhere
2746 that they were called before the out-of-line definition is installed,
2747 as is fairly common for structure accessors.)
2748 initially undefined function references:~2%")
2749       (labels ((key (name)
2750                  (etypecase name
2751                    (symbol (symbol-name name))
2752                    ;; FIXME: should use standard SETF-function parsing logic
2753                    (list (key (second name))))))
2754         (dolist (name (sort undefs #'string< :key #'key))
2755           (format t "~S" name)
2756           ;; FIXME: This ACCESSOR-FOR stuff should go away when the
2757           ;; code has stabilized. (It's only here to help me
2758           ;; categorize the flood of undefined functions caused by
2759           ;; completely rewriting the bootstrap process. Hopefully any
2760           ;; future maintainers will mostly have small numbers of
2761           ;; undefined functions..)
2762           (let ((accessor-for (info :function :accessor-for name)))
2763             (when accessor-for
2764               (format t " (accessor for ~S)" accessor-for)))
2765           (format t "~%")))))
2766
2767   (format t "~%~|~%layout names:~2%")
2768   (collect ((stuff))
2769     (maphash #'(lambda (name gorp)
2770                  (declare (ignore name))
2771                  (stuff (cons (descriptor-bits (car gorp))
2772                               (cdr gorp))))
2773              *cold-layouts*)
2774     (dolist (x (sort (stuff) #'< :key #'car))
2775       (apply #'format t "~8,'0X: ~S[~D]~%~10T~S~%" x)))
2776
2777   (values))
2778 \f
2779 ;;;; writing core file
2780
2781 (defvar *core-file*)
2782 (defvar *data-page*)
2783
2784 ;;; KLUDGE: These numbers correspond to values in core.h. If they're
2785 ;;; documented anywhere, I haven't found it. (I haven't tried very
2786 ;;; hard yet.) -- WHN 19990826
2787 (defparameter version-entry-type-code 3860)
2788 (defparameter validate-entry-type-code 3845)
2789 (defparameter directory-entry-type-code 3841)
2790 (defparameter new-directory-entry-type-code 3861)
2791 (defparameter initial-function-entry-type-code 3863)
2792 (defparameter end-entry-type-code 3840)
2793
2794 (declaim (ftype (function (sb!vm:word) sb!vm:word) write-long))
2795 (defun write-long (num) ; FIXME: WRITE-WORD would be a better name.
2796   (ecase sb!c:*backend-byte-order*
2797     (:little-endian
2798      (dotimes (i 4)
2799        (write-byte (ldb (byte 8 (* i 8)) num) *core-file*)))
2800     (:big-endian
2801      (dotimes (i 4)
2802        (write-byte (ldb (byte 8 (* (- 3 i) 8)) num) *core-file*))))
2803   num)
2804
2805 (defun advance-to-page ()
2806   (force-output *core-file*)
2807   (file-position *core-file*
2808                  (round-up (file-position *core-file*)
2809                            sb!c:*backend-page-size*)))
2810
2811 (defun output-gspace (gspace)
2812   (force-output *core-file*)
2813   (let* ((posn (file-position *core-file*))
2814          (bytes (* (gspace-free-word-index gspace) sb!vm:word-bytes))
2815          (pages (ceiling bytes sb!c:*backend-page-size*))
2816          (total-bytes (* pages sb!c:*backend-page-size*)))
2817
2818     (file-position *core-file*
2819                    (* sb!c:*backend-page-size* (1+ *data-page*)))
2820     (format t
2821             "writing ~S byte~:P [~S page~:P] from ~S~%"
2822             total-bytes
2823             pages
2824             gspace)
2825     (force-output)
2826
2827     ;; Note: It is assumed that the GSPACE allocation routines always
2828     ;; allocate whole pages (of size *target-page-size*) and that any
2829     ;; empty gspace between the free pointer and the end of page will
2830     ;; be zero-filled. This will always be true under Mach on machines
2831     ;; where the page size is equal. (RT is 4K, PMAX is 4K, Sun 3 is
2832     ;; 8K).
2833     (write-sequence (gspace-bytes gspace) *core-file* :end total-bytes)
2834     (force-output *core-file*)
2835     (file-position *core-file* posn)
2836
2837     ;; Write part of a (new) directory entry which looks like this:
2838     ;;   GSPACE IDENTIFIER
2839     ;;   WORD COUNT
2840     ;;   DATA PAGE
2841     ;;   ADDRESS
2842     ;;   PAGE COUNT
2843     (write-long (gspace-identifier gspace))
2844     (write-long (gspace-free-word-index gspace))
2845     (write-long *data-page*)
2846     (multiple-value-bind (floor rem)
2847         (floor (gspace-byte-address gspace) sb!c:*backend-page-size*)
2848       ;; FIXME: Define an INSIST macro which does like ASSERT, but
2849       ;; less expensively (ERROR, not CERROR), and which reports
2850       ;; "internal error" on failure. Use it here and elsewhere in the
2851       ;; system.
2852       (assert (zerop rem))
2853       (write-long floor))
2854     (write-long pages)
2855
2856     (incf *data-page* pages)))
2857
2858 ;;; Create a core file created from the cold loaded image. (This is
2859 ;;; the "initial core file" because core files could be created later
2860 ;;; by executing SAVE-LISP in a running system, perhaps after we've
2861 ;;; added some functionality to the system.)
2862 (declaim (ftype (function (string)) write-initial-core-file))
2863 (defun write-initial-core-file (filename)
2864
2865   (let ((filenamestring (namestring filename))
2866         (*data-page* 0))
2867
2868     (format t
2869             "[building initial core file in ~S: ~%"
2870             filenamestring)
2871     (force-output)
2872
2873     (with-open-file (*core-file* filenamestring
2874                                  :direction :output
2875                                  :element-type '(unsigned-byte 8)
2876                                  :if-exists :rename-and-delete)
2877
2878       ;; Write the magic number.
2879       (write-long core-magic)
2880
2881       ;; Write the Version entry.
2882       (write-long version-entry-type-code)
2883       (write-long 3)
2884       (write-long sbcl-core-version-integer)
2885
2886       ;; Write the New Directory entry header.
2887       (write-long new-directory-entry-type-code)
2888       (write-long 17) ; length = (5 words/space) * 3 spaces + 2 for header.
2889
2890       (output-gspace *read-only*)
2891       (output-gspace *static*)
2892       (output-gspace *dynamic*)
2893
2894       ;; Write the initial function.
2895       (write-long initial-function-entry-type-code)
2896       (write-long 3)
2897       (let* ((cold-name (cold-intern '!cold-init))
2898              (cold-fdefn (cold-fdefinition-object cold-name))
2899              (initial-function (read-wordindexed cold-fdefn
2900                                                  sb!vm:fdefn-function-slot)))
2901         (format t
2902                 "~&/(DESCRIPTOR-BITS INITIAL-FUNCTION)=#X~X~%"
2903                 (descriptor-bits initial-function))
2904         (write-long (descriptor-bits initial-function)))
2905
2906       ;; Write the End entry.
2907       (write-long end-entry-type-code)
2908       (write-long 2)))
2909
2910   (format t "done]~%")
2911   (force-output)
2912   (/show "leaving WRITE-INITIAL-CORE-FILE")
2913   (values))
2914 \f
2915 ;;;; the actual GENESIS function
2916
2917 ;;; Read the FASL files in OBJECT-FILE-NAMES and produce a Lisp core,
2918 ;;; and/or information about a Lisp core, therefrom.
2919 ;;;
2920 ;;; input file arguments:
2921 ;;;   SYMBOL-TABLE-FILE-NAME names a UNIX-style .nm file *with* *any*
2922 ;;;     *tab* *characters* *converted* *to* *spaces*. (We push
2923 ;;;     responsibility for removing tabs out to the caller it's
2924 ;;;     trivial to remove them using UNIX command line tools like
2925 ;;;     sed, whereas it's a headache to do it portably in Lisp because
2926 ;;;     #\TAB is not a STANDARD-CHAR.) If this file is not supplied,
2927 ;;;     a core file cannot be built (but a C header file can be).
2928 ;;;
2929 ;;; output files arguments (any of which may be NIL to suppress output):
2930 ;;;   CORE-FILE-NAME gets a Lisp core.
2931 ;;;   C-HEADER-FILE-NAME gets a C header file, traditionally called
2932 ;;;     internals.h, which is used by the C compiler when constructing
2933 ;;;     the executable which will load the core.
2934 ;;;   MAP-FILE-NAME gets (?) a map file. (dunno about this -- WHN 19990815)
2935 ;;;
2936 ;;; other arguments:
2937 ;;;   BYTE-ORDER-SWAP-P controls whether GENESIS tries to swap bytes
2938 ;;;     in some places in the output. It's only appropriate when
2939 ;;;     cross-compiling from a machine with one byte order to a
2940 ;;;     machine with the opposite byte order, which is irrelevant in
2941 ;;;     current (19990816) SBCL, since only the X86 architecture is
2942 ;;;     supported. If you're trying to add support for more
2943 ;;;     architectures, see the comments on DEFVAR
2944 ;;;     *GENESIS-BYTE-ORDER-SWAP-P* for more information.
2945 ;;;
2946 ;;; FIXME: GENESIS doesn't belong in SB!VM. Perhaps in %KERNEL for now,
2947 ;;; perhaps eventually in SB-LD or SB-BOOT.
2948 (defun sb!vm:genesis (&key
2949                       object-file-names
2950                       symbol-table-file-name
2951                       core-file-name
2952                       map-file-name
2953                       c-header-file-name
2954                       byte-order-swap-p)
2955
2956   (when (and core-file-name
2957              (not symbol-table-file-name))
2958     (error "can't output a core file without symbol table file input"))
2959
2960   (format t
2961           "~&beginning GENESIS, ~A~%"
2962           (if core-file-name
2963             ;; Note: This output summarizing what we're doing is
2964             ;; somewhat telegraphic in style, not meant to imply that
2965             ;; we're not e.g. also creating a header file when we
2966             ;; create a core.
2967             (format nil "creating core ~S" core-file-name)
2968             (format nil "creating header ~S" c-header-file-name)))
2969
2970   (let* ((*cold-foreign-symbol-table* (make-hash-table :test 'equal)))
2971
2972     ;; Read symbol table, if any.
2973     (when symbol-table-file-name
2974       (load-foreign-symbol-table symbol-table-file-name))
2975
2976     ;; Now that we've successfully read our only input file (by
2977     ;; loading the symbol table, if any), it's a good time to ensure
2978     ;; that there'll be someplace for our output files to go when
2979     ;; we're done.
2980     (flet ((frob (filename)
2981              (when filename
2982                (ensure-directories-exist filename :verbose t))))
2983       (frob core-file-name)
2984       (frob map-file-name)
2985       (frob c-header-file-name))
2986
2987     ;; (This shouldn't matter in normal use, since GENESIS normally
2988     ;; only runs once in any given Lisp image, but it could reduce
2989     ;; confusion if we ever experiment with running, tweaking, and
2990     ;; rerunning genesis interactively.)
2991     (do-all-symbols (sym)
2992       (remprop sym 'cold-intern-info))
2993
2994     (let* ((*foreign-symbol-placeholder-value* (if core-file-name nil 0))
2995            (*load-time-value-counter* 0)
2996            (*genesis-byte-order-swap-p* byte-order-swap-p)
2997            (*cold-fdefn-objects* (make-hash-table :test 'equal))
2998            (*cold-symbols* (make-hash-table :test 'equal))
2999            (*cold-package-symbols* nil)
3000            (*read-only* (make-gspace :read-only
3001                                      read-only-space-id
3002                                      sb!vm:read-only-space-start))
3003            (*static*    (make-gspace :static
3004                                      static-space-id
3005                                      sb!vm:static-space-start))
3006            (*dynamic*   (make-gspace :dynamic
3007                                      dynamic-space-id
3008                                      sb!vm:dynamic-space-start))
3009            (*nil-descriptor* (make-nil-descriptor))
3010            (*current-reversed-cold-toplevels* *nil-descriptor*)
3011            (*unbound-marker* (make-other-immediate-descriptor
3012                               0
3013                               sb!vm:unbound-marker-type))
3014            *cold-assembler-fixups*
3015            *cold-assembler-routines*
3016            #!+x86 *load-time-code-fixups*)
3017
3018       ;; Prepare for cold load.
3019       (initialize-non-nil-symbols)
3020       (initialize-layouts)
3021       (initialize-static-fns)
3022
3023       ;; Initialize the *COLD-SYMBOLS* system with the information
3024       ;; from package-data-list.lisp-expr and
3025       ;; common-lisp-exports.lisp-expr.
3026       ;;
3027       ;; Why do things this way? Historically, the *COLD-SYMBOLS*
3028       ;; machinery was designed and implemented in CMU CL long before
3029       ;; I (WHN) ever heard of CMU CL. It dumped symbols and packages
3030       ;; iff they were used in the cold image. When I added the
3031       ;; package-data-list.lisp-expr mechanism, the idea was to
3032       ;; centralize all information about packages and exports. Thus,
3033       ;; it was the natural place for information even about packages
3034       ;; (such as SB!PCL and SB!WALKER) which aren't used much until
3035       ;; after cold load. This didn't quite match the CMU CL approach
3036       ;; of filling *COLD-SYMBOLS* with symbols which appear in the
3037       ;; cold image and then dumping only those symbols. By explicitly
3038       ;; putting all the symbols from package-data-list.lisp-expr and
3039       ;; from common-lisp-exports.lisp-expr into *COLD-SYMBOLS* here,
3040       ;; we feed our centralized symbol information into the old CMU
3041       ;; CL code without having to change the old CMU CL code too
3042       ;; much. (And the old CMU CL code is still useful for making
3043       ;; sure that the appropriate keywords and internal symbols end
3044       ;; up interned in the target Lisp, which is good, e.g. in order
3045       ;; to make keyword arguments work right and in order to make
3046       ;; BACKTRACEs into target Lisp system code be legible.)
3047       (dolist (exported-name
3048                (sb-cold:read-from-file "common-lisp-exports.lisp-expr"))
3049         (cold-intern (intern exported-name *cl-package*)))
3050       (dolist (pd (sb-cold:read-from-file "package-data-list.lisp-expr"))
3051         (declare (type sb-cold:package-data pd))
3052         (let ((package (find-package (sb-cold:package-data-name pd))))
3053           (labels (;; Call FN on every node of the TREE.
3054                    (mapc-on-tree (fn tree)
3055                                  (typecase tree
3056                                    (cons (mapc-on-tree fn (car tree))
3057                                          (mapc-on-tree fn (cdr tree)))
3058                                    (t (funcall fn tree)
3059                                       (values))))
3060                    ;; Make sure that information about the association
3061                    ;; between PACKAGE and the symbol named NAME gets
3062                    ;; recorded in the cold-intern system or (as a
3063                    ;; convenience when dealing with the tree structure
3064                    ;; allowed in the PACKAGE-DATA-EXPORTS slot) do
3065                    ;; nothing if NAME is NIL.
3066                    (chill (name)
3067                      (when name
3068                        (cold-intern (intern name package) package))))
3069             (mapc-on-tree #'chill (sb-cold:package-data-export pd))
3070             (mapc #'chill (sb-cold:package-data-reexport pd))
3071             (dolist (sublist (sb-cold:package-data-import-from pd))
3072               (destructuring-bind (package-name &rest symbol-names) sublist
3073                 (declare (ignore package-name))
3074                 (mapc #'chill symbol-names))))))
3075
3076       ;; Cold load.
3077       (dolist (file-name object-file-names)
3078         (write-line (namestring file-name))
3079         (cold-load file-name))
3080
3081       ;; Tidy up loose ends left by cold loading. ("Postpare from cold load?")
3082       (resolve-assembler-fixups)
3083       #!+x86 (output-load-time-code-fixups)
3084       (linkage-info-to-core)
3085       (finish-symbols)
3086       (/show "back from FINISH-SYMBOLS")
3087       (finalize-load-time-value-noise)
3088
3089       ;; Tell the target Lisp how much stuff we've allocated.
3090       (cold-set 'sb!vm:*read-only-space-free-pointer*
3091                 (allocate-descriptor *read-only* 0 sb!vm:even-fixnum-type))
3092       (cold-set 'sb!vm:*static-space-free-pointer*
3093                 (allocate-descriptor *static* 0 sb!vm:even-fixnum-type))
3094       (cold-set 'sb!vm:*initial-dynamic-space-free-pointer*
3095                 (allocate-descriptor *dynamic* 0 sb!vm:even-fixnum-type))
3096       (/show "done setting free pointers")
3097
3098       ;; Write results to files.
3099       ;;
3100       ;; FIXME: I dislike this approach of redefining
3101       ;; *STANDARD-OUTPUT* instead of putting the new stream in a
3102       ;; lexical variable, and it's annoying to have WRITE-MAP (to
3103       ;; *STANDARD-OUTPUT*) not be parallel to WRITE-INITIAL-CORE-FILE
3104       ;; (to a stream explicitly passed as an argument).
3105       (when map-file-name
3106         (with-open-file (*standard-output* map-file-name
3107                                            :direction :output
3108                                            :if-exists :supersede)
3109           (write-map)))
3110       (when c-header-file-name
3111         (with-open-file (*standard-output* c-header-file-name
3112                                            :direction :output
3113                                            :if-exists :supersede)
3114           (write-c-header)))
3115       (when core-file-name
3116         (write-initial-core-file core-file-name)))))