From: Juho Snellman Date: Wed, 18 May 2005 02:22:48 +0000 (+0000) Subject: 0.9.0.37: X-Git-Url: http://repo.macrolet.net/gitweb/?a=commitdiff_plain;h=eaa8a506790bb6ed627da617247bfd13802eb365;p=sbcl.git 0.9.0.37: * Merge sbcl-devel "Unneeded REX prefixes on x86-64" (Lutz Euler, 2005-05-17) * Merge sbcl-devel " x86-64 fp exceptions" (James Knight, 2005-05-17) * Add "--userinit /dev/null --sysinit /dev/null" to the default SBCL_XC_HOST. * Clean up some stale x86 code (mostly floating point related) in the x86-64 port. --- diff --git a/BUGS b/BUGS index df38981..b8848f9 100644 --- a/BUGS +++ b/BUGS @@ -2045,11 +2045,6 @@ WORKAROUND: arrange_return_to_lisp_function(), but this looked hard to do in general without suffering from memory leaks. -378: floating-point exceptions not signalled on x86-64 - Floating point traps are currently not enabled on the x86-64 port. - This is true for at least overflow detection (as tested in - float.pure.lisp) and divide-by-zero. - 379: TRACE :ENCAPSULATE NIL broken on ppc/darwin See commented-out test-case in debug.impure.lisp. diff --git a/INSTALL b/INSTALL index f5d7e71..684aaf2 100644 --- a/INSTALL +++ b/INSTALL @@ -187,6 +187,10 @@ INSTALLING SBCL * Check that the host lisp you're building with is known to work as an SBCL build host, and the your OS is supported. + + * Try to do a build without loading any initialization files + for the cross-compilation host (for example + "sh make.sh 'sbcl --userinit /dev/null --sysinit /dev/null'"). * Some GCC versions are known to have bugs that affect SBCL compilation: if the error you're encountering seems related to diff --git a/NEWS b/NEWS index a7469ab..7d695ae 100644 --- a/NEWS +++ b/NEWS @@ -12,8 +12,12 @@ changes in sbcl-0.9.1 relative to sbcl-0.9.0: or more runtime options were provided to the sbcl binary. * compiled code is not steppable if COMPILATION-SPEED >= DEBUG. * contrib improvement: implement SB-POSIX:MKSTEMP (Yannick Gingras) - * optimization: There's now a fast-path for fixnum arguments in the + * optimization: there's now a fast-path for fixnum arguments in the generic subtraction routines on x86/x86-64. (Thanks to Lutz Euler) + * optimization: the code generated on x86-64 is more compact thanks + to not outputting unneccessary prefix bytes. (Thanks to Lutz Euler) + * bug fix: floating-point exception handling now works on x86-64. + (Thanks to James Knight) * fixed some bugs revealed by Paul Dietz' test suite: ** the type-error signalled from WARN has a filled-in DATUM slot. ** the type-error required when a stream is not associated with diff --git a/make.sh b/make.sh index 2a9a9b6..6d66d63 100755 --- a/make.sh +++ b/make.sh @@ -58,7 +58,7 @@ export LANG build_started=`date` echo "//starting build: $build_started" -SBCL_XC_HOST="${1:-sbcl --disable-debugger}" +SBCL_XC_HOST="${1:-sbcl --disable-debugger --userinit /dev/null --sysinit /dev/null}" export SBCL_XC_HOST echo //SBCL_XC_HOST=\"$SBCL_XC_HOST\" diff --git a/src/code/x86-64-vm.lisp b/src/code/x86-64-vm.lisp index f6fa3d3..a9698db 100644 --- a/src/code/x86-64-vm.lisp +++ b/src/code/x86-64-vm.lisp @@ -261,10 +261,15 @@ ;;; Given a signal context, return the floating point modes word in ;;; the same format as returned by FLOATING-POINT-MODES. +#!-linux (defun context-floating-point-modes (context) (declare (ignore context)) ; stub! (warn "stub CONTEXT-FLOATING-POINT-MODES") 0) +#!+linux +(define-alien-routine ("os_context_fp_control" context-floating-point-modes) + (sb!alien:unsigned 32) + (context (* os-context-t))) ;;;; INTERNAL-ERROR-ARGS @@ -302,38 +307,6 @@ (sc-offsets sc-offset))) (values error-number (sc-offsets))))))) -;;; This is used in error.lisp to insure that floating-point exceptions -;;; are properly trapped. The compiler translates this to a VOP. -(defun float-wait () - (float-wait)) - -;;; float constants -;;; -;;; These are used by the FP MOVE-FROM-{SINGLE|DOUBLE} VOPs rather -;;; than the i387 load constant instructions to avoid consing in some -;;; cases. Note these are initialized by GENESIS as they are needed -;;; early. -(defvar *fp-constant-0f0*) -(defvar *fp-constant-1f0*) -(defvar *fp-constant-0d0*) -(defvar *fp-constant-1d0*) -;;; the long-float constants -(defvar *fp-constant-0l0*) -(defvar *fp-constant-1l0*) -(defvar *fp-constant-pi*) -(defvar *fp-constant-l2t*) -(defvar *fp-constant-l2e*) -(defvar *fp-constant-lg2*) -(defvar *fp-constant-ln2*) ;;; the current alien stack pointer; saved/restored for non-local exits (defvar *alien-stack*) - -;;; Support for the MT19937 random number generator. The update -;;; function is implemented as an assembly routine. This definition is -;;; transformed to a call to the assembly routine allowing its use in -;;; interpreted code. -#+nil -(defun random-mt19937 (state) - (declare (type (simple-array (unsigned-byte 32) (627)) state)) - (random-mt19937 state)) diff --git a/src/compiler/x86-64/float.lisp b/src/compiler/x86-64/float.lisp index f6de9ba..8c00995 100644 --- a/src/compiler/x86-64/float.lisp +++ b/src/compiler/x86-64/float.lisp @@ -39,22 +39,6 @@ (defun ea-for-df-stack (tn) (ea-for-xf-stack tn :double))) -;;; Telling the FPU to wait is required in order to make signals occur -;;; at the expected place, but naturally slows things down. -;;; -;;; NODE is the node whose compilation policy controls the decision -;;; whether to just blast through carelessly or carefully emit wait -;;; instructions and whatnot. -;;; -;;; NOTE-NEXT-INSTRUCTION, if supplied, is to be passed to -;;; #'NOTE-NEXT-INSTRUCTION. -(defun maybe-fp-wait (node &optional note-next-instruction) - (when (policy node (or (= debug 3) (> safety speed)))) - (when note-next-instruction - (note-next-instruction note-next-instruction :internal-error)) - #+nil - (inst wait)) - ;;; complex float stack EAs (macrolet ((ea-for-cxf-stack (tn kind slot &optional base) (declare (ignore kind)) @@ -228,20 +212,6 @@ (define-move-vop move-from-double :move (double-reg) (descriptor-reg)) -#+nil -(define-vop (move-from-fp-constant) - (:args (x :scs (fp-constant))) - (:results (y :scs (descriptor-reg))) - (:generator 2 - (ecase (sb!c::constant-value (sb!c::tn-leaf x)) - (0f0 (load-symbol-value y *fp-constant-0f0*)) - (1f0 (load-symbol-value y *fp-constant-1f0*)) - (0d0 (load-symbol-value y *fp-constant-0d0*)) - (1d0 (load-symbol-value y *fp-constant-1d0*))))) -#+nil -(define-move-vop move-from-fp-constant :move - (fp-constant) (descriptor-reg)) - ;;; Move from a descriptor to a float register. (define-vop (move-to-single) (:args (x :scs (descriptor-reg) :target tmp)) @@ -629,23 +599,6 @@ (frob %single-float/signed %single-float cvtsi2ss single-reg single-float) (frob %double-float/signed %double-float cvtsi2sd double-reg double-float)) -#+nil -(macrolet ((frob (name translate inst to-sc to-type) - `(define-vop (,name) - (:args (x :scs (unsigned-reg))) - (:results (y :scs (,to-sc))) - (:arg-types unsigned-num) - (:result-types ,to-type) - (:policy :fast-safe) - (:note "inline float coercion") - (:translate ,translate) - (:vop-var vop) - (:save-p :compute-only) - (:generator 6 - (inst ,inst y x))))) - (frob %single-float/unsigned %single-float cvtsi2ss single-reg single-float) - (frob %double-float/unsigned %double-float cvtsi2sd double-reg double-float)) - (macrolet ((frob (name translate inst from-sc from-type to-sc to-type) `(define-vop (,name) (:args (x :scs (,from-sc) :target y)) @@ -693,50 +646,6 @@ (frob %unary-round cvtss2si single-reg single-float t) (frob %unary-round cvtsd2si double-reg double-float t)) -#+nil ;; will we need this? -(macrolet ((frob (trans from-sc from-type round-p) - `(define-vop (,(symbolicate trans "/" from-type "=>UNSIGNED")) - (:args (x :scs (,from-sc) :target fr0)) - (:temporary (:sc double-reg :offset fr0-offset - :from :argument :to :result) fr0) - ,@(unless round-p - '((:temporary (:sc unsigned-stack) stack-temp) - (:temporary (:sc unsigned-stack) scw) - (:temporary (:sc any-reg) rcw))) - (:results (y :scs (unsigned-reg))) - (:arg-types ,from-type) - (:result-types unsigned-num) - (:translate ,trans) - (:policy :fast-safe) - (:note "inline float truncate") - (:vop-var vop) - (:save-p :compute-only) - (:generator 5 - ,@(unless round-p - '((note-this-location vop :internal-error) - ;; Catch any pending FPE exceptions. - (inst wait))) - ;; Normal mode (for now) is "round to best". - (unless (zerop (tn-offset x)) - (copy-fp-reg-to-fr0 x)) - ,@(unless round-p - '((inst fnstcw scw) ; save current control word - (move rcw scw) ; into 16-bit register - (inst or rcw (ash #b11 10)) ; CHOP - (move stack-temp rcw) - (inst fldcw stack-temp))) - (inst sub rsp-tn 8) - (inst fistpl (make-ea :dword :base rsp-tn)) - (inst pop y) - (inst fld fr0) ; copy fr0 to at least restore stack. - (inst add rsp-tn 8) - ,@(unless round-p - '((inst fldcw scw))))))) - (frob %unary-truncate single-reg single-float nil) - (frob %unary-truncate double-reg double-float nil) - (frob %unary-round single-reg single-float t) - (frob %unary-round double-reg double-float t)) - (define-vop (make-single-float) (:args (bits :scs (signed-reg) :target res :load-if (not (or (and (sc-is bits signed-stack) @@ -745,7 +654,6 @@ (sc-is res single-stack) (location= bits res)))))) (:results (res :scs (single-reg single-stack))) - ; (:temporary (:sc signed-stack) stack-temp) (:arg-types signed-num) (:result-types single-float) (:translate make-single-float) diff --git a/src/compiler/x86-64/insts.lisp b/src/compiler/x86-64/insts.lisp index f6c36aa..23b3de5 100644 --- a/src/compiler/x86-64/insts.lisp +++ b/src/compiler/x86-64/insts.lisp @@ -43,6 +43,8 @@ (defparameter *byte-reg-names* #(al cl dl bl spl bpl sil dil r8b r9b r10b r11b r12b r13b r14b r15b)) +(defparameter *high-byte-reg-names* + #(ah ch dh bh)) (defparameter *word-reg-names* #(ax cx dx bx sp bp si di r8w r9w r10w r11w r12w r13w r14w r15w)) (defparameter *dword-reg-names* @@ -88,16 +90,24 @@ :word :qword)) +;;; Print to STREAM the name of the general purpose register encoded by +;;; VALUE and of size WIDTH. For robustness, the high byte registers +;;; (AH, BH, CH, DH) are correctly detected, too, although the compiler +;;; does not use them. (defun print-reg-with-width (value width stream dstate) (declare (type full-reg value) (type stream stream) - (ignore dstate)) - (princ (aref (ecase width - (:byte *byte-reg-names*) - (:word *word-reg-names*) - (:dword *dword-reg-names*) - (:qword *qword-reg-names*)) - value) + (type sb!disassem:disassem-state dstate)) + (princ (if (and (eq width :byte) + (<= 4 value 7) + (not (sb!disassem:dstate-get-inst-prop dstate 'rex))) + (aref *high-byte-reg-names* (- value 4)) + (aref (ecase width + (:byte *byte-reg-names*) + (:word *word-reg-names*) + (:dword *dword-reg-names*) + (:qword *qword-reg-names*)) + value)) stream) ;; XXX plus should do some source-var notes ) @@ -1005,7 +1015,7 @@ (defstruct (ea (:constructor make-ea (size &key base index scale disp)) (:copier nil)) - ;; note that we can represent an EA qith a QWORD size, but EMIT-EA + ;; note that we can represent an EA with a QWORD size, but EMIT-EA ;; can't actually emit it on its own: caller also needs to emit REX ;; prefix (size nil :type (member :byte :word :dword :qword)) @@ -1236,7 +1246,37 @@ (eq size +default-operand-size+)) (emit-byte segment +operand-size-prefix-byte+))) +;;; A REX prefix must be emitted if at least one of the following +;;; conditions is true: +;; 1. The operand size is :QWORD and the default operand size of the +;; instruction is not :QWORD. +;;; 2. The instruction references an extended register. +;;; 3. The instruction references one of the byte registers SIL, DIL, +;;; SPL or BPL. + +;;; Emit a REX prefix if necessary. OPERAND-SIZE is used to determine +;;; whether to set REX.W. Callers pass it explicitly as :DO-NOT-SET if +;;; this should not happen, for example because the instruction's +;;; default operand size is qword. R, X and B are NIL or TNs specifying +;;; registers the encodings of which are extended with the REX.R, REX.X +;;; and REX.B bit, respectively. To determine whether one of the byte +;;; registers is used that can only be accessed using a REX prefix, we +;;; need only to test R and B, because X is only used for the index +;;; register of an effective address and therefore never byte-sized. +;;; For R we can avoid to calculate the size of the TN because it is +;;; always OPERAND-SIZE. The size of B must be calculated here because +;;; B can be address-sized (if it is the base register of an effective +;;; address), of OPERAND-SIZE (if the instruction operates on two +;;; registers) or of some different size (in the instructions that +;;; combine arguments of different sizes: MOVZX, MOVSX, MOVSXD). +;;; We don't distinguish between general purpose and floating point +;;; registers for this cause because only general purpose registers can +;;; be byte-sized at all. (defun maybe-emit-rex-prefix (segment operand-size r x b) + (declare (type (member nil :byte :word :dword :qword :float :double + :do-not-set) + operand-size) + (type (or null tn) r x b)) (labels ((if-hi (r) (if (and r (> (tn-offset r) ;; offset of r8 is 16, offset of xmm8 is 8 @@ -1244,26 +1284,55 @@ 7 15))) 1 - 0))) + 0)) + (reg-4-7-p (r) + ;; Assuming R is a TN describing a general purpose + ;; register, return true if it references register + ;; 4 upto 7. + (<= 8 (tn-offset r) 15))) (let ((rex-w (if (eq operand-size :qword) 1 0)) (rex-r (if-hi r)) (rex-x (if-hi x)) (rex-b (if-hi b))) - (when (or (eq operand-size :byte) ;; REX needed to access SIL/DIL - (not (zerop (logior rex-w rex-r rex-x rex-b)))) + (when (or (not (zerop (logior rex-w rex-r rex-x rex-b))) + (and r + (eq operand-size :byte) + (reg-4-7-p r)) + (and b + (eq (operand-size b) :byte) + (reg-4-7-p b))) (emit-rex-byte segment #b0100 rex-w rex-r rex-x rex-b))))) -(defun maybe-emit-rex-for-ea (segment ea reg &key operand-size) - (let ((ea-p (ea-p ea))) ;emit-ea can also be called with a tn +;;; Emit a REX prefix if necessary. The operand size is determined from +;;; THING or can be overwritten by OPERAND-SIZE. This and REG are always +;;; passed to MAYBE-EMIT-REX-PREFIX. Additionally, if THING is an EA we +;;; pass its index and base registers, if it is a register TN, we pass +;;; only itself. +;;; In contrast to EMIT-EA above, neither stack TNs nor fixups need to +;;; be treated specially here: If THING is a stack TN, neither it nor +;;; any of its components are passed to MAYBE-EMIT-REX-PREFIX which +;;; works correctly because stack references always use RBP as the base +;;; register and never use an index register so no extended registers +;;; need to be accessed. Fixups are assembled using an addressing mode +;;; of displacement-only or RIP-plus-displacement (see EMIT-EA), so may +;;; not reference an extended register. The displacement-only addressing +;;; mode requires that REX.X is 0, which is ensured here. +(defun maybe-emit-rex-for-ea (segment thing reg &key operand-size) + (declare (type (or ea tn fixup) thing) + (type (or null tn) reg) + (type (member nil :byte :word :dword :qword :float :double + :do-not-set) + operand-size)) + (let ((ea-p (ea-p thing))) (maybe-emit-rex-prefix segment - (or operand-size (operand-size ea)) + (or operand-size (operand-size thing)) reg - (and ea-p (ea-index ea)) - (cond (ea-p (ea-base ea)) - ((and (tn-p ea) - (member (sb-name (sc-sb (tn-sc ea))) + (and ea-p (ea-index thing)) + (cond (ea-p (ea-base thing)) + ((and (tn-p thing) + (member (sb-name (sc-sb (tn-sc thing))) '(float-registers registers))) - ea) + thing) (t nil))))) (defun operand-size (thing) @@ -1407,21 +1476,20 @@ (:word (aver (eq src-size :byte)) (maybe-emit-operand-size-prefix segment :word) + ;; REX prefix is needed if SRC is SIL, DIL, SPL or BPL. + (maybe-emit-rex-for-ea segment src dst :operand-size :word) (emit-byte segment #b00001111) (emit-byte segment opcode) (emit-ea segment src (reg-tn-encoding dst))) ((:dword :qword) (ecase src-size (:byte - (maybe-emit-operand-size-prefix segment :dword) - (maybe-emit-rex-for-ea segment src dst - :operand-size (operand-size dst)) + (maybe-emit-rex-for-ea segment src dst :operand-size dst-size) (emit-byte segment #b00001111) (emit-byte segment opcode) (emit-ea segment src (reg-tn-encoding dst))) (:word - (maybe-emit-rex-for-ea segment src dst - :operand-size (operand-size dst)) + (maybe-emit-rex-for-ea segment src dst :operand-size dst-size) (emit-byte segment #b00001111) (emit-byte segment (logior opcode 1)) (emit-ea segment src (reg-tn-encoding dst))) @@ -1498,15 +1566,16 @@ (emit-byte segment #b01101010) (emit-byte segment src)) (t - ;; AMD64 manual says no REX needed but is unclear - ;; whether it expects 32 or 64 bit immediate here + ;; A REX-prefix is not needed because the operand size + ;; defaults to 64 bits. The size of the immediate is 32 + ;; bits and it is sign-extended. (emit-byte segment #b01101000) (emit-dword segment src)))) (t (let ((size (operand-size src))) (aver (not (eq size :byte))) (maybe-emit-operand-size-prefix segment size) - (maybe-emit-rex-for-ea segment src nil) + (maybe-emit-rex-for-ea segment src nil :operand-size :do-not-set) (cond ((register-p src) (emit-byte-with-reg segment #b01010 (reg-tn-encoding src))) (t @@ -1522,7 +1591,7 @@ (let ((size (operand-size dst))) (aver (not (eq size :byte))) (maybe-emit-operand-size-prefix segment size) - (maybe-emit-rex-for-ea segment dst nil) + (maybe-emit-rex-for-ea segment dst nil :operand-size :do-not-set) (cond ((register-p dst) (emit-byte-with-reg segment #b01011 (reg-tn-encoding dst))) (t @@ -2267,7 +2336,6 @@ (:emitter (typecase where (label - (maybe-emit-rex-for-ea segment where nil) (emit-byte segment #b11101000) ; 32 bit relative (emit-back-patch segment 4 @@ -2276,11 +2344,10 @@ (- (label-position where) (+ posn 4)))))) (fixup - (maybe-emit-rex-for-ea segment where nil) (emit-byte segment #b11101000) (emit-relative-fixup segment where)) (t - (maybe-emit-rex-for-ea segment where nil) + (maybe-emit-rex-for-ea segment where nil :operand-size :do-not-set) (emit-byte segment #b11111111) (emit-ea segment where #b010))))) @@ -2345,7 +2412,7 @@ (error "don't know what to do with ~A" where)) ;; near jump defaults to 64 bit ;; w-bit in rex prefix is unnecessary - (maybe-emit-rex-for-ea segment where nil :operand-size :dword) + (maybe-emit-rex-for-ea segment where nil :operand-size :do-not-set) (emit-byte segment #b11111111) (emit-ea segment where #b100))))) diff --git a/src/compiler/x86-64/macros.lisp b/src/compiler/x86-64/macros.lisp index ff53bf9..625b496 100644 --- a/src/compiler/x86-64/macros.lisp +++ b/src/compiler/x86-64/macros.lisp @@ -11,31 +11,6 @@ (in-package "SB!VM") -;;; We can load/store into fp registers through the top of stack -;;; %st(0) (fr0 here). Loads imply a push to an empty register which -;;; then changes all the reg numbers. These macros help manage that. - -;;; Use this when we don't have to load anything. It preserves old tos -;;; value, but probably destroys tn with operation. -(defmacro with-tn@fp-top((tn) &body body) - `(progn - (unless (zerop (tn-offset ,tn)) - (inst fxch ,tn)) - ,@body - (unless (zerop (tn-offset ,tn)) - (inst fxch ,tn)))) - -;;; Use this to prepare for load of new value from memory. This -;;; changes the register numbering so the next instruction had better -;;; be a FP load from memory; a register load from another register -;;; will probably be loading the wrong register! -(defmacro with-empty-tn@fp-top((tn) &body body) - `(progn - (inst fstp ,tn) - ,@body - (unless (zerop (tn-offset ,tn)) - (inst fxch ,tn)))) ; save into new dest and restore st(0) - ;;;; instruction-like macros (defmacro move (dst src) diff --git a/src/compiler/x86-64/parms.lisp b/src/compiler/x86-64/parms.lisp index de4af8a..ec06769 100644 --- a/src/compiler/x86-64/parms.lisp +++ b/src/compiler/x86-64/parms.lisp @@ -217,14 +217,6 @@ *fp-constant-1d0* *fp-constant-0f0* *fp-constant-1f0* - ;; The following are all long-floats. - *fp-constant-0l0* - *fp-constant-1l0* - *fp-constant-pi* - *fp-constant-l2t* - *fp-constant-l2e* - *fp-constant-lg2* - *fp-constant-ln2* ;; The ..SLOT-UNBOUND.. symbol is static in order to optimise the ;; common slot unbound check. @@ -250,9 +242,3 @@ sb!kernel:two-arg-xor sb!kernel:two-arg-gcd sb!kernel:two-arg-lcm)) - -;;;; stuff added by jrd - -;;; FIXME: Is this used? Delete it or document it. -;;; cf the sparc PARMS.LISP -(defparameter *assembly-unit-length* 8) diff --git a/src/runtime/x86-64-linux-os.c b/src/runtime/x86-64-linux-os.c index 6633b32..01e69bc 100644 --- a/src/runtime/x86-64-linux-os.c +++ b/src/runtime/x86-64-linux-os.c @@ -129,12 +129,8 @@ os_context_fp_addr(os_context_t *context) unsigned long os_context_fp_control(os_context_t *context) { -#if 0 - return ((((context->uc_mcontext.fpregs->cw) & 0xffff) ^ 0x3f) | - (((context->uc_mcontext.fpregs->sw) & 0xffff) << 16)); -#else - return 0; -#endif + int mxcsr = context->uc_mcontext.fpregs->mxcsr; + return ((mxcsr & 0x3F) << 16 | ((mxcsr >> 7) & 0x3F)) ^ 0x3F; } sigset_t * @@ -146,9 +142,7 @@ os_context_sigmask_addr(os_context_t *context) void os_restore_fp_control(os_context_t *context) { -#if 0 - asm ("fldcw %0" : : "m" (context->uc_mcontext.fpregs->cw)); -#endif + asm ("ldmxcsr %0" : : "m" (context->uc_mcontext.fpregs->mxcsr)); } void diff --git a/tests/float.pure.lisp b/tests/float.pure.lisp index dba1bed..c797f53 100644 --- a/tests/float.pure.lisp +++ b/tests/float.pure.lisp @@ -91,7 +91,7 @@ least-positive-double-float)) (assert (= 0.0 (scale-float 1.0 most-negative-fixnum))) (assert (= 0.0d0 (scale-float 1.0d0 (1- most-negative-fixnum)))) -#-(or darwin x86-64) ;; bug 372 / 378 +#-(or darwin) ;; bug 372 (progn (assert (raises-error? (scale-float 1.0 most-positive-fixnum) floating-point-overflow)) diff --git a/version.lisp-expr b/version.lisp-expr index e6026ed..c9358db 100644 --- a/version.lisp-expr +++ b/version.lisp-expr @@ -17,4 +17,4 @@ ;;; checkins which aren't released. (And occasionally for internal ;;; versions, especially for internal versions off the main CVS ;;; branch, it gets hairier, e.g. "0.pre7.14.flaky4.13".) -"0.9.0.36" +"0.9.0.37"