Begin to add long long to C compiler for linux386.
				
					
				
			Add long long type, but without literals; you can't say '123LL' yet.
You can try constant operations, like `(long long)123 + 1`, but the
compiler's `arith` type might not be wide enough.  Conversions,
shifts, and some other operations don't work in i386 ncg; I am using a
union instead of conversions:
	union q {
		long long ll;
		unsigned long long ull;
		int i[2];
	};
Hack plat/linux386/descr to enable long long (size 8, alignment 4)
only for this platform.  The default for other platforms is to disable
long long (size -1).
In lang/cem/cemcom.ansi,
 - BigPars, SmallPars: Add default size, alignment of long long.
 - align.h: Add lnglng_align.
 - arith.c: Convert arithmetic operands to long long or unsigned long
   long when necessary; avoid conversion from long long to long.
   Allow long long as an arithmetic, integral, or logical operand.
 - ch3.c: Handle long long like int and long when erroneously applying
   a selector, like `long long ll; ll.member` or `ll->member`.  Add
   long long to integral and arithmetic types.
 - code.c: Add long long to type stabs for debugging.
 - conversion.c: Add long long to integral conversions.
 - cstoper.c: Write masks up to full_mask[8].  Add FIXME comment.
 - declar.g: Parse `long long` in code.
 - decspecs.c: Understand long long in type declarations.
 - eval.c: Add long long to operations, to generate code like `adi 8`.
   Don't use `ldc` with constant over 4 bytes.
 - ival.g: Allow long long in initializations.
 - main.c: Set lnglng_type and related values.
 - options.c: Add option like `-Vq8.4` to set long long to size 8,
   alignment 4.  I chose 'q', because Perl's pack and Ruby's
   Array#pack use 'q' for 64-bit or long long values; it might be a
   reference to BSD's old quad_t alias for long long.
 - sizes.h: Add lnglng_size.
 - stab.c: Allow long long when writing the type stab for debugging.
   Switch from calculating the ranges to hardcoding them in strings;
   add 8-byte ranges as a special case.  This also hardcodes the
   unsigned 4-byte range as "0;-1".  Before it was either "0;-1" or
   "0;4294967295", depending on sizeof(long) in the compiler.
 - struct.c: Try long long bitfield, but it will probably give the
   error, "bit field type long long does not fit in a word".
 - switch.c: Update comment.
 - tokenname.c: Define LNGLNG (long long) like LNGDBL (long double).
 - type.c, type.str: Add lnglng_type and ulnglng_type.  Add function
   no_long_long() to check if long long is disabled.
			
			
This commit is contained in:
		
							parent
							
								
									893df4b79b
								
							
						
					
					
						commit
						007a63d529
					
				
					 22 changed files with 187 additions and 56 deletions
				
			
		| 
						 | 
				
			
			@ -55,6 +55,7 @@
 | 
			
		|||
#define SZ_WORD		4
 | 
			
		||||
#define	SZ_INT		4
 | 
			
		||||
#define	SZ_LONG		4
 | 
			
		||||
#define	SZ_LNGLNG	-1
 | 
			
		||||
#define	SZ_FLOAT	4
 | 
			
		||||
#define	SZ_DOUBLE	8
 | 
			
		||||
#define	SZ_LNGDBL	8	/* for now */
 | 
			
		||||
| 
						 | 
				
			
			@ -66,6 +67,7 @@
 | 
			
		|||
#define AL_WORD		SZ_WORD
 | 
			
		||||
#define	AL_INT		SZ_WORD
 | 
			
		||||
#define	AL_LONG		SZ_WORD
 | 
			
		||||
#define	AL_LNGLNG	SZ_WORD
 | 
			
		||||
#define	AL_FLOAT	SZ_WORD
 | 
			
		||||
#define	AL_DOUBLE	SZ_WORD
 | 
			
		||||
#define	AL_LNGDBL	SZ_WORD
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -55,6 +55,7 @@
 | 
			
		|||
#define SZ_WORD		4
 | 
			
		||||
#define	SZ_INT		4
 | 
			
		||||
#define	SZ_LONG		4
 | 
			
		||||
#define	SZ_LNGLNG	-1
 | 
			
		||||
#define	SZ_FLOAT	4
 | 
			
		||||
#define	SZ_DOUBLE	8
 | 
			
		||||
#define	SZ_LNGDBL	8	/* for now */
 | 
			
		||||
| 
						 | 
				
			
			@ -66,6 +67,7 @@
 | 
			
		|||
#define AL_WORD		SZ_WORD
 | 
			
		||||
#define	AL_INT		SZ_WORD
 | 
			
		||||
#define	AL_LONG		SZ_WORD
 | 
			
		||||
#define	AL_LNGLNG	SZ_WORD
 | 
			
		||||
#define	AL_FLOAT	SZ_WORD
 | 
			
		||||
#define	AL_DOUBLE	SZ_WORD
 | 
			
		||||
#define	AL_LNGDBL	SZ_WORD
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@
 | 
			
		|||
#ifndef NOCROSS
 | 
			
		||||
extern int
 | 
			
		||||
	short_align, word_align, int_align, long_align,
 | 
			
		||||
	lnglng_align,
 | 
			
		||||
	float_align, double_align, lngdbl_align,
 | 
			
		||||
	pointer_align,
 | 
			
		||||
	struct_align, union_align;
 | 
			
		||||
