I am beginning a port of TCL 8.0 to a Cray-T3E running UNICOS/mk.
I have seen some minor problems. For example, configure did not know how
to deal with the T3E, or with the slightly different UNICOS-UNICOS/mk uname.
The first general showstopper is the fact that Cray PVP and MPP
architectures have a 32 bit short and a 64 bit int/long. This requires
special handling from the "binary" subroutine ScanNumber. This is a design
problem, in that a "good" answer to this report would be a mechanism to
handle implementing the Tcl psuedo-machine on the varying sizes and sexes
of short, int, long, etc.
% ./a.out
size of short is: 4
size of int is: 8
size of long is: 8
size of float is: 4
size of double is: 8
the order of character arrays is 1020304050607
% cat test.c
main()
{
unsigned char bytearray[8];
int i;
printf("size of short is: %d\n",sizeof(short));
printf("size of int is: %d\n",sizeof(int));
printf("size of long is: %d\n",sizeof(long));
printf("size of float is: %d\n",sizeof(float));
printf("size of double is: %d\n",sizeof(double));
for( i=0; i < 8 ; i++)
bytearray[i]=i;
printf("the order of character arrays is %x",*(long *)bytearray);
}
---
ScanNumber casts assuming that short is 2 bytes and long is 4
---
static Tcl_Obj *
ScanNumber(buffer, type)
char *buffer; /* Buffer to scan number from. */
int type; /* Type of number to scan. */
{
int c;
switch ((char) type) {
case 'c':
/*
* Characters need special handling. We want to produce a
* signed result, but on some platforms (such as AIX) chars
* are unsigned. To deal with this, check for a value that
* should be negative but isn't.
*/
c = buffer[0];
if (c > 127) {
c -= 256;
}
return Tcl_NewIntObj(c);
case 's':
return Tcl_NewIntObj((short)(((unsigned char)buffer[0])
+ ((unsigned char)buffer[1] << 8)));
case 'S':
return Tcl_NewIntObj((short)(((unsigned char)buffer[1])
+ ((unsigned char)buffer[0] << 8)));
case 'i':
return Tcl_NewIntObj((long) (((unsigned char)buffer[0])
+ ((unsigned char)buffer[1] << 8)
+ ((unsigned char)buffer[2] << 16)
+ ((unsigned char)buffer[3] << 24)));
case 'I':
return Tcl_NewIntObj((long) (((unsigned char)buffer[3])
+ ((unsigned char)buffer[2] << 8)
+ ((unsigned char)buffer[1] << 16)
+ ((unsigned char)buffer[0] << 24)));
...
Scott Emery
em...@cray.com
> I am beginning a port of TCL 8.0 to a Cray-T3E running UNICOS/mk.
> I have seen some minor problems. For example, configure did not know how
> to deal with the T3E, or with the slightly different UNICOS-UNICOS/mk uname.
>
> The first general showstopper is the fact that Cray PVP and MPP
> architectures have a 32 bit short and a 64 bit int/long. This requires
> special handling from the "binary" subroutine ScanNumber. This is a design
> problem, in that a "good" answer to this report would be a mechanism to
> handle implementing the Tcl psuedo-machine on the varying sizes and sexes
> of short, int, long, etc.
The binary command is defined to operate on 8-, 16-, and 32- bit
quantities, regardless of the word size of the host machine. The
current implementation doesn't work properly with different word
sizes, as you point out. I've attached a patch that should work on
any architecture where long is at least 32-bits. Please let me know
if this doesn't fix the problems you are seeing.
--Scott
*** /proj/tcl/dist/tcl8.0/generic/tclBinary.c Tue Aug 12 17:04:44 1997
--- tcl8.0/generic/tclBinary.c Tue Oct 28 13:17:52 1997
***************
*** 9,15 ****
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
! * SCCS: @(#) tclBinary.c 1.20 97/08/11 18:43:09
*/
#include <math.h>
--- 9,15 ----
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
! * SCCS: @(#) tclBinary.c 1.23 97/10/28 13:17:51
*/
#include <math.h>
***************
*** 867,879 ****
char cmd = (char)type;
if (cmd == 'd' || cmd == 'f') {
if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) {
return TCL_ERROR;
}
if (cmd == 'd') {
! *((double *)(*cursorPtr)) = dvalue;
(*cursorPtr) += sizeof(double);
} else {
/*
* Because some compilers will generate floating point exceptions
* on an overflow cast (e.g. Borland), we restrict the values
--- 867,886 ----
char cmd = (char)type;
if (cmd == 'd' || cmd == 'f') {
+ /*
+ * For floating point types, we need to copy the data using
+ * memcpy to avoid alignment issues.
+ */
+
if (Tcl_GetDoubleFromObj(interp, src, &dvalue) != TCL_OK) {
return TCL_ERROR;
}
if (cmd == 'd') {
! memcpy((*cursorPtr), &dvalue, sizeof(double));
(*cursorPtr) += sizeof(double);
} else {
+ float fvalue;
+
/*
* Because some compilers will generate floating point exceptions
* on an overflow cast (e.g. Borland), we restrict the values
***************
*** 881,893 ****
*/
if (fabs(dvalue) > (double)FLT_MAX) {
! *((float *)(*cursorPtr))
! = (dvalue >= 0.0) ? FLT_MAX : -FLT_MAX;
! } else if (fabs(dvalue) < (double)FLT_MIN) {
! *((float *)(*cursorPtr)) = (float) 0.0;
} else {
! *((float *)(*cursorPtr)) = (float) dvalue;
}
(*cursorPtr) += sizeof(float);
}
} else {
--- 888,898 ----
*/
if (fabs(dvalue) > (double)FLT_MAX) {
! fvalue = (dvalue >= 0.0) ? FLT_MAX : -FLT_MAX;
} else {
! fvalue = (float) dvalue;
}
+ memcpy((*cursorPtr), &fvalue, sizeof(float));
(*cursorPtr) += sizeof(float);
}
} else {
***************
*** 938,981 ****
static Tcl_Obj *
ScanNumber(buffer, type)
char *buffer; /* Buffer to scan number from. */
! int type; /* Type of number to scan. */
{
! int c;
switch ((char) type) {
case 'c':
! /*
! * Characters need special handling. We want to produce a
! * signed result, but on some platforms (such as AIX) chars
! * are unsigned. To deal with this, check for a value that
! * should be negative but isn't.
! */
! c = buffer[0];
! if (c > 127) {
! c -= 256;
}
! return Tcl_NewIntObj(c);
case 's':
! return Tcl_NewIntObj((short)(((unsigned char)buffer[0])
! + ((unsigned char)buffer[1] << 8)));
case 'S':
! return Tcl_NewIntObj((short)(((unsigned char)buffer[1])
! + ((unsigned char)buffer[0] << 8)));
case 'i':
! return Tcl_NewIntObj((long) (((unsigned char)buffer[0])
+ ((unsigned char)buffer[1] << 8)
+ ((unsigned char)buffer[2] << 16)
! + ((unsigned char)buffer[3] << 24)));
case 'I':
! return Tcl_NewIntObj((long) (((unsigned char)buffer[3])
+ ((unsigned char)buffer[2] << 8)
+ ((unsigned char)buffer[1] << 16)
! + ((unsigned char)buffer[0] << 24)));
! case 'f':
! return Tcl_NewDoubleObj(*(float*)buffer);
! case 'd':
! return Tcl_NewDoubleObj(*(double*)buffer);
}
return NULL;
}
--- 943,1012 ----
static Tcl_Obj *
ScanNumber(buffer, type)
char *buffer; /* Buffer to scan number from. */
! int type; /* Format character from "binary scan" */
{
! long value;
+ /*
+ * We cannot rely on the compiler to properly sign extend integer values
+ * when we cast from smaller values to larger values because we don't know
+ * the exact size of the integer types. So, we have to handle sign
+ * extension explicitly by checking the high bit and padding with 1's as
+ * needed.
+ */
+
switch ((char) type) {
case 'c':
! value = buffer[0];
! if (value & 0x80) {
! value |= -0x100;
}
! return Tcl_NewLongObj(value);
case 's':
! value = (long) (((unsigned char)buffer[0])
! + ((unsigned char)buffer[1] << 8));
! goto shortValue;
case 'S':
! value = (long) (((unsigned char)buffer[1])
! + ((unsigned char)buffer[0] << 8));
! shortValue:
! if (value & 0x8000) {
! value |= -0x10000;
! }
! return Tcl_NewLongObj(value);
case 'i':
! value = (long) (((unsigned char)buffer[0])
+ ((unsigned char)buffer[1] << 8)
+ ((unsigned char)buffer[2] << 16)
! + ((unsigned char)buffer[3] << 24));
! goto intValue;
case 'I':
! value = (long) (((unsigned char)buffer[3])
+ ((unsigned char)buffer[2] << 8)
+ ((unsigned char)buffer[1] << 16)
! + ((unsigned char)buffer[0] << 24));
! intValue:
! if (value & 0x80000000) {
! /*
! * Subtract 0x100000000 in two passes to work on compilers
! * that don't support 33-bit constants.
! */
!
! value -= 0xffffffff;
! value--;
! }
! return Tcl_NewLongObj(value);
! case 'f': {
! float fvalue;
! memcpy(&fvalue, buffer, sizeof(float));
! return Tcl_NewDoubleObj(fvalue);
! }
! case 'd': {
! double dvalue;
! memcpy(&dvalue, buffer, sizeof(double));
! return Tcl_NewDoubleObj(dvalue);
! }
}
return NULL;
}
I thought _I_ had architecture problems supporting 6 flavors of UNIX +
NT! ;-)
Is the outcome of your UNICOS port something that you can make available
to the Tcl community? Not that I have a Cray, but I can see wanting a
64-bit "patch" sometime "soon". To the extent that it's practical, it
would be wonderful if you could keep your work in two bins, Cray and
wide-word, so others could use either or both sets of changes.
(I've joked with co-workers that if 2-bytes are a word and 16 bytes are
a "paragraph" (in some assemblers), then 8-bytes (64-bit "words") should
be a "sentence" ;-)
Chris
--
Chris Nelson Rens-se-LEER is a county.
Work: nel...@pinebush.com RENS-se-ler is a city.
Play: chris....@juno.com R-P-I is a school in Troy!
> Scott Emery wrote:
> >
> > The first general showstopper is the fact that Cray PVP and MPP
> > architectures have a 32 bit short and a 64 bit int/long.
> ...
>
>
> I thought _I_ had architecture problems supporting 6 flavors of UNIX +
> NT! ;-)
>
>
I, too, have trouble compiling Tcl on a 64bit SGI Indigo System.Although tclsh
and wish are build and executable, they often crash
which is due to explicit casts of pointers to int which means truncating
64bit pointers to 32bit int and this, of course, often leads to runtime errors.
In fact I had that problem compiling tcl7.6 / tk4.2 not versions 8.0.
Maybe explicit casts are removed in 8.0, I didn't check this, yet.
Ciao,
Joerg
--
Joerg Reiberg, rei...@math.uni-muenster.de
IfI WWU Muenster, Einsteinstr. 62, 48727 Muenster
Tel. +49 251/83-33987
http://www.uni-muenster.de/informatik/u/reiberg
Maybe there is a need to expand the interface to binary to allow access
to types whose lengths will vary such as shorts and also to allow access
to types of a fixed length such as 16bit numbers.
Scott Emery wrote:
>
> I am beginning a port of TCL 8.0 to a Cray-T3E running UNICOS/mk.
> I have seen some minor problems. For example, configure did not know how
> to deal with the T3E, or with the slightly different UNICOS-UNICOS/mk uname.
>
> The first general showstopper is the fact that Cray PVP and MPP
> architectures have a 32 bit short and a 64 bit int/long. This requires
> special handling from the "binary" subroutine ScanNumber. This is a design
> problem, in that a "good" answer to this report would be a mechanism to
> handle implementing the Tcl psuedo-machine on the varying sizes and sexes
> of short, int, long, etc.
>
> % ./a.out
> size of short is: 4
> size of int is: 8
> size of long is: 8
> size of float is: 4
> size of double is: 8
> the order of character arrays is 1020304050607
> % cat test.c
>
> main()
> {
> unsigned char bytearray[8];
> int i;
>
> printf("size of short is: %d\n",sizeof(short));
> printf("size of int is: %d\n",sizeof(int));
> printf("size of long is: %d\n",sizeof(long));
> printf("size of float is: %d\n",sizeof(float));
> printf("size of double is: %d\n",sizeof(double));
> for( i=0; i < 8 ; i++)
> bytearray[i]=i;
> printf("the order of character arrays is %x",*(long *)bytearray);
> }
> ---
> ScanNumber casts assuming that short is 2 bytes and long is 4
> ---
> static Tcl_Obj *
> ScanNumber(buffer, type)
> char *buffer; /* Buffer to scan number from. */
> int type; /* Type of number to scan. */
> {
> int c;
>
> switch ((char) type) {
> case 'c':
> /*
> * Characters need special handling. We want to produce a
> * signed result, but on some platforms (such as AIX) chars
> * are unsigned. To deal with this, check for a value that
> * should be negative but isn't.
> */
>
> c = buffer[0];
> if (c > 127) {
> c -= 256;
> }
> return Tcl_NewIntObj(c);
> case 's':
> return Tcl_NewIntObj((short)(((unsigned char)buffer[0])
> + ((unsigned char)buffer[1] << 8)));
> case 'S':
> return Tcl_NewIntObj((short)(((unsigned char)buffer[1])
> + ((unsigned char)buffer[0] << 8)));
> case 'i':
> return Tcl_NewIntObj((long) (((unsigned char)buffer[0])
> + ((unsigned char)buffer[1] << 8)
> + ((unsigned char)buffer[2] << 16)
> + ((unsigned char)buffer[3] << 24)));
> case 'I':
> return Tcl_NewIntObj((long) (((unsigned char)buffer[3])
> + ((unsigned char)buffer[2] << 8)
> + ((unsigned char)buffer[1] << 16)
> + ((unsigned char)buffer[0] << 24)));
> ...
>
> Scott Emery
> em...@cray.com
--
Paul Duffin
DT/6000 Development Email: pdu...@hursley.ibm.com
IBM UK Laboratories Ltd., Hursley Park nr. Winchester
Internal: 7-246880 International: +44 1962-816880