Subject: Re: [clisp-list] Problems compiling clisp 2.27 for Tru64 5.1 on Alpha using cc

From: Sam Steingold <[email-masked]>
Date: Fri Sep 21 11:11:04 2001

> * In message <[email-masked]>
> * On the subject of "Re: [clisp-list] Problems compiling clisp 2.27 for Tru64 5.1 on Alpha using cc"
> * Sent on Fri, 21 Sep 2001 13:09 -0400
> * Honorable [email-masked] writes:
>
> [mailing list removed]

please do not do that because mailing lists are archived and my
personal mail is not.

> 	  (loop for size from 2 to 40 do (handler-case (bin-stream-test :size size :type'signed-byte) (error (e) (format t "~&Case ~d got error ~a" size e))))
> 
>     and got this result:
> 
>     Case 2 got error 
>      * [(SIGNED-BYTE 2)] -10 != 1.70139s38

you also got errors until case 35, i.e., bignums are broken too.

> The problem appears to be in the following code from the rd_by_iu_I routine in stream.d/c:
> 
>       return negfixnum(wbitm(intLsize)+(oint)wert);
> 
> The wbitm appears to be adding 0x100000000 to the correct signed C
> value in wert, and then negfixnum is adding that to 0x4200000000 to
> produce 0x44xxxxxxxx.  If I change it back to 0x43xxxxxxxx, I get the
> right answer, so whatever bit 0x100000000 is (the mark bit?), it is
> erroneously getting added in twice apparently changing the type code.

interesting.
what if you replace the line with

        return negfixnum((oint)wert);

what does "make check" say?

thanks.

-- 
Sam Steingold (http://www.podval.org/~sds)
Support Israel's right to defend herself! <http://www.i-charity.com/go/israel>
Read what the Arab leaders say to their people on <http://www.memri.org/>
OK, so you're a Ph.D.  Just don't touch anything.

---

From: [email-masked]
Date: Mon Sep 24 12:45:07 2001

Date: Fri, 21 Sep 2001 14:09 EDT
    From: Sam Steingold <[email-masked]>

Sorry, I was just trying to prevent bothering everyone with what seemed
like a one-on-one conversation.

    > value in wert, and then negfixnum is adding that to 0x4200000000 to

Whoops, the above should have been 0x43000000 insteand of 0x4200000000.

    > erroneously getting added in twice apparently changing the type code.

I was wrong.  It got what appeared to be the right answer, i.e. it printed
out as -1 or -2 (the two test cases I used in the 2-bit case) but those
returned values were not EQ (or EQL or EQUAL) to a typed-in -1 or -2.

0x43ffffffff prints out as -1, but 0x42ffffffff is the real -1.

    interesting.

It still fails, but this time because the values, although they print out OK,
are not EQL, since they have the 0x43 type bits instead of the 0x42 type bits.

    thanks.

---

From: Sam Steingold <[email-masked]>
Date: Mon Sep 24 13:40:05 2001

> * In message <[email-masked]>
> * Sent on Mon, 24 Sep 2001 15:44 -0400
> Sorry, I was just trying to prevent bothering everyone with what
> seemed like a one-on-one conversation.

I understand.

>     > produce 0x44xxxxxxxx.  If I change it back to 0x43xxxxxxxx, I
>     > get the right answer, so whatever bit 0x100000000 is (the mark
>     > bit?), it is erroneously getting added in twice apparently
>     > changing the type code.
> 
> I was wrong.  It got what appeared to be the right answer, i.e. it
> printed out as -1 or -2 (the two test cases I used in the 2-bit case)
> but those returned values were not EQ (or EQL or EQUAL) to a typed-in
> -1 or -2.
> 

what do you get as type-of for 0x43ffffffff?

what do you get when you replace

with

        return negfixnum(-wbitm(intLsize)+(oint)wert);

??

thanks for your help!

-- 
Sam Steingold (http://www.podval.org/~sds)
Support Israel's right to defend herself! <http://www.i-charity.com/go/israel>
Read what the Arab leaders say to their people on <http://www.memri.org/>
MS: Brain off-line, please wait.

---

From: [email-masked]
Date: Tue Sep 25 06:00:02 2001

Date: Mon, 24 Sep 2001 16:38 EDT
    From: Sam Steingold <[email-masked]>

[stuff elided]

Fixnum    

    with

    ??

That fixed it.  Just out of curiosity, what is bit 32 supposed to mean?

    thanks for your help!

You're welcome.

---

From: Sam Steingold <[email-masked]>
Date: Tue Sep 25 09:25:03 2001

> * In message <[email-masked]>
> * Sent on Tue, 25 Sep 2001 09:00 -0400

what does this evaluate to?
(+ 0 0x43ffffffff) ==> 

> That fixed it.

all cases?  fixnum and bignum?  make check now passes?

> Just out of curiosity, what is bit 32 supposed to mean?

all 3 cases:
   return negfixnum( wbitm(intLsize)+(oint)wert);
   return negfixnum(-wbitm(intLsize)+(oint)wert);
   return negfixnum(                 (oint)wert);
are identical on win32, linux and solaris.

I wonder what is going on here.

Note that negfixnum() is used in just a couple of place in the whole of
CLISP - actually, always with small constants, except for SF_to_I() and
FF_to_I().  Kalman, could you please try coercing some negative single
and short floats to fixnums?

Bruno, I would greatly appreciate your insight.

thanks.

-- 
Sam Steingold (http://www.podval.org/~sds)
Support Israel's right to defend herself! <http://www.i-charity.com/go/israel>
Read what the Arab leaders say to their people on <http://www.memri.org/>
Marriage is the sole cause of divorce.

---

From: [email-masked]
Date: Wed Sep 26 07:55:03 2001

Date: Tue, 25 Sep 2001 12:23 EDT
    From: Sam Steingold <[email-masked]>

Prints out as -1, but isn't EQL to typed in -1, hence I deduce it
is an example of 0x43ffffffff.

Yes, sorry for not making that clear.

    all 3 cases:

You mean a 32-bit Linux, right?  I'm planning to set up an Alpha Linux
presently, and I presume it would behave the same way as Tru64. Is the
Solaris on a 64-bit or 32-bit system?  The code is conditionalized to
allow more type bits for 64-bit systems, so it isn't surprisiing that
32-bit systems don't see any problems.

There is something curious in lispbibl.c:

      /* Bits 63..33 = Typcode, Bits 32..0 = Adresse */
      #if 1 /* Was ist besser?? */
        #define oint_type_shift 32
        #define oint_type_len 32
      #else
        #define oint_type_shift 33
        #define oint_type_len 31
      #endif
      #define oint_type_mask 0xFFFFFFFE00000000UL
      #define oint_addr_shift 0
      #define oint_addr_len 33
      #define oint_addr_mask 0x00000001FFFFFFFFUL
      #define oint_data_shift 0
      #define oint_data_len 32
      #define oint_data_mask 0x00000000FFFFFFFFUL

I'm guessing that the original code was the second leg of the #if 1, i.e.
shift of 33 and length of 31, but someone was trying out the first branch,
i.e. shift of 32 and length of 32.  However, the oint_type_mask value looks
like it goes with the original value (i.e. 31 bits starting in bit 33).  
This makes the type bits be shifted over one from where the should be,
(i.e. fixnum is 0x40 instead of 0x20) and leaves room for the "don't care"
bit which leads to the confusion between 0x43ffffffff and 0x42ffffffff. 

However, putting it back didn't fix this particular bug.

From reading the code some more, I'm reasonably certain that bit 32 is
intended to be the fixnum sign bit, and that the wbitm(intLsize)+ part
of the expression is intended to be doing sign extension of the known to
be negative sign of the C value into that sign bit.  

The various preprocessor macros used inside negfixnum (fixnum_inc which
calls objectplus which calls pointerplus) seem to expect addition to be
modulo 32-bits, i.e. not affecting the sign or type bits, but on a 64bit
machine the addition is a 64-bit one, and if you supply the sign bit
twice [in this case both from the Fixnum_minus1 in negfixnum's expansion
and the wbitm(intLsize) in returning the result], the overflow out of
the sign bit goes into the next higher order type bit, hence the bug of
returning a short float result instead of a negative fixnum.  (The type
short float is next higher than fixnum.)

My guess is that on a 64-bit machine, fixnum_inc needs to be a bit smarter
and do a masked or 32-bit addition.

I'm not sure what you want me to do.  The Common Lisp COERCE function won't
accept fixnum as a type.  Floor and ceiling work as expected, i.e. give
correct negative integers, not the bogus ones.

    thanks.

---

From: Sam Steingold <[email-masked]>
Date: Wed Sep 26 09:41:02 2001

> * In message <[email-masked]>
> * Sent on Wed, 26 Sep 2001 03:45 -0400
> You mean a 32-bit Linux, right?
yes, and 32-big Solaris too.
sorry about not saying this.

> I'm planning to set up an Alpha Linux presently, and I presume it
> would behave the same way as Tru64.

Unfortunately, I must tell you that CLISP does _not_ work on Alpha Linux
with glibc2.2 (it _does_ work with glibc2.1).
http://sourceforge.net/tracker/index.php?func=detail&aid=223193&group_id=1355&atid=101355
your assistance in tracking down the problem would be greatly appreciated!

> I'm not sure what you want me to do.  The Common Lisp COERCE function
> won't accept fixnum as a type.

if the float is small enough, (coerce float 'integer) should return a
fixnum.

> My guess is that on a 64-bit machine, fixnum_inc needs to be a bit
> smarter and do a masked or 32-bit addition.

could you please remove "wbitm(intLsize)" from the negfixnum() call
altogether and try the appended patch?  [untested - I am sure you can
fix it :-]

thanks.

-- 
Sam Steingold (http://www.podval.org/~sds)
Support Israel's right to defend herself! <http://www.i-charity.com/go/israel>
Read what the Arab leaders say to their people on <http://www.memri.org/>
If your VCR is still blinking 12:00, you don't want Linux.

Index: lispbibl.d
===================================================================
RCS file: /cvsroot/clisp/clisp/src/lispbibl.d,v
retrieving revision 1.217
diff -u -w -b -u -b -w -i -B -r1.217 lispbibl.d
--- lispbibl.d	2001/09/24 20:03:22	1.217
+++ lispbibl.d	2001/09/26 16:36:52
@@ -2619,11 +2619,15 @@
 
 # To add something to an object/oint:
 # objectplus(obj,offset)
+#define add(obj,offset)                                         \
+  ( (as_oint(obj)                    & oint_type_mask) |        \
+    (as_oint(obj) + (soint)(offset)) & oint_addr_mask )
 #if !(defined(WIDE_SOFT) || defined(OBJECT_STRUCT))
-  #define objectplus(obj,offset)  ((object)pointerplus(obj,offset))
+  #define objectplus(obj,offset)  ((object)add(obj,offset))
 #else # defined(WIDE_SOFT) || defined(OBJECT_STRUCT)
-  #define objectplus(obj,offset)  as_object(as_oint(obj)+(soint)(offset))
+  #define objectplus(obj,offset)  as_object(add(obj,offset))
 #endif
+#undef add
 
 # Bit operations on sizes of type oint:
 # ...wbit... instead of ...bit..., "w" = "wide".

---

From: Raymond Toy <[email-masked]>
Date: Thu Sep 27 13:50:03 2001

>>>>> "Sam" == Sam Steingold <[email-masked]> writes:

    Sam> if the float is small enough, (coerce float 'integer) should return a
    Sam> fixnum.

Are you sure?  This seems wrong to me.

Ray

---

From: Sam Steingold <[email-masked]>
Date: Fri Sep 28 06:06:01 2001

> * In message <[email-masked]>
> * Sent on 27 Sep 2001 16:49:38 -0400
> * Honorable Raymond Toy <[email-masked]> writes:
>

you are right.
sorry.
I wonder how to make CLISP invoke FF_to_I().
Bruno?

---

From: Sam Steingold <[email-masked]>
Date: Mon Oct 1 06:54:03 2001

> altogether and try the appended patch? 

my patch was broken.

please try this:

Index: lispbibl.d
===================================================================
RCS file: /cvsroot/clisp/clisp/src/lispbibl.d,v
retrieving revision 1.217
diff -u -w -b -r1.217 lispbibl.d
--- lispbibl.d  2001/09/24 20:03:22     1.217
+++ lispbibl.d  2001/10/01 13:49:08
@@ -4082,7 +4082,9 @@
 # > delta: a constant
 # < result: incremented fixnum
 #define fixnum_inc(obj,delta)  \
-    objectplus(obj, (soint)(delta) << oint_data_shift)
+ (as_object( (as_oint(obj) & oint_type_mask) |                          \
+            ((as_oint(obj) + ((soint)(delta) << oint_data_shift))       \
+                           & oint_addr_mask) ))
 
 # posfixnum(x) is a fixnum with value x>=0.
 #define posfixnum(x)  fixnum_inc(Fixnum_0,x)

thanks.

-- 
Sam Steingold (http://www.podval.org/~sds)
Support Israel's right to defend herself! <http://www.i-charity.com/go/israel>
Read what the Arab leaders say to their people on <http://www.memri.org/>
Don't hit a man when he's down -- kick him; it's easier.