ccl
ccl copied to clipboard
bad regspec: NIL in X862-COMPILE
This function has a problematic COERCE on a dynamically dead branch (assuming P is always going to be NIL). This sort of thing shouldn't cause an failure at compile time, since this kind of bad COERCE could have been introduced by a macro that creates such dead code. At the very least, this is a bad way for the compiler to indicate there's a problem in the code.
(defun bug7 (p) (and p (dotimes (i 1) (- (coerce (progn i 0) nil)))))
==>
bad regspec: NIL [Condition of type SIMPLE-ERROR] [...] Backtrace: 0: (CCL::%HARD-REGSPEC-CLASS NIL) 1: (CCL::NODE-REG-P NIL) 2: (CCL::ENSURE-NODE-TARGET NIL) 3: (CCL::X862-%SINGLE-FLOAT-NEGATE #<DLL-HEADER #x3020023050ED> NIL NIL #<ACODE typed-form (SINGLE-FLOAT #<ACODE %single-float (#<ACODE progn ((#<ACODE typed-form #> #<ACODE fixnum #>))>)> T)>) 4: (CCL::X862-FORM #<DLL-HEADER #x3020023050ED> NIL NIL #<ACODE %single-float-negate (#<ACODE typed-form (SINGLE-FLOAT #<ACODE %single-float (#<ACODE progn (#)>)> T)>)>) 5: (CCL::X862-LOCAL-TAGBODY #<DLL-HEADER #x3020023050ED> NIL NIL ((#:G20106175 10 #(0 0 16) . T) (#:G20106176 11 #(0 0 16))) (#<ACODE local-go ((#:G20106176 11 #(0 0 16)))> ..)))))) 6: (CCL::X862-FORM #<DLL-HEADER #x3020023050ED> NIL NIL #<ACODE local-tagbody (((#:G20106175 10 #(0 0 16) . T) (#:G20106176 11 #(0 0 16))) ..))))) 7: (CCL::X862-PROGN #<DLL-HEADER #x3020023050ED> #<LREG 0 GPR [6]/LISP> 262143 (#<ACODE nil NIL>)) 8: (CCL::X862-FORM #<DLL-HEADER #x3020023050ED> #<LREG 0 GPR [6]/LISP> 262143 #<ACODE progn ((#<ACODE local-tagbody ((# #) ..)))) 9: (CCL::X862-FORM #<DLL-HEADER #x3020023050ED> #<LREG 0 GPR [6]/LISP> 262143 #<ACODE progn ((#<ACODE typed-form (BIT #<ACODE typed-form (BIT #<ACODE lexical-reference #>)> T)> ..))))))) 10: (CCL::X862-LET* #<DLL-HEADER #x3020023050ED> #<LREG 0 GPR [6]/LISP> 262143 (#<VAR I #x302002306A2D>) (#<ACODE fixnum (0)>) #<ACODE progn ((#<ACODE typed-form (BIT #<ACODE typed-form (BIT ..)))))))) 42.. 11: (CCL::X862-FORM #<DLL-HEADER #x3020023050ED> #<LREG 0 GPR [6]/LISP> 262143 #<ACODE let* ((#<VAR I #x302002306A2D>) (#<ACODE fixnum (0)>) ..)))) 12: (CCL::X862-IF #<DLL-HEADER #x3020023050ED> #<LREG 0 GPR [6]/LISP> 262143 #<ACODE lexical-reference (#<VAR P #x302002306EAD>)> #<ACODE let* ((#<VAR I #x302002306A2D>) (#<ACODE fixnum (0)>) ..))) #<ACOD.. 13: (CCL::X862-FORM #<DLL-HEADER #x3020023050ED> #<LREG 0 GPR [6]/LISP> 262143 #<ACODE if (#<ACODE lexical-reference (#<VAR P #x302002306EAD>)> ..)))))) 14: (CCL::X862-LAMBDA #<DLL-HEADER #x3020023050ED> #<LREG 0 GPR [6]/LISP> 262143 (#<VAR P #x302002306EAD>) NIL NIL NIL (NIL NIL) #<ACODE if (#<ACODE lexical-reference (#<VAR P #x302002306EAD>)> ..))))) 42.. 15: (CCL::X862-COMPILE #<CCL::AFUNC #x302002306F2D> NIL T) 16: (CCL::COMPILE-NAMED-FUNCTION (LAMBDA (P) (DECLARE (CCL::GLOBAL-FUNCTION-NAME BUG7)) (BLOCK BUG7 (AND P (DOTIMES # #)))) :NAME BUG7 :ENV #<CCL::LEXICAL-ENVIRONMENT #x30200230704D> :POLICY NIL :LOAD-TIM.. 17: (CCL::CHEAP-EVAL-FUNCTION BUG7 (LAMBDA (P) (DECLARE (CCL::GLOBAL-FUNCTION-NAME BUG7)) (BLOCK BUG7 (AND P (DOTIMES # #)))) #<CCL::LEXICAL-ENVIRONMENT #x30200230704D>) 18: (CCL::CHEAP-EVAL-IN-ENVIRONMENT (CCL::%DEFUN (CCL:NFUNCTION BUG7 (LAMBDA (P) (DECLARE #) (BLOCK BUG7 #))) 'NIL) #<CCL::LEXICAL-ENVIRONMENT #x30200230704D>) 19: ((:INTERNAL CCL::PROGN-IN-ENV CCL::CHEAP-EVAL-IN-ENVIRONMENT) ((CCL::%DEFUN (CCL:NFUNCTION BUG7 (LAMBDA # # #)) 'NIL) 'BUG7) NIL #<CCL::LEXICAL-ENVIRONMENT #x30200230704D>) 20: (CCL::CHEAP-EVAL (DEFUN BUG7 (P) (AND P (DOTIMES (I 1) (- #))))) 21: (SWANK::EVAL-REGION "(defun bug7 (p) (and p (dotimes (i 1) (- (coerce (progn i 0) nil)))))\n\n") 22: ((:INTERNAL SWANK-REPL::REPL-EVAL)) 23: (SWANK-REPL::TRACK-PACKAGE #<CCL:COMPILED-LEXICAL-CLOSURE (:INTERNAL SWANK-REPL::REPL-EVAL) #x30200230752F>) 24: (SWANK::CALL-WITH-RETRY-RESTART "Retry SLIME REPL evaluation request." #<CCL:COMPILED-LEXICAL-CLOSURE (:INTERNAL SWANK-REPL::REPL-EVAL) #x3020023075AF>) 25: (SWANK::CALL-WITH-BUFFER-SYNTAX NIL #<CCL:COMPILED-LEXICAL-CLOSURE (:INTERNAL SWANK-REPL::REPL-EVAL) #x3020023075EF>) 26: (SWANK-REPL::REPL-EVAL "(defun bug7 (p) (and p (dotimes (i 1) (- (coerce (progn i 0) nil)))))\n\n") 27: (CCL::CALL-CHECK-REGS SWANK-REPL:LISTENER-EVAL "(defun bug7 (p) (and p (dotimes (i 1) (- (coerce (progn i 0) nil)))))\n\n") 28: (CCL::CHEAP-EVAL (SWANK-REPL:LISTENER-EVAL "(defun bug7 (p) (and p (dotimes (i 1) (- (coerce (progn i 0) nil)))))\n\n")) 29: (SWANK:EVAL-FOR-EMACS (SWANK-REPL:LISTENER-EVAL "(defun bug7 (p) (and p (dotimes (i 1) (- (coerce (progn i 0) nil)))))\n\n") "CL-TEST" 476)
Because the empty type nil is a subtype of every type, non-careful code is losing here.
See the source of the coerce compiler macro and the coerce function.
(defun bug7 (p) (- (the single-float p)) 0) likewise triggers this issue, so it's not related to CCL's (admittedly somewhat screwy) handling of the NIL type. The problem appears when the result of %single-float-negate is discarded. I see two solutions here:
-
x862-%single-float-negateshould not callensuring-node-targetwith a nilvreg; the wholex862-copy-registercall is a no-op when the destination is nil anyway. -
ensure-node-targetshould be able to handle nil since this is a common value ofvregin the backend. I'm not sure how this change would affect other code;ensure-node-targethas many indirect callers and I can't say I fully understand the subtle distinction between reg, lreg, vreg, ... in the backends.:pushis not supported either for instance, butx862-%single-float-negatedoesn't support:pushvregs anyway.