;;; Return true if a constant LEAF is of a type which we can legally
;;; directly reference in code. Named constants with arbitrary pointer
;;; values cannot, since we must preserve EQLness.
+;;;
+;;; FIXME: why not? The values in a function's constant vector are
+;;; subject to being moved by the garbage collector. Having arbitrary
+;;; values in said vector doesn't seem like a problem.
(defun legal-immediate-constant-p (leaf)
(declare (type constant leaf))
(or (not (leaf-has-source-name-p leaf))
- (typecase (constant-value leaf)
- ((or number character) t)
- (symbol (symbol-package (constant-value leaf)))
- (t nil))))
+ ;; Specialized arrays are legal, too. KLUDGE: this would be
+ ;; *much* cleaner if SIMPLE-UNBOXED-ARRAY was defined on the host.
+ #.(loop for saetp across sb!vm:*specialized-array-element-type-properties*
+ unless (eq t (sb!vm:saetp-specifier saetp))
+ collect `((simple-array ,(sb!vm:saetp-specifier saetp) (*)) t) into cases
+ finally (return
+ `(typecase (constant-value leaf)
+ ((or number character) t)
+ (symbol (symbol-package (constant-value leaf)))
+ ,@cases
+ (t nil))))))
;;; If LVAR is used only by a REF to a leaf that can be delayed, then
;;; return the leaf, otherwise return NIL.
(cond
((lvar-delayed-leaf lvar)
(setf (ir2-lvar-kind info) :delayed))
- (t (setf (ir2-lvar-locs info)
- (list (make-normal-tn (ir2-lvar-primitive-type info)))))))
+ (t (let ((tn (make-normal-tn (ir2-lvar-primitive-type info))))
+ (setf (ir2-lvar-locs info) (list tn))
+ (when (lvar-dynamic-extent lvar)
+ (setf (ir2-lvar-stack-pointer info)
+ (make-stack-pointer-tn)))))))
(ltn-annotate-casts lvar)
(values))
;;; reference, otherwise we annotate for a single value.
(defun annotate-fun-lvar (lvar &optional (delay t))
(declare (type lvar lvar))
+ (aver (not (lvar-dynamic-extent lvar)))
(let* ((tn-ptype (primitive-type (lvar-type lvar)))
(info (make-ir2-lvar tn-ptype)))
(setf (lvar-info lvar) info)
(defun annotate-unknown-values-lvar (lvar)
(declare (type lvar lvar))
+ (aver (not (lvar-dynamic-extent lvar)))
(let ((2lvar (make-ir2-lvar nil)))
(setf (ir2-lvar-kind 2lvar) :unknown)
(setf (ir2-lvar-locs 2lvar) (make-unknown-values-locations))
;;; specified primitive TYPES.
(defun annotate-fixed-values-lvar (lvar types)
(declare (type lvar lvar) (list types))
- (let ((res (make-ir2-lvar nil)))
- (setf (ir2-lvar-locs res) (mapcar #'make-normal-tn types))
- (setf (lvar-info lvar) res))
+ (let ((info (make-ir2-lvar nil)))
+ (setf (ir2-lvar-locs info) (mapcar #'make-normal-tn types))
+ (setf (lvar-info lvar) info)
+ (when (lvar-dynamic-extent lvar)
+ (aver (proper-list-of-length-p types 1))
+ (setf (ir2-lvar-stack-pointer info)
+ (make-stack-pointer-tn))))
(ltn-annotate-casts lvar)
(values))
\f
ltn-policy ; a hack to effectively (DECLARE (IGNORE LTN-POLICY))
(setf (basic-combination-info node) :funny)
(setf (node-tail-p node) nil))
+
+;;; Make sure that arguments of magic functions are not annotated.
+;;; (Otherwise the compiler may dump its internal structures as
+;;; constants :-()
+(defoptimizer (%pop-values ltn-annotate) ((%lvar) node ltn-policy)
+ %lvar node ltn-policy)
+(defoptimizer (%nip-values ltn-annotate) ((last-nipped last-preserved
+ &rest moved)
+ node ltn-policy)
+ last-nipped last-preserved moved node ltn-policy)
+
\f
;;;; known call annotation
(when (losers)
(collect ((messages)
- (count 0 +))
+ (notes 0 +))
(flet ((lose1 (string &rest stuff)
(messages string)
(messages stuff)))
(dolist (loser (losers))
(when (and *efficiency-note-limit*
- (>= (count) *efficiency-note-limit*))
+ (>= (notes) *efficiency-note-limit*))
(lose1 "etc.")
(return))
(let* ((type (template-type loser))
(t
(aver (ltn-policy-safe-p ltn-policy))
(lose1 "can't trust output type assertion under safe policy")))
- (count 1))))
+ (notes 1))))
(let ((*compiler-error-context* call))
(compiler-notify "~{~?~^~&~6T~}"
(when (and (cast-type-check cast)
(not (node-lvar cast)))
;; FIXME
- (bug "IR2 type checking of unused values in not implemented.")
+ (bug "IR2 type checking of unused values is not implemented.")
)
(values))