t)
res))
-(define-fop (fop-single-float-vector 84)
+(defglobal **saetp-bits-per-length**
+ (let ((array (make-array 255 :element-type '(unsigned-byte 8)
+ :initial-element 255)))
+ (loop for saetp across sb!vm:*specialized-array-element-type-properties*
+ do
+ (setf (aref array (sb!vm:saetp-typecode saetp))
+ (sb!vm:saetp-n-bits saetp)))
+ array)
+ "255 means bad entry.")
+(declaim (type (simple-array (unsigned-byte 8) (255))
+ **saetp-bits-per-length**))
+
+(define-fop (fop-spec-vector 43)
(let* ((length (read-word-arg))
- (result (make-array length :element-type 'single-float)))
- (read-n-bytes *fasl-input-stream* result 0 (* length 4))
- result))
-
-(define-fop (fop-double-float-vector 85)
- (let* ((length (read-word-arg))
- (result (make-array length :element-type 'double-float)))
- (read-n-bytes *fasl-input-stream* result 0 (* length 8))
- result))
-
-(define-fop (fop-complex-single-float-vector 86)
- (let* ((length (read-word-arg))
- (result (make-array length :element-type '(complex single-float))))
- (read-n-bytes *fasl-input-stream* result 0 (* length 8))
- result))
-
-(define-fop (fop-complex-double-float-vector 87)
- (let* ((length (read-word-arg))
- (result (make-array length :element-type '(complex double-float))))
- (read-n-bytes *fasl-input-stream* result 0 (* length 16))
- result))
-
-;;; CMU CL comment:
-;;; *** NOT *** the FOP-INT-VECTOR as currently documented in rtguts.
-;;; Size must be a directly supported I-vector element size, with no
-;;; extra bits. This must be packed according to the local
-;;; byte-ordering, allowing us to directly read the bits.
-(define-fop (fop-int-vector 43)
- (let* ((len (read-word-arg))
- (size (read-byte-arg))
- (res (case size
- (0 (make-array len :element-type 'nil))
- (1 (make-array len :element-type 'bit))
- (2 (make-array len :element-type '(unsigned-byte 2)))
- (4 (make-array len :element-type '(unsigned-byte 4)))
- (7 (prog1 (make-array len :element-type '(unsigned-byte 7))
- (setf size 8)))
- (8 (make-array len :element-type '(unsigned-byte 8)))
- (15 (prog1 (make-array len :element-type '(unsigned-byte 15))
- (setf size 16)))
- (16 (make-array len :element-type '(unsigned-byte 16)))
- (31 (prog1 (make-array len :element-type '(unsigned-byte 31))
- (setf size 32)))
- (32 (make-array len :element-type '(unsigned-byte 32)))
- #!+#.(cl:if (cl:= 64 sb!vm:n-word-bits) '(and) '(or))
- (63 (prog1 (make-array len :element-type '(unsigned-byte 63))
- (setf size 64)))
- (64 (make-array len :element-type '(unsigned-byte 64)))
- (t (bug "losing i-vector element size: ~S" size)))))
- (declare (type index len))
- (read-n-bytes *fasl-input-stream*
- res
- 0
- (ceiling (the index (* size len)) sb!vm:n-byte-bits))
- res))
-
-;;; This is the same as FOP-INT-VECTOR, except this is for signed
-;;; SIMPLE-ARRAYs.
-(define-fop (fop-signed-int-vector 50)
- (let* ((len (read-word-arg))
- (size (read-byte-arg))
- (res (case size
- (8 (make-array len :element-type '(signed-byte 8)))
- (16 (make-array len :element-type '(signed-byte 16)))
- #!+#.(cl:if (cl:= 32 sb!vm:n-word-bits) '(and) '(or))
- (29 (prog1 (make-array len :element-type '(unsigned-byte 29))
- (setf size 32)))
- #!+#.(cl:if (cl:= 32 sb!vm:n-word-bits) '(and) '(or))
- (30 (prog1 (make-array len :element-type '(signed-byte 30))
- (setf size 32)))
- (32 (make-array len :element-type '(signed-byte 32)))
- #!+#.(cl:if (cl:= 64 sb!vm:n-word-bits) '(and) '(or))
- (60 (prog1 (make-array len :element-type '(unsigned-byte 60))
- (setf size 64)))
- #!+#.(cl:if (cl:= 64 sb!vm:n-word-bits) '(and) '(or))
- (61 (prog1 (make-array len :element-type '(signed-byte 61))
- (setf size 64)))
- #!+#.(cl:if (cl:= 64 sb!vm:n-word-bits) '(and) '(or))
- (64 (make-array len :element-type '(signed-byte 64)))
- (t (bug "losing si-vector element size: ~S" size)))))
- (declare (type index len))
- (read-n-bytes *fasl-input-stream*
- res
- 0
- (ceiling (the index (* size len)) sb!vm:n-byte-bits))
- res))
+ (widetag (read-byte-arg))
+ (bits-per-length (aref **saetp-bits-per-length** widetag))
+ (bytes (progn
+ (aver (< bits-per-length 255))
+ (ceiling (* length bits-per-length) sb!vm:n-byte-bits)))
+ (vector (allocate-vector widetag length (* bytes sb!vm:n-word-bytes))))
+ (declare (type index length))
+ (read-n-bytes *fasl-input-stream* vector 0 bytes)
+ vector))
(define-fop (fop-eval 53)
(if *skip-until*
(simple-vector
(dump-simple-vector simple-version file)
(eq-save-object x file))
- ((simple-array single-float (*))
- (dump-single-float-vector simple-version file)
- (eq-save-object x file))
- ((simple-array double-float (*))
- (dump-double-float-vector simple-version file)
- (eq-save-object x file))
- #!+long-float
- ((simple-array long-float (*))
- (dump-long-float-vector simple-version file)
- (eq-save-object x file))
- ((simple-array (complex single-float) (*))
- (dump-complex-single-float-vector simple-version file)
- (eq-save-object x file))
- ((simple-array (complex double-float) (*))
- (dump-complex-double-float-vector simple-version file)
- (eq-save-object x file))
- #!+long-float
- ((simple-array (complex long-float) (*))
- (dump-complex-long-float-vector simple-version file)
- (eq-save-object x file))
(t
- (dump-i-vector simple-version file)
+ (dump-specialized-vector simple-version file)
(eq-save-object x file)))))
;;; Dump a SIMPLE-VECTOR, handling any circularities.
;;; In the grand scheme of things I don't pretend to understand any
;;; more how this works, or indeed whether. But to write out specialized
-;;; vectors in the same format as fop-int-vector expects to read them
+;;; vectors in the same format as fop-spec-vector expects to read them
;;; we need to be target-endian. dump-integer-as-n-bytes always writes
;;; little-endian (which is correct for all other integers) so for a bigendian
;;; target we need to swap octets -- CSR, after DB
+#+sb-xc-host
+(defun dump-specialized-vector (vector file &key data-only)
+ (labels ((octet-swap (word bits)
+ "BITS must be a multiple of 8"
+ (do ((input word (ash input -8))
+ (output 0 (logior (ash output 8) (logand input #xff)))
+ (bits bits (- bits 8)))
+ ((<= bits 0) output)))
+ (dump-unsigned-vector (widetag bytes bits)
+ (unless data-only
+ (dump-fop 'fop-spec-vector file)
+ (dump-word (length vector) file)
+ (dump-byte widetag file))
+ (dovector (i vector)
+ (dump-integer-as-n-bytes
+ (ecase sb!c:*backend-byte-order*
+ (:little-endian i)
+ (:big-endian (octet-swap i bits)))
+ bytes file))))
+ (etypecase vector
+ ((simple-array (unsigned-byte 8) (*))
+ (dump-unsigned-vector sb!vm:simple-array-unsigned-byte-8-widetag 1 8))
+ ((simple-array (unsigned-byte 16) (*))
+ (dump-unsigned-vector sb!vm:simple-array-unsigned-byte-16-widetag 2 16))
+ ((simple-array (unsigned-byte 32) (*))
+ (dump-unsigned-vector sb!vm:simple-array-unsigned-byte-32-widetag 4 32)))))
-(defun octet-swap (word bits)
- "BITS must be a multiple of 8"
- (do ((input word (ash input -8))
- (output 0 (logior (ash output 8) (logand input #xff)))
- (bits bits (- bits 8)))
- ((<= bits 0) output)))
-
-(defun dump-i-vector (vec file &key data-only)
- (declare (type (simple-array * (*)) vec))
- (let ((len (length vec)))
- (labels ((dump-unsigned-vector (size bytes)
- (unless data-only
- (dump-fop 'fop-int-vector file)
- (dump-word len file)
- (dump-byte size file))
- ;; The case which is easy to handle in a portable way is when
- ;; the element size is a multiple of the output byte size, and
- ;; happily that's the only case we need to be portable. (The
- ;; cross-compiler has to output debug information (including
- ;; (SIMPLE-ARRAY (UNSIGNED-BYTE 8) *).) The other cases are only
- ;; needed in the target SBCL, so we let them be handled with
- ;; unportable bit bashing.
- (cond ((>= size 7) ; easy cases
- (multiple-value-bind (floor rem) (floor size 8)
- (aver (or (zerop rem) (= rem 7)))
- (when (= rem 7)
- (setq size (1+ size))
- (setq floor (1+ floor)))
- (dovector (i vec)
- (dump-integer-as-n-bytes
- (ecase sb!c:*backend-byte-order*
- (:little-endian i)
- (:big-endian (octet-swap i size)))
- floor file))))
- (t ; harder cases, not supported in cross-compiler
- (dump-raw-bytes vec bytes file))))
- (dump-signed-vector (size bytes)
- ;; Note: Dumping specialized signed vectors isn't
- ;; supported in the cross-compiler. (All cases here end
- ;; up trying to call DUMP-RAW-BYTES, which isn't
- ;; provided in the cross-compilation host, only on the
- ;; target machine.)
- (unless data-only
- (dump-fop 'fop-signed-int-vector file)
- (dump-word len file)
- (dump-byte size file))
- (dump-raw-bytes vec bytes file)))
- #+sb-xc-host
- (etypecase vec
- ((simple-array (unsigned-byte 8) (*))
- (dump-unsigned-vector 8 len))
- ((simple-array (unsigned-byte 16) (*))
- (dump-unsigned-vector 16 (* 2 len)))
- ((simple-array (unsigned-byte 32) (*))
- (dump-unsigned-vector 32 (* 4 len))))
- #-sb-xc-host
- (macrolet ((frob ()
- (labels ((bytes (saetp len)
- (let ((n-bits (sb!vm:saetp-n-bits saetp)))
- (if (zerop (rem n-bits 8))
- `(* ,len ,(/ n-bits 8))
- `(ceiling (* ,len ,n-bits) 8))))
- (size (ctype)
- (aver (numeric-type-p ctype))
- (let ((low (numeric-type-low ctype))
- (high (numeric-type-high ctype)))
- (cond
- ((zerop low) (integer-length high))
- ((minusp low)
- (aver (= (integer-length low) (integer-length high)))
- (1+ (integer-length low)))
- (t (bug "confused ctype: ~S" ctype)))))
- (clause (saetp)
- (let ((ctype (sb!vm:saetp-ctype saetp))
- (specifier (sb!vm:saetp-specifier saetp)))
- (aver (or (eql ctype *empty-type*)
- (numeric-type-p ctype)))
- (cond
- ((eql ctype *empty-type*)
- `((simple-array ,specifier (*))
- (dump-unsigned-vector 0 0)))
- ((minusp (numeric-type-low ctype))
- `((simple-array ,specifier (*))
- (dump-signed-vector ,(size ctype) ,(bytes saetp 'len))))
- (t
- (aver (zerop (numeric-type-low ctype)))
- `((simple-array ,specifier (*))
- (dump-unsigned-vector ,(size ctype) ,(bytes saetp 'len))))))))
- `(etypecase vec
- ,@(loop for x across sb!vm:*specialized-array-element-type-properties*
- when (csubtypep (sb!vm:saetp-ctype x) (specifier-type 'integer))
- collect (clause x))))))
- (frob)))))
+#-sb-xc-host
+(defun dump-specialized-vector (vector file &key data-only)
+ (declare (type (simple-array * (*)) vector))
+ (let* ((length (length vector))
+ (widetag (widetag-of vector))
+ (bits-per-length (aref **saetp-bits-per-length** widetag)))
+ (aver (< bits-per-length 255))
+ (unless data-only
+ (dump-fop 'fop-spec-vector file)
+ (dump-word length file)
+ (dump-byte widetag file))
+ (dump-raw-bytes vector (ceiling (* length bits-per-length) sb!vm:n-byte-bits) file)))
\f
;;; Dump characters and string-ish things.
;; These two dumps are only ones which contribute to our
;; TOTAL-LENGTH value.
(dump-segment code-segment code-length fasl-output)
- (dump-i-vector packed-trace-table fasl-output :data-only t)
+ (dump-specialized-vector packed-trace-table fasl-output :data-only t)
;; DUMP-FIXUPS does its own internal DUMP-FOPs: the bytes it
;; dumps aren't included in the TOTAL-LENGTH passed to our
(pop-stack)))
result))
-(define-cold-fop (fop-int-vector)
+(define-cold-fop (fop-spec-vector)
(let* ((len (read-word-arg))
- (sizebits (read-byte-arg))
- (type (case sizebits
- (0 sb!vm:simple-array-nil-widetag)
- (1 sb!vm:simple-bit-vector-widetag)
- (2 sb!vm:simple-array-unsigned-byte-2-widetag)
- (4 sb!vm:simple-array-unsigned-byte-4-widetag)
- (7 (prog1 sb!vm:simple-array-unsigned-byte-7-widetag
- (setf sizebits 8)))
- (8 sb!vm:simple-array-unsigned-byte-8-widetag)
- (15 (prog1 sb!vm:simple-array-unsigned-byte-15-widetag
- (setf sizebits 16)))
- (16 sb!vm:simple-array-unsigned-byte-16-widetag)
- (31 (prog1 sb!vm:simple-array-unsigned-byte-31-widetag
- (setf sizebits 32)))
- (32 sb!vm:simple-array-unsigned-byte-32-widetag)
- #!+#.(cl:if (cl:= 64 sb!vm:n-word-bits) '(and) '(or))
- (63 (prog1 sb!vm:simple-array-unsigned-byte-63-widetag
- (setf sizebits 64)))
- #!+#.(cl:if (cl:= 64 sb!vm:n-word-bits) '(and) '(or))
- (64 sb!vm:simple-array-unsigned-byte-64-widetag)
- (t (error "losing element size: ~W" sizebits))))
- (result (allocate-vector-object *dynamic* sizebits len type))
+ (type (read-byte-arg))
+ (sizebits (aref **saetp-bits-per-length** type))
+ (result (progn (aver (< sizebits 255))
+ (allocate-vector-object *dynamic* sizebits len type)))
(start (+ (descriptor-byte-offset result)
(ash sb!vm:vector-data-offset sb!vm:word-shift)))
(end (+ start
:end end)
result))
-(define-cold-fop (fop-single-float-vector)
- (let* ((len (read-word-arg))
- (result (allocate-vector-object
- *dynamic*
- sb!vm:n-word-bits
- len
- sb!vm:simple-array-single-float-widetag))
- (start (+ (descriptor-byte-offset result)
- (ash sb!vm:vector-data-offset sb!vm:word-shift)))
- (end (+ start (* len 4))))
- (read-bigvec-as-sequence-or-die (descriptor-bytes result)
- *fasl-input-stream*
- :start start
- :end end)
- result))
-
-(not-cold-fop fop-double-float-vector)
-#!+long-float (not-cold-fop fop-long-float-vector)
-(not-cold-fop fop-complex-single-float-vector)
-(not-cold-fop fop-complex-double-float-vector)
-#!+long-float (not-cold-fop fop-complex-long-float-vector)
-
(define-cold-fop (fop-array)
(let* ((rank (read-word-arg))
(data-vector (pop-stack))
(dump-word rank file)
(eq-save-object array file)))
\f
-;;;; various dump-a-number operations
-
-(defun dump-single-float-vector (vec file)
- (let ((length (length vec)))
- (dump-fop 'fop-single-float-vector file)
- (dump-word length file)
- (dump-raw-bytes vec (* length 4) file)))
-
-(defun dump-double-float-vector (vec file)
- (let ((length (length vec)))
- (dump-fop 'fop-double-float-vector file)
- (dump-word length file)
- (dump-raw-bytes vec (* length 8) file)))
-
-#!+long-float
-(defun dump-long-float-vector (vec file)
- (let ((length (length vec)))
- (dump-fop 'fop-long-float-vector file)
- (dump-word length file)
- (dump-raw-bytes vec
- (* length sb!vm:n-word-bytes #!+x86 3 #!+sparc 4)
- file)))
-
-(defun dump-complex-single-float-vector (vec file)
- (let ((length (length vec)))
- (dump-fop 'fop-complex-single-float-vector file)
- (dump-word length file)
- (dump-raw-bytes vec (* length 8) file)))
-
-(defun dump-complex-double-float-vector (vec file)
- (let ((length (length vec)))
- (dump-fop 'fop-complex-double-float-vector file)
- (dump-word length file)
- (dump-raw-bytes vec (* length 16) file)))
-
-#!+long-float
-(defun dump-complex-long-float-vector (vec file)
- (let ((length (length vec)))
- (dump-fop 'fop-complex-long-float-vector file)
- (dump-word length file)
- (dump-raw-bytes vec
- (* length sb!vm:n-word-bytes #!+x86 3 #!+sparc 4 2)
- file)))
-
#!+(and long-float x86)
(defun dump-long-float (float file)
(declare (long-float float))
;;; MAYBE-INFER-ITERATION-VAR-TYPE did not deal with types (REAL * (n)).
(let ((s (loop for x from (- pi) below (floor (* 2 pi)) by (/ pi 75) count t)))
(assert (= s 219)))
+
+(with-test (:name :specialized-array-dumping)
+ (macrolet
+ ((make-tests ()
+ `(progn
+ ,@(loop for saetp across
+ sb-vm:*specialized-array-element-type-properties*
+ for specifier = (sb-vm:saetp-specifier saetp)
+ for array = (make-array (if specifier 10 0)
+ :element-type specifier)
+ for make-array = `(make-array ,(if specifier 10 0)
+ :element-type ',specifier)
+ collect `(assert (and (equal (type-of ,array)
+ ',(type-of array))
+ (equalp ,array
+ ,make-array)))))))
+ (make-tests)))