-(def-source-transform make-string (length &key
- (element-type ''base-char)
- (initial-element
- '#.*default-init-char-form*))
- (if (byte-compiling)
- (values nil t)
- `(make-array (the index ,length)
- :element-type ,element-type
- :initial-element ,initial-element)))
-
-(defstruct (specialized-array-element-type-properties
- (:conc-name saetp-)
- (:constructor !make-saetp (ctype
- initial-element-default
- n-bits
- typecode
- &key
- (n-pad-elements 0)))
- (:copier nil))
- ;; the element type, e.g. #<BUILT-IN-CLASS BASE-CHAR (sealed)> or
- ;; #<SB-KERNEL:NUMERIC-TYPE (UNSIGNED-BYTE 4)>
- (ctype (required-argument) :type ctype :read-only t)
- ;; what we get when the low-level vector-creation logic zeroes all
- ;; the bits (which also serves as the default value of MAKE-ARRAY's
- ;; :INITIAL-ELEMENT keyword)
- (initial-element-default (required-argument) :read-only t)
- ;; how many bits per element
- (n-bits (required-argument) :type index :read-only t)
- ;; the low-level type code
- (typecode (required-argument) :type index :read-only t)
- ;; the number of extra elements we use at the end of the array for
- ;; low level hackery (e.g., one element for arrays of BASE-CHAR,
- ;; which is used for a fixed #\NULL so that when we call out to C
- ;; we don't need to cons a new copy)
- (n-pad-elements (required-argument) :type index :read-only t))
-
-(defparameter *specialized-array-element-type-properties*
- (map 'simple-vector
- (lambda (args)
- (destructuring-bind (type-spec &rest rest) args
- (let ((ctype (specifier-type type-spec)))
- (apply #'!make-saetp ctype rest))))
- `((base-char ,(code-char 0) 8 ,sb!vm:simple-string-type
- ;; (SIMPLE-STRINGs are stored with an extra trailing
- ;; #\NULL for convenience in calling out to C.)
- :n-pad-elements 1)
- (single-float 0.0s0 32 ,sb!vm:simple-array-single-float-type)
- (double-float 0.0d0 64 ,sb!vm:simple-array-double-float-type)
- #!+long-float (long-float 0.0L0 #!+x86 96 #!+sparc 128
- ,sb!vm:simple-array-long-float-type)
- (bit 0 1 ,sb!vm:simple-bit-vector-type)
- ((unsigned-byte 2) 0 2 ,sb!vm:simple-array-unsigned-byte-2-type)
- ((unsigned-byte 4) 0 4 ,sb!vm:simple-array-unsigned-byte-4-type)
- ((unsigned-byte 8) 0 8 ,sb!vm:simple-array-unsigned-byte-8-type)
- ((unsigned-byte 16) 0 16 ,sb!vm:simple-array-unsigned-byte-16-type)
- ((unsigned-byte 32) 0 32 ,sb!vm:simple-array-unsigned-byte-32-type)
- ((signed-byte 8) 0 8 ,sb!vm:simple-array-signed-byte-8-type)
- ((signed-byte 16) 0 16 ,sb!vm:simple-array-signed-byte-16-type)
- ((signed-byte 30) 0 32 ,sb!vm:simple-array-signed-byte-30-type)
- ((signed-byte 32) 0 32 ,sb!vm:simple-array-signed-byte-32-type)
- ((complex single-float) #C(0.0s0 0.0s0) 64
- ,sb!vm:simple-array-complex-single-float-type)
- ((complex double-float) #C(0.0d0 0.0d0) 128
- ,sb!vm:simple-array-complex-double-float-type)
- #!+long-float ((complex long-float) #C(0.0L0 0.0L0)
- #!+x86 192 #!+sparc 256
- ,sb!vm:simple-array-complex-long-float-type)
- (t 0 32 ,sb!vm:simple-vector-type))))
+(deftransform make-string ((length &key
+ (element-type 'character)
+ (initial-element
+ #.*default-init-char-form*)))
+ `(the simple-string (make-array (the index length)
+ :element-type element-type
+ ,@(when initial-element
+ '(:initial-element initial-element)))))
+
+(deftransform make-array ((dims &key initial-element element-type
+ adjustable fill-pointer)
+ (t &rest *))
+ (when (null initial-element)
+ (give-up-ir1-transform))
+ (let* ((eltype (cond ((not element-type) t)
+ ((not (constant-lvar-p element-type))
+ (give-up-ir1-transform
+ "ELEMENT-TYPE is not constant."))
+ (t
+ (lvar-value element-type))))
+ (eltype-type (ir1-transform-specifier-type eltype))
+ (saetp (find-if (lambda (saetp)
+ (csubtypep eltype-type (sb!vm:saetp-ctype saetp)))
+ sb!vm:*specialized-array-element-type-properties*))
+ (creation-form `(make-array dims
+ :element-type ',(type-specifier (sb!vm:saetp-ctype saetp))
+ ,@(when fill-pointer
+ '(:fill-pointer fill-pointer))
+ ,@(when adjustable
+ '(:adjustable adjustable)))))
+
+ (unless saetp
+ (give-up-ir1-transform "ELEMENT-TYPE not found in *SAETP*: ~S" eltype))
+
+ (cond ((and (constant-lvar-p initial-element)
+ (eql (lvar-value initial-element)
+ (sb!vm:saetp-initial-element-default saetp)))
+ creation-form)
+ (t
+ ;; error checking for target, disabled on the host because
+ ;; (CTYPE-OF #\Null) is not possible.
+ #-sb-xc-host
+ (when (constant-lvar-p initial-element)
+ (let ((value (lvar-value initial-element)))
+ (cond
+ ((not (ctypep value (sb!vm:saetp-ctype saetp)))
+ ;; this case will cause an error at runtime, so we'd
+ ;; better WARN about it now.
+ (warn 'array-initial-element-mismatch
+ :format-control "~@<~S is not a ~S (which is the ~
+ ~S of ~S).~@:>"
+ :format-arguments
+ (list
+ value
+ (type-specifier (sb!vm:saetp-ctype saetp))
+ 'upgraded-array-element-type
+ eltype)))
+ ((not (ctypep value eltype-type))
+ ;; this case will not cause an error at runtime, but
+ ;; it's still worth STYLE-WARNing about.
+ (compiler-style-warn "~S is not a ~S."
+ value eltype)))))
+ `(let ((array ,creation-form))
+ (multiple-value-bind (vector)
+ (%data-vector-and-index array 0)
+ (fill vector initial-element))
+ array)))))