;;; type is going to be the array upgraded element type.
(defun extract-upgraded-element-type (array)
(let ((type (continuation-type array)))
+ ;; Note that this IF mightn't be satisfied even if the runtime
+ ;; value is known to be a subtype of some specialized ARRAY, because
+ ;; we can have values declared e.g. (AND SIMPLE-VECTOR UNKNOWN-TYPE),
+ ;; which are represented in the compiler as INTERSECTION-TYPE, not
+ ;; array type.
(if (array-type-p type)
(array-type-specialized-element-type type)
- *universal-type*)))
+ ;; KLUDGE: there is no good answer here, but at least
+ ;; *wild-type* won't cause HAIRY-DATA-VECTOR-{REF,SET} to be
+ ;; erroneously optimized (see generic/vm-tran.lisp) -- CSR,
+ ;; 2002-08-21
+ *wild-type*)))
;;; The ``new-value'' for array setters must fit in the array, and the
;;; return type is going to be the same as the new-value for SETF
(defun assert-new-value-type (new-value array)
(let ((type (continuation-type array)))
(when (array-type-p type)
- (assert-continuation-type new-value (array-type-specialized-element-type type))))
+ (assert-continuation-type
+ new-value
+ (array-type-specialized-element-type type)
+ (lexenv-policy (node-lexenv (continuation-dest new-value))))))
(continuation-type new-value))
-;;; Return true if Arg is NIL, or is a constant-continuation whose
+(defun assert-array-complex (array)
+ (assert-continuation-type
+ array
+ (make-array-type :complexp t
+ :element-type *wild-type*)
+ (lexenv-policy (node-lexenv (continuation-dest array)))))
+
+;;; Return true if ARG is NIL, or is a constant-continuation whose
;;; value is NIL, false otherwise.
(defun unsupplied-or-nil (arg)
(declare (type (or continuation null) arg))
(defun assert-array-rank (array rank)
(assert-continuation-type
array
- (specifier-type `(array * ,(make-list rank :initial-element '*)))))
+ (specifier-type `(array * ,(make-list rank :initial-element '*)))
+ (lexenv-policy (node-lexenv (continuation-dest array)))))
(defoptimizer (array-in-bounds-p derive-type) ((array &rest indices))
(assert-array-rank array (length indices))
;; If the node continuation has a single use then assert its type.
(let ((cont (node-cont node)))
(when (= (length (find-uses cont)) 1)
- (assert-continuation-type cont (extract-upgraded-element-type array))))
+ (assert-continuation-type cont (extract-upgraded-element-type array)
+ (lexenv-policy (node-lexenv node)))))
(extract-upgraded-element-type array))
(defoptimizer (%aset derive-type) ((array &rest stuff))
(let ((simple (and (unsupplied-or-nil adjustable)
(unsupplied-or-nil displaced-to)
(unsupplied-or-nil fill-pointer))))
- (specifier-type
- `(,(if simple 'simple-array 'array)
- ,(cond ((not element-type) t)
- ((constant-continuation-p element-type)
- (continuation-value element-type))
- (t
- '*))
- ,(cond ((not simple)
- '*)
- ((constant-continuation-p dims)
- (let ((val (continuation-value dims)))
- (if (listp val) val (list val))))
- ((csubtypep (continuation-type dims)
- (specifier-type 'integer))
- '(*))
- (t
- '*))))))
+ (or (careful-specifier-type
+ `(,(if simple 'simple-array 'array)
+ ,(cond ((not element-type) t)
+ ((constant-continuation-p element-type)
+ (continuation-value element-type))
+ (t
+ '*))
+ ,(cond ((not simple)
+ '*)
+ ((constant-continuation-p dims)
+ (let ((val (continuation-value dims)))
+ (if (listp val) val (list val))))
+ ((csubtypep (continuation-type dims)
+ (specifier-type 'integer))
+ '(*))
+ (t
+ '*))))
+ (specifier-type 'array))))
+
+;;; Complex array operations should assert that their array argument
+;;; is complex. In SBCL, vectors with fill-pointers are complex.
+(defoptimizer (fill-pointer derive-type) ((vector))
+ (assert-array-complex vector))
+(defoptimizer (%set-fill-pointer derive-type) ((vector index))
+ (declare (ignorable index))
+ (assert-array-complex vector))
+
+(defoptimizer (vector-push derive-type) ((object vector))
+ (declare (ignorable object))
+ (assert-array-complex vector))
+(defoptimizer (vector-push-extend derive-type)
+ ((object vector &optional index))
+ (declare (ignorable object index))
+ (assert-array-complex vector))
+(defoptimizer (vector-pop derive-type) ((vector))
+ (assert-array-complex vector))
\f
;;;; constructors
"ELEMENT-TYPE is not constant."))
(t
(continuation-value element-type))))
- (eltype-type (specifier-type eltype))
+ (eltype-type (ir1-transform-specifier-type eltype))
(saetp (find-if (lambda (saetp)
(csubtypep eltype-type (saetp-ctype saetp)))
*specialized-array-element-type-properties*))
- (creation-form `(make-array dims :element-type ',eltype
- ,@(when fill-pointer
- '(:fill-pointer fill-pointer))
- ,@(when adjustable
- '(:adjustable adjustable)))))
+ (creation-form `(make-array dims
+ :element-type ',(type-specifier (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 ((or (null initial-element)
- (and (constant-continuation-p initial-element)
- (eql (continuation-value initial-element)
- (saetp-initial-element-default saetp))))
- (unless (csubtypep (ctype-of (saetp-initial-element-default saetp))
- eltype-type)
- ;; This situation arises e.g. in (MAKE-ARRAY 4
- ;; :ELEMENT-TYPE '(INTEGER 1 5)) ANSI's definition of
- ;; MAKE-ARRAY says "If INITIAL-ELEMENT is not supplied,
- ;; the consequences of later reading an uninitialized
- ;; element of new-array are undefined," so this could be
- ;; legal code as long as the user plans to write before
- ;; he reads, and if he doesn't we're free to do anything
- ;; we like. But in case the user doesn't know to write
- ;; elements before he reads elements (or to read manuals
- ;; before he writes code:-), we'll signal a STYLE-WARNING
- ;; in case he didn't realize this.
- (compiler-note "The default initial element ~S is not a ~S."
- (saetp-initial-element-default saetp)
- eltype))
+
+ (cond ((and (constant-continuation-p initial-element)
+ (eql (continuation-value initial-element)
+ (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-continuation-p initial-element)
+ (let ((value (continuation-value initial-element)))
+ (cond
+ ((not (csubtypep (ctype-of value)
+ (saetp-ctype saetp)))
+ ;; this case will cause an error at runtime, so we'd
+ ;; better WARN about it now.
+ (compiler-warn "~@<~S is not a ~S (which is the ~
+ UPGRADED-ARRAY-ELEMENT-TYPE of ~S).~@:>"
+ value
+ (type-specifier (saetp-ctype saetp))
+ eltype))
+ ((not (csubtypep (ctype-of 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)))))
-
+
;;; The integer type restriction on the length ensures that it will be
;;; a vector. The lack of :ADJUSTABLE, :FILL-POINTER, and
;;; :DISPLACED-TO keywords ensures that it will be simple; the lack of
(continuation-value length)
'*))
(result-type-spec `(simple-array ,eltype (,len)))
- (eltype-type (specifier-type eltype))
+ (eltype-type (ir1-transform-specifier-type eltype))
(saetp (find-if (lambda (saetp)
(csubtypep eltype-type (saetp-ctype saetp)))
*specialized-array-element-type-properties*)))
(unless saetp
(give-up-ir1-transform
"cannot open-code creation of ~S" result-type-spec))
-
+ #-sb-xc-host
+ (unless (csubtypep (ctype-of (saetp-initial-element-default saetp))
+ eltype-type)
+ ;; This situation arises e.g. in (MAKE-ARRAY 4 :ELEMENT-TYPE
+ ;; '(INTEGER 1 5)) ANSI's definition of MAKE-ARRAY says "If
+ ;; INITIAL-ELEMENT is not supplied, the consequences of later
+ ;; reading an uninitialized element of new-array are undefined,"
+ ;; so this could be legal code as long as the user plans to
+ ;; write before he reads, and if he doesn't we're free to do
+ ;; anything we like. But in case the user doesn't know to write
+ ;; elements before he reads elements (or to read manuals before
+ ;; he writes code:-), we'll signal a STYLE-WARNING in case he
+ ;; didn't realize this.
+ (compiler-style-warn "The default initial element ~S is not a ~S."
+ (saetp-initial-element-default saetp)
+ eltype))
(let* ((n-bits-per-element (saetp-n-bits saetp))
(typecode (saetp-typecode saetp))
(n-pad-elements (saetp-n-pad-elements saetp))
`(if (<= ,n-svalue ,n-end ,n-len)
;; success
(values ,n-array ,n-svalue ,n-end 0)
- (failed-%with-array-data ,n-array ,n-svalue ,n-evalue))))
+ (failed-%with-array-data ,n-array
+ ,n-svalue
+ ,n-evalue))))
(,(if force-inline '%with-array-data-macro '%with-array-data)
,n-array ,n-svalue ,n-evalue))
,@forms)))