| 
						 | 
				
			
			@ -18,6 +19,7 @@ extern int
 | 
			
		|||
#define word_align	((int)AL_WORD)
 | 
			
		||||
#define int_align	((int)AL_INT)
 | 
			
		||||
#define long_align	((int)AL_LONG)
 | 
			
		||||
#define lnglng_align	((int)AL_LNGLNG)
 | 
			
		||||
#define float_align	((int)AL_FLOAT)
 | 
			
		||||
#define double_align	((int)AL_DOUBLE)
 | 
			
		||||
#define	lngdbl_align	((int)AL_LNGDBL)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,6 +12,7 @@
 | 
			
		|||
*/
 | 
			
		||||
 | 
			
		||||
#include	<assert.h>
 | 
			
		||||
#include	<stddef.h>
 | 
			
		||||
#include    "parameters.h"
 | 
			
		||||
#include	<alloc.h>
 | 
			
		||||
#include	<flt_arith.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -45,7 +46,8 @@ void arithbalance(register struct expr **e1p, int oper, register struct expr **e
 | 
			
		|||
		have a floating type, in which case the flags shouldn't
 | 
			
		||||
		travel upward in the expression tree.
 | 
			
		||||
	*/
 | 
			
		||||
	register int t1, t2, u1, u2;
 | 
			
		||||
	struct type *convert1, *convert2;
 | 
			
		||||
	int t1, t2, u1, u2;
 | 
			
		||||
	int shifting = (oper == LEFT || oper == RIGHT
 | 
			
		||||
			|| oper == LEFTAB || oper == RIGHTAB);
 | 
			
		||||
	int ptrdiff = 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -56,9 +58,11 @@ void arithbalance(register struct expr **e1p, int oper, register struct expr **e
 | 
			
		|||
	if (int_size != pointer_size) {
 | 
			
		||||
		if (ptrdiff = ((*e1p)->ex_flags & EX_PTRDIFF)
 | 
			
		||||
			    || ((*e2p)->ex_flags & EX_PTRDIFF)) {
 | 
			
		||||
			if (!((*e1p)->ex_flags & EX_PTRDIFF) && t1 == LONG)
 | 
			
		||||
			if (!((*e1p)->ex_flags & EX_PTRDIFF)
 | 
			
		||||
			    && (t1 == LONG || t1 == LNGLNG))
 | 
			
		||||
				ptrdiff = 0;
 | 
			
		||||
			if (!((*e2p)->ex_flags & EX_PTRDIFF) && t2 == LONG
 | 
			
		||||
			if (!((*e2p)->ex_flags & EX_PTRDIFF)
 | 
			
		||||
			    && (t2 == LONG || t2 == LNGLNG)
 | 
			
		||||
			    && !shifting)
 | 
			
		||||
				ptrdiff = 0;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -67,7 +71,9 @@ void arithbalance(register struct expr **e1p, int oper, register struct expr **e
 | 
			
		|||
		(*e2p)->ex_flags &= ~EX_PTRDIFF;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Now t1 and t2 are either INT, LONG, FLOAT, DOUBLE, or LNGDBL */
 | 
			
		||||
	/*	Now t1 and t2 are either INT, LONG, LNGLNG,
 | 
			
		||||
		FLOAT, DOUBLE, or LNGDBL
 | 
			
		||||
	*/
 | 
			
		||||
 | 
			
		||||
	/*	If any operand has the type long double, the other operand
 | 
			
		||||
		is converted to long double.
 | 
			
		||||
| 
						 | 
				
			
			@ -82,11 +88,12 @@ void arithbalance(register struct expr **e1p, int oper, register struct expr **e
 | 
			
		|||
		}
 | 
			
		||||
		return;
 | 
			
		||||
	} else if (t2 == LNGDBL) {
 | 
			
		||||
		if (t1 != LNGDBL)
 | 
			
		||||
		if (t1 != LNGDBL) {
 | 
			
		||||
		    if (t1 == DOUBLE || t1 == FLOAT)
 | 
			
		||||
			float2float(e1p, lngdbl_type);
 | 
			
		||||
		    else
 | 
			
		||||
			int2float(e1p, lngdbl_type);
 | 
			
		||||
		}
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -120,38 +127,63 @@ void arithbalance(register struct expr **e1p, int oper, register struct expr **e
 | 
			
		|||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Now they are INT or LONG */
 | 
			
		||||
	/* Now they are INT, LONG or LNGLNG */
 | 
			
		||||
	u1 = (*e1p)->ex_type->tp_unsigned;
 | 
			
		||||
	u2 = (*e2p)->ex_type->tp_unsigned;
 | 
			
		||||
	convert1 = NULL;
 | 
			
		||||
	convert2 = NULL;
 | 
			
		||||
 | 
			
		||||
	/*	If either operand has type unsigned long int, the other
 | 
			
		||||
		operand is converted to unsigned long int.
 | 
			
		||||
	*/
 | 
			
		||||
	if (t1 == LONG && u1 && (t2 != LONG || !u2))
 | 
			
		||||
		t2 = int2int(e2p, ulong_type);
 | 
			
		||||
	else if (t2 == LONG && u2 && (t1 != LONG || !u1)
 | 
			
		||||
			&& !shifting)	/* ??? */
 | 
			
		||||
		t1 = int2int(e1p, ulong_type);
 | 
			
		||||
	/*	If either operand is a long long, the other operand
 | 
			
		||||
		is converted to long long; else if either operand is
 | 
			
		||||
		a long, the other operand is converted to a long.
 | 
			
		||||
 | 
			
		||||
	/*	If one operand has type long int and the other has type unsigned
 | 
			
		||||
		int, if a long int can represent all values of an unsigned int,
 | 
			
		||||
		the operand of type unsigned int is converted to long int; if
 | 
			
		||||
		a long int cannot represent all values of an unsigned int,
 | 
			
		||||
		both operands are converted to unsigned long int.
 | 
			
		||||
		If one operand is signed and the other operand is
 | 
			
		||||
		unsigned, if the signed type can represent all values
 | 
			
		||||
		of the unsigned type, the unsigned operand is
 | 
			
		||||
		converted to the signed type, else both operands are
 | 
			
		||||
		converted to an unsigned type.
 | 
			
		||||
	*/
 | 
			
		||||
	if (t1 == LONG && t2 == INT && u2)
 | 
			
		||||
		t2 = int2int(e2p, (int_size<long_size)? long_type : ulong_type);
 | 
			
		||||
	else if (t2 == LONG && t1 == INT && u1 && !shifting)	/* ??? */
 | 
			
		||||
		t1 = int2int(e1p, (int_size<long_size)? long_type : ulong_type);
 | 
			
		||||
	if (t1 == LNGLNG && u1 && (t2 != LNGLNG || !u2))
 | 
			
		||||
		convert2 = ulnglng_type;
 | 
			
		||||
	else if (t2 == LNGLNG && u2 && (t1 != LNGLNG || !u1))
 | 
			
		||||
		convert1 = ulnglng_type;
 | 
			
		||||
	else if (t1 == LNGLNG && t2 != LNGLNG && u2) {
 | 
			
		||||
		if ((t2 == LONG ? long_size : int_size) < lnglng_size)
 | 
			
		||||
			convert2 = lnglng_type;
 | 
			
		||||
		else
 | 
			
		||||
			convert1 = convert2 = ulnglng_type;
 | 
			
		||||
	} else if (t2 == LNGLNG && t1 != LNGLNG && u1) {
 | 
			
		||||
		if ((t1 == LONG ? long_size : int_size) < lnglng_size)
 | 
			
		||||
			convert1 = lnglng_type;
 | 
			
		||||
		else
 | 
			
		||||
			convert1 = convert2 = ulnglng_type;
 | 
			
		||||
	} else if (t1 == LNGLNG && t2 != LNGLNG)
 | 
			
		||||
		convert2 = lnglng_type;
 | 
			
		||||
	else if (t2 == LNGLNG && t1 != LNGLNG)
 | 
			
		||||
		convert1 = lnglng_type;
 | 
			
		||||
	else if (t1 == LONG && u1 && (t2 != LONG || !u2))
 | 
			
		||||
		convert2 = ulong_type;
 | 
			
		||||
	else if (t2 == LONG && u2 && (t1 != LONG || !u1))
 | 
			
		||||
		convert1 = ulong_type;
 | 
			
		||||
	else if (t1 == LONG && t2 == INT && u2) {
 | 
			
		||||
		if (int_size < long_size)
 | 
			
		||||
			convert2 = long_type;
 | 
			
		||||
		else
 | 
			
		||||
			convert1 = convert2 = ulong_type;
 | 
			
		||||
	} else if (t2 == LONG && t1 == INT && u1) {
 | 
			
		||||
		if (int_size < long_size)
 | 
			
		||||
			convert1 = long_type;
 | 
			
		||||
		else
 | 
			
		||||
			convert1 = convert2 = ulong_type;
 | 
			
		||||
	} else if (t1 == LONG && t2 != LONG)
 | 
			
		||||
		convert2 = long_type;
 | 
			
		||||
	else if (t2 == LONG && t1 != LONG)
 | 
			
		||||
		convert1 = long_type;
 | 
			
		||||
 | 
			
		||||
	/*	If either operand has type long int, the other operand is con-
 | 
			
		||||
		verted to long int.
 | 
			
		||||
	*/
 | 
			
		||||
	if (t1 == LONG && t2 != LONG)
 | 
			
		||||
		t2 = int2int(e2p, long_type);
 | 
			
		||||
	else
 | 
			
		||||
	if (t2 == LONG && t1 != LONG && !shifting)	/* ??? */
 | 
			
		||||
		t1 = int2int(e1p, long_type);
 | 
			
		||||
	if (convert1 && !shifting)	/* ??? */
 | 
			
		||||
		t1 = int2int(e1p, convert1);
 | 
			
		||||
	if (convert2)
 | 
			
		||||
		t2 = int2int(e2p, convert2);
 | 
			
		||||
 | 
			
		||||
	u1 = (*e1p)->ex_type->tp_unsigned;
 | 
			
		||||
	u2 = (*e2p)->ex_type->tp_unsigned;
 | 
			
		||||
| 
						 | 
				
			
			@ -161,10 +193,10 @@ void arithbalance(register struct expr **e1p, int oper, register struct expr **e
 | 
			
		|||
		Otherwise, both operands have type int.
 | 
			
		||||
	*/
 | 
			
		||||
	if (u1 && !u2 && !shifting)
 | 
			
		||||
		t2 = int2int(e2p, (t1 == LONG) ? ulong_type : uint_type);
 | 
			
		||||
		t2 = int2int(e2p, uint_type);
 | 
			
		||||
	else
 | 
			
		||||
	if (!u1 && u2 && !shifting)
 | 
			
		||||
		t1 = int2int(e1p, (t2 == LONG) ? ulong_type : uint_type);
 | 
			
		||||
		t1 = int2int(e1p, uint_type);
 | 
			
		||||
 | 
			
		||||
	if (int_size != pointer_size) {
 | 
			
		||||
		if (ptrdiff) {
 | 
			
		||||
| 
						 | 
				
			
			@ -259,6 +291,7 @@ any2arith(register struct expr **expp, register int oper)
 | 
			
		|||
		break;
 | 
			
		||||
	case INT:
 | 
			
		||||
	case LONG:
 | 
			
		||||
	case LNGLNG:
 | 
			
		||||
		break;
 | 
			
		||||
	case ENUM:
 | 
			
		||||
#ifndef	LINT
 | 
			
		||||
| 
						 | 
				
			
			@ -457,7 +490,7 @@ void opnd2integral(register struct expr **expp, int oper)
 | 
			
		|||
{
 | 
			
		||||
	register int fund = (*expp)->ex_type->tp_fund;
 | 
			
		||||
 | 
			
		||||
	if (fund != INT && fund != LONG)	{
 | 
			
		||||
	if (fund != INT && fund != LONG && fund != LNGLNG) {
 | 
			
		||||
		expr_error(*expp, "%s operand to %s",
 | 
			
		||||
				symbol2str(fund), symbol2str(oper));
 | 
			
		||||
		erroneous2int(expp);
 | 
			
		||||
| 
						 | 
				
			
			@ -486,6 +519,7 @@ void opnd2logical(register struct expr **expp, int oper)
 | 
			
		|||
	case SHORT:
 | 
			
		||||
	case INT:
 | 
			
		||||
	case LONG:
 | 
			
		||||
	case LNGLNG:
 | 
			
		||||
	case ENUM:
 | 
			
		||||
	case POINTER:
 | 
			
		||||
	case FLOAT:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,6 +58,7 @@ void ch3sel(struct expr **expp, int oper, struct idf *idf)
 | 
			
		|||
				break;
 | 
			
		||||
			case INT:
 | 
			
		||||
			case LONG:
 | 
			
		||||
			case LNGLNG:
 | 
			
		||||
				/* An error is given in idf2sdef() */
 | 
			
		||||
				ch3cast(expp, CAST, pa_type);
 | 
			
		||||
				sd = idf2sdef(idf, tp);
 | 
			
		||||
| 
						 | 
				
			
			@ -82,6 +83,7 @@ void ch3sel(struct expr **expp, int oper, struct idf *idf)
 | 
			
		|||
		break;
 | 
			
		||||
	case INT:
 | 
			
		||||
	case LONG:
 | 
			
		||||
	case LNGLNG:
 | 
			
		||||
		/* warning will be given by idf2sdef() */
 | 
			
		||||
		break;
 | 
			
		||||
	default:
 | 
			
		||||
| 
						 | 
				
			
			@ -679,6 +681,7 @@ int is_integral_type(register struct type *tp)
 | 
			
		|||
	case SHORT:
 | 
			
		||||
	case INT:
 | 
			
		||||
	case LONG:
 | 
			
		||||
	case LNGLNG:
 | 
			
		||||
	case ENUM:
 | 
			
		||||
		return 1;
 | 
			
		||||
#ifndef NOBITFIELD
 | 
			
		||||
| 
						 | 
				
			
			@ -697,6 +700,7 @@ int is_arith_type(register struct type *tp)
 | 
			
		|||
	case SHORT:
 | 
			
		||||
	case INT:
 | 
			
		||||
	case LONG:
 | 
			
		||||
	case LNGLNG:
 | 
			
		||||
	case ENUM:
 | 
			
		||||
	case FLOAT:
 | 
			
		||||
	case DOUBLE:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -101,6 +101,10 @@ void init_code(char *dst_file)
 | 
			
		|||
		stb_typedef(ushort_type, "unsigned short");
 | 
			
		||||
		stb_typedef(ulong_type, "unsigned long");
 | 
			
		||||
		stb_typedef(uint_type, "unsigned int");
 | 
			
		||||
		if (lnglng_size >= 0) {
 | 
			
		||||
			stb_typedef(lnglng_type, "long long");
 | 
			
		||||
			stb_typedef(ulnglng_type, "unsigned long long");
 | 
			
		||||
		}
 | 
			
		||||
		stb_typedef(float_type, "float");
 | 
			
		||||
		stb_typedef(double_type, "double");
 | 
			
		||||
		stb_typedef(lngdbl_type, "long double");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -137,6 +137,7 @@ static int convtype(register struct type *tp)
 | 
			
		|||
	case INT:
 | 
			
		||||
	case ERRONEOUS:
 | 
			
		||||
	case LONG:
 | 
			
		||||
	case LNGLNG:
 | 
			
		||||
	case ENUM:
 | 
			
		||||
		return tp->tp_unsigned ? T_UNSIGNED : T_SIGNED;
 | 
			
		||||
	case FLOAT:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -175,7 +175,11 @@ void init_cst(void)
 | 
			
		|||
	register int i = 0;
 | 
			
		||||
	register arith bt = (arith)0;
 | 
			
		||||
 | 
			
		||||
	while (!(bt < 0))	{
 | 
			
		||||
	/*	FIXME arith is insufficient for long long.  We ignore
 | 
			
		||||
		this problem and write masks up to full_mask[8], but
 | 
			
		||||
		masks are wrong after bt < 0.
 | 
			
		||||
	*/
 | 
			
		||||
	while (!(bt < 0) || i < 8) {
 | 
			
		||||
		bt = (bt << 8) + 0377, i++;
 | 
			
		||||
		if (i > MAXSIZE)
 | 
			
		||||
			fatal("array full_mask too small for this machine");
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -123,9 +123,13 @@ single_decl_specifier /* non_empty */ (register struct decspecs *ds;)
 | 
			
		|||
	}
 | 
			
		||||
|
 | 
			
		||||
	[ SHORT | LONG ]
 | 
			
		||||
	{	if (ds->ds_size)
 | 
			
		||||
			error("repeated size specifier");
 | 
			
		||||
		ds->ds_size = DOT;
 | 
			
		||||
	{	if (ds->ds_size == LONG && DOT == LONG)
 | 
			
		||||
			ds->ds_size = LNGLNG;
 | 
			
		||||
		else {
 | 
			
		||||
			if (ds->ds_size)
 | 
			
		||||
				error("repeated size specifier");
 | 
			
		||||
			ds->ds_size = DOT;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
|
 | 
			
		||||
	[ SIGNED | UNSIGNED ]
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -69,7 +69,8 @@ void do_decspecs(register struct decspecs *ds)
 | 
			
		|||
	}
 | 
			
		||||
	if (ds->ds_size)
 | 
			
		||||
	{
 | 
			
		||||
		register int ds_isshort = (ds->ds_size == SHORT);
 | 
			
		||||
		int ds_isshort = (ds->ds_size == SHORT);
 | 
			
		||||
		int ds_islong = (ds->ds_size == LONG);
 | 
			
		||||
 | 
			
		||||
		if (ds->ds_typedef)
 | 
			
		||||
			goto SIZE_ERROR;
 | 
			
		||||
| 
						 | 
				
			
			@ -78,10 +79,18 @@ void do_decspecs(register struct decspecs *ds)
 | 
			
		|||
		{
 | 
			
		||||
			if (ds_isshort)
 | 
			
		||||
				tp = short_type;
 | 
			
		||||
			else
 | 
			
		||||
			else if (ds_islong)
 | 
			
		||||
				tp = long_type;
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				assert(ds->ds_size == LNGLNG);
 | 
			
		||||
				if (no_long_long())
 | 
			
		||||
					tp = error_type;
 | 
			
		||||
				else
 | 
			
		||||
					tp = lnglng_type;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		else if (tp == double_type && !ds_isshort)
 | 
			
		||||
		else if (tp == double_type && ds_islong)
 | 
			
		||||
		{
 | 
			
		||||
			tp = lngdbl_type;
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -122,6 +131,11 @@ void do_decspecs(register struct decspecs *ds)
 | 
			
		|||
			if (ds_isunsigned)
 | 
			
		||||
				tp = ulong_type;
 | 
			
		||||
		}
 | 
			
		||||
		else if (tp == lnglng_type)
 | 
			
		||||
		{
 | 
			
		||||
			if (ds_isunsigned)
 | 
			
		||||
				tp = ulnglng_type;
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			SIGN_ERROR: error("%s with illegal type",
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -133,13 +133,15 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
 | 
			
		|||
		case '+':
 | 
			
		||||
			/*	We have the following possibilities :
 | 
			
		||||
				int + int, pointer + int, pointer + long,
 | 
			
		||||
				long + long, double + double
 | 
			
		||||
				long + long, long long + long long,
 | 
			
		||||
				double + double
 | 
			
		||||
			*/
 | 
			
		||||
			operands(expr, gencode);
 | 
			
		||||
			if (gencode) {
 | 
			
		||||
				switch (tp->tp_fund) {
 | 
			
		||||
				case INT:
 | 
			
		||||
				case LONG:
 | 
			
		||||
				case LNGLNG:
 | 
			
		||||
					if (tp->tp_unsigned)
 | 
			
		||||
						C_adu(tp->tp_size);
 | 
			
		||||
					else
 | 
			
		||||
| 
						 | 
				
			
			@ -165,6 +167,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
 | 
			
		|||
					switch (tp->tp_fund) {
 | 
			
		||||
					case INT:
 | 
			
		||||
					case LONG:
 | 
			
		||||
					case LNGLNG:
 | 
			
		||||
					case POINTER:
 | 
			
		||||
						C_ngi(tp->tp_size);
 | 
			
		||||
						break;
 | 
			
		||||
| 
						 | 
				
			
			@ -181,7 +184,8 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
 | 
			
		|||
			}
 | 
			
		||||
			/*	else binary; we have the following flavours:
 | 
			
		||||
				int - int, pointer - int, pointer - long,
 | 
			
		||||
				pointer - pointer, long - long, double - double
 | 
			
		||||
				pointer - pointer, long - long,
 | 
			
		||||
				long long - long long, double - double
 | 
			
		||||
			*/
 | 
			
		||||
			operands(expr, gencode);
 | 
			
		||||
			if (!gencode)
 | 
			
		||||
| 
						 | 
				
			
			@ -189,6 +193,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
 | 
			
		|||
			switch (tp->tp_fund) {
 | 
			
		||||
			case INT:
 | 
			
		||||
			case LONG:
 | 
			
		||||
			case LNGLNG:
 | 
			
		||||
				if (tp->tp_unsigned)
 | 
			
		||||
					C_sbu(tp->tp_size);
 | 
			
		||||
				else
 | 
			
		||||
| 
						 | 
				
			
			@ -224,6 +229,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
 | 
			
		|||
				switch (tp->tp_fund) {
 | 
			
		||||
				case INT:
 | 
			
		||||
				case LONG:
 | 
			
		||||
				case LNGLNG:
 | 
			
		||||
				case POINTER:
 | 
			
		||||
					if (tp->tp_unsigned)
 | 
			
		||||
						C_mlu(tp->tp_size);
 | 
			
		||||
| 
						 | 
				
			
			@ -246,6 +252,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
 | 
			
		|||
				switch (tp->tp_fund) {
 | 
			
		||||
				case INT:
 | 
			
		||||
				case LONG:
 | 
			
		||||
				case LNGLNG:
 | 
			
		||||
				case POINTER:
 | 
			
		||||
					if (tp->tp_unsigned)
 | 
			
		||||
						C_dvu(tp->tp_size);
 | 
			
		||||
| 
						 | 
				
			
			@ -264,7 +271,8 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
 | 
			
		|||
			break;
 | 
			
		||||
		case '%':
 | 
			
		||||
			operands(expr, gencode);
 | 
			
		||||
			assert(tp->tp_fund==INT || tp->tp_fund==LONG);
 | 
			
		||||
			assert(tp->tp_fund==INT || tp->tp_fund==LONG ||
 | 
			
		||||
			       tp->tp_fund==LNGLNG);
 | 
			
		||||
			if (gencode)
 | 
			
		||||
				if (tp->tp_unsigned)
 | 
			
		||||
					C_rmu(tp->tp_size);
 | 
			
		||||
| 
						 | 
				
			
			@ -301,6 +309,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
 | 
			
		|||
				switch (tp->tp_fund) {
 | 
			
		||||
				case INT:
 | 
			
		||||
				case LONG:
 | 
			
		||||
				case LNGLNG:
 | 
			
		||||
					if (left->ex_type->tp_unsigned)
 | 
			
		||||
						C_cmu(size);
 | 
			
		||||
					else
 | 
			
		||||
| 
						 | 
				
			
			@ -736,6 +745,7 @@ void assop(register struct type *type, int oper)
 | 
			
		|||
	case SHORT:
 | 
			
		||||
	case INT:
 | 
			
		||||
	case LONG:
 | 
			
		||||
	case LNGLNG:
 | 
			
		||||
	case ENUM:
 | 
			
		||||
		switch (oper) {
 | 
			
		||||
		case PLUSAB:
 | 
			
		||||
| 
						 | 
				
			
			@ -1014,10 +1024,13 @@ void load_val(register struct expr *expr, int rlval)
 | 
			
		|||
 | 
			
		||||
void load_cst(arith val, arith siz)
 | 
			
		||||
{
 | 
			
		||||
	/*	EM can't encode ldc with constant over 4 bytes.
 | 
			
		||||
		Such a constant must go into rom.
 | 
			
		||||
	*/
 | 
			
		||||
	if ((int)siz <= (int)word_size)
 | 
			
		||||
		C_loc(val);
 | 
			
		||||
	else
 | 
			
		||||
	if ((int)siz == (int)dword_size)
 | 
			
		||||
	if ((int)siz == (int)dword_size && (int)dword_size <= 4)
 | 
			
		||||
		C_ldc(val);
 | 
			
		||||
	else {
 | 
			
		||||
		label datlab;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -518,6 +518,7 @@ void check_ival(struct expr **expp, register struct type *tp)
 | 
			
		|||
	case SHORT:
 | 
			
		||||
	case INT:
 | 
			
		||||
	case LONG:
 | 
			
		||||
	case LNGLNG:
 | 
			
		||||
	case ENUM:
 | 
			
		||||
	case POINTER:
 | 
			
		||||
		ch3cast(expp, '=', tp);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -57,6 +57,7 @@ arith
 | 
			
		|||
	dword_size = (2 * SZ_WORD),
 | 
			
		||||
	int_size = SZ_INT,
 | 
			
		||||
	long_size = SZ_LONG,
 | 
			
		||||
	lnglng_size = SZ_LNGLNG,
 | 
			
		||||
	float_size = SZ_FLOAT,
 | 
			
		||||
	double_size = SZ_DOUBLE,
 | 
			
		||||
	lngdbl_size = SZ_LNGDBL,
 | 
			
		||||
| 
						 | 
				
			
			@ -67,6 +68,7 @@ int
 | 
			
		|||
	word_align = AL_WORD,
 | 
			
		||||
	int_align = AL_INT,
 | 
			
		||||
	long_align = AL_LONG,
 | 
			
		||||
	lnglng_align = AL_LNGLNG,
 | 
			
		||||
	float_align = AL_FLOAT,
 | 
			
		||||
	double_align = AL_DOUBLE,
 | 
			
		||||
	lngdbl_align = AL_LNGDBL,
 | 
			
		||||
| 
						 | 
				
			
			@ -227,6 +229,10 @@ static void init(void)
 | 
			
		|||
	long_type = standard_type(LONG, 0, long_align, long_size);
 | 
			
		||||
	ulong_type = standard_type(LONG, UNSIGNED, long_align, long_size);
 | 
			
		||||
 | 
			
		||||
	lnglng_type = standard_type(LNGLNG, 0, lnglng_align, lnglng_size);
 | 
			
		||||
	ulnglng_type = standard_type(LNGLNG, UNSIGNED, lnglng_align,
 | 
			
		||||
				     lnglng_size);
 | 
			
		||||
 | 
			
		||||
	float_type = standard_type(FLOAT, 0, float_align, float_size);
 | 
			
		||||
	double_type = standard_type(DOUBLE, 0, double_align, double_size);
 | 
			
		||||
	lngdbl_type = standard_type(LNGDBL, 0, lngdbl_align, lngdbl_size);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -159,6 +159,12 @@ next_option:			/* to allow combined one-char options */
 | 
			
		|||
				if (algn != 0)
 | 
			
		||||
					long_align = algn;
 | 
			
		||||
				break;
 | 
			
		||||
			case 'q':	/* long long	*/
 | 
			
		||||
				if (sz != (arith)0)
 | 
			
		||||
					lnglng_size = sz;
 | 
			
		||||
				if (algn != 0)
 | 
			
		||||
					lnglng_align = algn;
 | 
			
		||||
				break;
 | 
			
		||||
			case 'f':	/* float	*/
 | 
			
		||||
				if (sz != (arith)0)
 | 
			
		||||
					float_size = sz;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@
 | 
			
		|||
#ifndef NOCROSS
 | 
			
		||||
extern arith
 | 
			
		||||
	short_size, word_size, dword_size, int_size, long_size,
 | 
			
		||||
	lnglng_size,
 | 
			
		||||
	float_size, double_size, lngdbl_size,
 | 
			
		||||
	pointer_size;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -20,6 +21,7 @@ extern arith max_int, max_unsigned;	/* cstoper.c	*/
 | 
			
		|||
#define dword_size	((arith)2*SZ_WORD)
 | 
			
		||||
#define int_size	((arith)SZ_INT)
 | 
			
		||||
#define long_size	((arith)SZ_LONG)
 | 
			
		||||
#define lnglng_size	((arith)SZ_LNGLNG)
 | 
			
		||||
#define float_size	((arith)SZ_FLOAT)
 | 
			
		||||
#define double_size	((arith)SZ_DOUBLE)
 | 
			
		||||
#define	lngdbl_size	((arith)SZ_LNGDBL)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -74,9 +74,10 @@ static void adds_db_str(char *s)
 | 
			
		|||
 | 
			
		||||
static void stb_type(register struct type *tp)
 | 
			
		||||
{
 | 
			
		||||
	char buf[128];
 | 
			
		||||
	char buf[128], *range;
 | 
			
		||||
	static int stb_count;
 | 
			
		||||
	long l;
 | 
			
		||||
	int uns;
 | 
			
		||||
 | 
			
		||||
	if (tp->tp_dbindex > 0)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -101,18 +102,26 @@ static void stb_type(register struct type *tp)
 | 
			
		|||
		break;
 | 
			
		||||
	case INT:
 | 
			
		||||
	case LONG:
 | 
			
		||||
	case LNGLNG:
 | 
			
		||||
	case CHAR:
 | 
			
		||||
	case SHORT:
 | 
			
		||||
		l = full_mask[(int) tp->tp_size];
 | 
			
		||||
		if (tp->tp_unsigned)
 | 
			
		||||
		switch ((tp->tp_size << 3) + !tp->tp_unsigned)
 | 
			
		||||
		{
 | 
			
		||||
			adds_db_str(sprint(buf, "r%d;0;%ld", tp->tp_dbindex, l));
 | 
			
		||||
		}
 | 
			
		||||
		else
 | 
			
		||||
		{
 | 
			
		||||
			l &= ~(1L << ((int) tp->tp_size * 8 - 1));
 | 
			
		||||
			adds_db_str(sprint(buf, "r%d;%ld;%ld", tp->tp_dbindex, -l - 1, l));
 | 
			
		||||
#define R(s) range = #s; break
 | 
			
		||||
		case 0010: R(0;255);
 | 
			
		||||
		case 0011: R(-128;127);
 | 
			
		||||
		case 0020: R(0;65535);
 | 
			
		||||
		case 0021: R(-32768;32767);
 | 
			
		||||
		default:   R(0;-1); /* acts as 0;4294967295 */
 | 
			
		||||
		case 0041: R(-2147483648;2147483647);
 | 
			
		||||
		/*	The stabs reader in gdb(1) needs an octal integer
 | 
			
		||||
			when its value doesn't fit in type long.
 | 
			
		||||
		*/
 | 
			
		||||
		case 0100: R(0;01777777777777777777777);
 | 
			
		||||
		case 0101: R(01000000000000000000000;0777777777777777777777);
 | 
			
		||||
#undef R
 | 
			
		||||
		}
 | 
			
		||||
		adds_db_str(sprint(buf, "r%d;%s", tp->tp_dbindex, range));
 | 
			
		||||
		break;
 | 
			
		||||
	case FLOAT:
 | 
			
		||||
	case DOUBLE:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -360,6 +360,7 @@ add_field(
 | 
			
		|||
	case SHORT:
 | 
			
		||||
	case ENUM:
 | 
			
		||||
	case LONG:
 | 
			
		||||
	case LNGLNG:
 | 
			
		||||
		strict("non-portable field type");
 | 
			
		||||
	case INT:
 | 
			
		||||
		/* right type; size OK? */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,7 +61,7 @@ void code_startswitch(struct expr **expp)
 | 
			
		|||
	register label l_break = text_label();
 | 
			
		||||
	register struct switch_hdr *sh = new_switch_hdr();
 | 
			
		||||
	int fund = any2arith(expp, SWITCH);
 | 
			
		||||
				    /* INT, LONG, FLOAT, DOUBLE or LNGDBL */
 | 
			
		||||
			/* INT, LONG, LNGLNG, FLOAT, DOUBLE or LNGDBL */
 | 
			
		||||
	
 | 
			
		||||
	switch (fund) {
 | 
			
		||||
	case FLOAT:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -104,6 +104,7 @@ struct tokenname tkidf[] =	{	/* names of the identifier tokens */
 | 
			
		|||
 | 
			
		||||
#ifdef	____
 | 
			
		||||
struct tokenname tkfunny[] =	{	/* internal keywords */
 | 
			
		||||
	{LNGLNG, "long long"},
 | 
			
		||||
	{LNGDBL, "long double"},
 | 
			
		||||
	{ULONG, "unsigned long"},
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,7 @@
 | 
			
		|||
 */
 | 
			
		||||
struct type *schar_type, *uchar_type, *short_type, *ushort_type, *word_type,
 | 
			
		||||
		*uword_type, *int_type, *uint_type, *long_type, *ulong_type,
 | 
			
		||||
		*lnglng_type, *ulnglng_type,
 | 
			
		||||
		*float_type, *double_type, *lngdbl_type, *void_type, *string_type,
 | 
			
		||||
		*funint_type, *error_type;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -291,3 +292,20 @@ void completed(struct type *tp)
 | 
			
		|||
		atp = atp->next;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int no_long_long(void)
 | 
			
		||||
{
 | 
			
		||||
	static int shown = 0;
 | 
			
		||||
 | 
			
		||||
	if (lnglng_size < 0)
 | 
			
		||||
	{
 | 
			
		||||
		if (!shown)
 | 
			
		||||
		{
 | 
			
		||||
			error("no long long for this machine");
 | 
			
		||||
			shown = 1;
 | 
			
		||||
		}
 | 
			
		||||
		return 1;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
		return 0;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -71,6 +71,7 @@ extern struct type
 | 
			
		|||
	*word_type, *uword_type,
 | 
			
		||||
	*int_type, *uint_type,
 | 
			
		||||
	*long_type, *ulong_type,
 | 
			
		||||
	*lnglng_type, *ulnglng_type,
 | 
			
		||||
	*float_type, *double_type, *lngdbl_type,
 | 
			
		||||
	*void_type,
 | 
			
		||||
	*string_type, *funint_type, *error_type;
 | 
			
		||||
| 
						 | 
				
			
			@ -93,6 +94,7 @@ void idf2type(struct idf *idf, struct type **tpp);
 | 
			
		|||
arith align(arith pos, int al);
 | 
			
		||||
struct type * standard_type(int fund, int sgn, int algn, arith sz);
 | 
			
		||||
void completed(struct type *tp);
 | 
			
		||||
int no_long_long(void);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* ALLOCDEF "type" 50 */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,7 +23,8 @@ var CPP_F=-D__unix
 | 
			
		|||
var ALIGN=-a0:4 -a1:4 -a2:4 -a3:4 -b0:0x08048054
 | 
			
		||||
var C_LIB={PLATFORMDIR}/libc-ansi.a
 | 
			
		||||
# bitfields reversed for compatibility with (g)cc.
 | 
			
		||||
var CC_ALIGN=-Vr
 | 
			
		||||
# long long enabled.
 | 
			
		||||
var CC_ALIGN=-Vrq8.4
 | 
			
		||||
var OLD_C_LIB={C_LIB}
 | 
			
		||||
var MACHOPT_F=-m10
 | 
			
		||||
var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		
		Reference in a new issue