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:
George Koehler 2019-09-02 11:24:44 -04:00
parent 893df4b79b
commit 007a63d529
22 changed files with 187 additions and 56 deletions

View file

@ -55,6 +55,7 @@
#define SZ_WORD 4 #define SZ_WORD 4
#define SZ_INT 4 #define SZ_INT 4
#define SZ_LONG 4 #define SZ_LONG 4
#define SZ_LNGLNG -1
#define SZ_FLOAT 4 #define SZ_FLOAT 4
#define SZ_DOUBLE 8 #define SZ_DOUBLE 8
#define SZ_LNGDBL 8 /* for now */ #define SZ_LNGDBL 8 /* for now */
@ -66,6 +67,7 @@
#define AL_WORD SZ_WORD #define AL_WORD SZ_WORD
#define AL_INT SZ_WORD #define AL_INT SZ_WORD
#define AL_LONG SZ_WORD #define AL_LONG SZ_WORD
#define AL_LNGLNG SZ_WORD
#define AL_FLOAT SZ_WORD #define AL_FLOAT SZ_WORD
#define AL_DOUBLE SZ_WORD #define AL_DOUBLE SZ_WORD
#define AL_LNGDBL SZ_WORD #define AL_LNGDBL SZ_WORD

View file

@ -55,6 +55,7 @@
#define SZ_WORD 4 #define SZ_WORD 4
#define SZ_INT 4 #define SZ_INT 4
#define SZ_LONG 4 #define SZ_LONG 4
#define SZ_LNGLNG -1
#define SZ_FLOAT 4 #define SZ_FLOAT 4
#define SZ_DOUBLE 8 #define SZ_DOUBLE 8
#define SZ_LNGDBL 8 /* for now */ #define SZ_LNGDBL 8 /* for now */
@ -66,6 +67,7 @@
#define AL_WORD SZ_WORD #define AL_WORD SZ_WORD
#define AL_INT SZ_WORD #define AL_INT SZ_WORD
#define AL_LONG SZ_WORD #define AL_LONG SZ_WORD
#define AL_LNGLNG SZ_WORD
#define AL_FLOAT SZ_WORD #define AL_FLOAT SZ_WORD
#define AL_DOUBLE SZ_WORD #define AL_DOUBLE SZ_WORD
#define AL_LNGDBL SZ_WORD #define AL_LNGDBL SZ_WORD

View file

@ -10,6 +10,7 @@
#ifndef NOCROSS #ifndef NOCROSS
extern int extern int
short_align, word_align, int_align, long_align, short_align, word_align, int_align, long_align,
lnglng_align,
float_align, double_align, lngdbl_align, float_align, double_align, lngdbl_align,
pointer_align, pointer_align,
struct_align, union_align; struct_align, union_align;
@ -18,6 +19,7 @@ extern int
#define word_align ((int)AL_WORD) #define word_align ((int)AL_WORD)
#define int_align ((int)AL_INT) #define int_align ((int)AL_INT)
#define long_align ((int)AL_LONG) #define long_align ((int)AL_LONG)
#define lnglng_align ((int)AL_LNGLNG)
#define float_align ((int)AL_FLOAT) #define float_align ((int)AL_FLOAT)
#define double_align ((int)AL_DOUBLE) #define double_align ((int)AL_DOUBLE)
#define lngdbl_align ((int)AL_LNGDBL) #define lngdbl_align ((int)AL_LNGDBL)

View file

@ -12,6 +12,7 @@
*/ */
#include <assert.h> #include <assert.h>
#include <stddef.h>
#include "parameters.h" #include "parameters.h"
#include <alloc.h> #include <alloc.h>
#include <flt_arith.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 have a floating type, in which case the flags shouldn't
travel upward in the expression tree. 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 int shifting = (oper == LEFT || oper == RIGHT
|| oper == LEFTAB || oper == RIGHTAB); || oper == LEFTAB || oper == RIGHTAB);
int ptrdiff = 0; 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 (int_size != pointer_size) {
if (ptrdiff = ((*e1p)->ex_flags & EX_PTRDIFF) if (ptrdiff = ((*e1p)->ex_flags & EX_PTRDIFF)
|| ((*e2p)->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; ptrdiff = 0;
if (!((*e2p)->ex_flags & EX_PTRDIFF) && t2 == LONG if (!((*e2p)->ex_flags & EX_PTRDIFF)
&& (t2 == LONG || t2 == LNGLNG)
&& !shifting) && !shifting)
ptrdiff = 0; ptrdiff = 0;
} }
@ -67,7 +71,9 @@ void arithbalance(register struct expr **e1p, int oper, register struct expr **e
(*e2p)->ex_flags &= ~EX_PTRDIFF; (*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 /* If any operand has the type long double, the other operand
is converted to long double. is converted to long double.
@ -82,11 +88,12 @@ void arithbalance(register struct expr **e1p, int oper, register struct expr **e
} }
return; return;
} else if (t2 == LNGDBL) { } else if (t2 == LNGDBL) {
if (t1 != LNGDBL) if (t1 != LNGDBL) {
if (t1 == DOUBLE || t1 == FLOAT) if (t1 == DOUBLE || t1 == FLOAT)
float2float(e1p, lngdbl_type); float2float(e1p, lngdbl_type);
else else
int2float(e1p, lngdbl_type); int2float(e1p, lngdbl_type);
}
return; return;
} }
@ -120,38 +127,63 @@ void arithbalance(register struct expr **e1p, int oper, register struct expr **e
return; return;
} }
/* Now they are INT or LONG */ /* Now they are INT, LONG or LNGLNG */
u1 = (*e1p)->ex_type->tp_unsigned; u1 = (*e1p)->ex_type->tp_unsigned;
u2 = (*e2p)->ex_type->tp_unsigned; u2 = (*e2p)->ex_type->tp_unsigned;
convert1 = NULL;
convert2 = NULL;
/* If either operand has type unsigned long int, the other /* If either operand is a long long, the other operand
operand is converted to unsigned long int. is converted to long long; else if either operand is
*/ a long, the other operand is converted to a long.
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 one operand has type long int and the other has type unsigned If one operand is signed and the other operand is
int, if a long int can represent all values of an unsigned int, unsigned, if the signed type can represent all values
the operand of type unsigned int is converted to long int; if of the unsigned type, the unsigned operand is
a long int cannot represent all values of an unsigned int, converted to the signed type, else both operands are
both operands are converted to unsigned long int. converted to an unsigned type.
*/ */
if (t1 == LONG && t2 == INT && u2) if (t1 == LNGLNG && u1 && (t2 != LNGLNG || !u2))
t2 = int2int(e2p, (int_size<long_size)? long_type : ulong_type); convert2 = ulnglng_type;
else if (t2 == LONG && t1 == INT && u1 && !shifting) /* ??? */ else if (t2 == LNGLNG && u2 && (t1 != LNGLNG || !u1))
t1 = int2int(e1p, (int_size<long_size)? long_type : ulong_type); convert1 = ulnglng_type;
else if (t1 == LNGLNG && t2 != LNGLNG && u2) {
/* If either operand has type long int, the other operand is con- if ((t2 == LONG ? long_size : int_size) < lnglng_size)
verted to long int. convert2 = lnglng_type;
*/
if (t1 == LONG && t2 != LONG)
t2 = int2int(e2p, long_type);
else else
if (t2 == LONG && t1 != LONG && !shifting) /* ??? */ convert1 = convert2 = ulnglng_type;
t1 = int2int(e1p, long_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 (convert1 && !shifting) /* ??? */
t1 = int2int(e1p, convert1);
if (convert2)
t2 = int2int(e2p, convert2);
u1 = (*e1p)->ex_type->tp_unsigned; u1 = (*e1p)->ex_type->tp_unsigned;
u2 = (*e2p)->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. Otherwise, both operands have type int.
*/ */
if (u1 && !u2 && !shifting) if (u1 && !u2 && !shifting)
t2 = int2int(e2p, (t1 == LONG) ? ulong_type : uint_type); t2 = int2int(e2p, uint_type);
else else
if (!u1 && u2 && !shifting) if (!u1 && u2 && !shifting)
t1 = int2int(e1p, (t2 == LONG) ? ulong_type : uint_type); t1 = int2int(e1p, uint_type);
if (int_size != pointer_size) { if (int_size != pointer_size) {
if (ptrdiff) { if (ptrdiff) {
@ -259,6 +291,7 @@ any2arith(register struct expr **expp, register int oper)
break; break;
case INT: case INT:
case LONG: case LONG:
case LNGLNG:
break; break;
case ENUM: case ENUM:
#ifndef LINT #ifndef LINT
@ -457,7 +490,7 @@ void opnd2integral(register struct expr **expp, int oper)
{ {
register int fund = (*expp)->ex_type->tp_fund; 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", expr_error(*expp, "%s operand to %s",
symbol2str(fund), symbol2str(oper)); symbol2str(fund), symbol2str(oper));
erroneous2int(expp); erroneous2int(expp);
@ -486,6 +519,7 @@ void opnd2logical(register struct expr **expp, int oper)
case SHORT: case SHORT:
case INT: case INT:
case LONG: case LONG:
case LNGLNG:
case ENUM: case ENUM:
case POINTER: case POINTER:
case FLOAT: case FLOAT:

View file

@ -58,6 +58,7 @@ void ch3sel(struct expr **expp, int oper, struct idf *idf)
break; break;
case INT: case INT:
case LONG: case LONG:
case LNGLNG:
/* An error is given in idf2sdef() */ /* An error is given in idf2sdef() */
ch3cast(expp, CAST, pa_type); ch3cast(expp, CAST, pa_type);
sd = idf2sdef(idf, tp); sd = idf2sdef(idf, tp);
@ -82,6 +83,7 @@ void ch3sel(struct expr **expp, int oper, struct idf *idf)
break; break;
case INT: case INT:
case LONG: case LONG:
case LNGLNG:
/* warning will be given by idf2sdef() */ /* warning will be given by idf2sdef() */
break; break;
default: default:
@ -679,6 +681,7 @@ int is_integral_type(register struct type *tp)
case SHORT: case SHORT:
case INT: case INT:
case LONG: case LONG:
case LNGLNG:
case ENUM: case ENUM:
return 1; return 1;
#ifndef NOBITFIELD #ifndef NOBITFIELD
@ -697,6 +700,7 @@ int is_arith_type(register struct type *tp)
case SHORT: case SHORT:
case INT: case INT:
case LONG: case LONG:
case LNGLNG:
case ENUM: case ENUM:
case FLOAT: case FLOAT:
case DOUBLE: case DOUBLE:

View file

@ -101,6 +101,10 @@ void init_code(char *dst_file)
stb_typedef(ushort_type, "unsigned short"); stb_typedef(ushort_type, "unsigned short");
stb_typedef(ulong_type, "unsigned long"); stb_typedef(ulong_type, "unsigned long");
stb_typedef(uint_type, "unsigned int"); 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(float_type, "float");
stb_typedef(double_type, "double"); stb_typedef(double_type, "double");
stb_typedef(lngdbl_type, "long double"); stb_typedef(lngdbl_type, "long double");

View file

@ -137,6 +137,7 @@ static int convtype(register struct type *tp)
case INT: case INT:
case ERRONEOUS: case ERRONEOUS:
case LONG: case LONG:
case LNGLNG:
case ENUM: case ENUM:
return tp->tp_unsigned ? T_UNSIGNED : T_SIGNED; return tp->tp_unsigned ? T_UNSIGNED : T_SIGNED;
case FLOAT: case FLOAT:

View file

@ -175,7 +175,11 @@ void init_cst(void)
register int i = 0; register int i = 0;
register arith bt = (arith)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++; bt = (bt << 8) + 0377, i++;
if (i > MAXSIZE) if (i > MAXSIZE)
fatal("array full_mask too small for this machine"); fatal("array full_mask too small for this machine");

View file

@ -123,10 +123,14 @@ single_decl_specifier /* non_empty */ (register struct decspecs *ds;)
} }
| |
[ SHORT | LONG ] [ SHORT | LONG ]
{ if (ds->ds_size) { if (ds->ds_size == LONG && DOT == LONG)
ds->ds_size = LNGLNG;
else {
if (ds->ds_size)
error("repeated size specifier"); error("repeated size specifier");
ds->ds_size = DOT; ds->ds_size = DOT;
} }
}
| |
[ SIGNED | UNSIGNED ] [ SIGNED | UNSIGNED ]
{ if (ds->ds_unsigned != 0) { if (ds->ds_unsigned != 0)

View file

@ -69,7 +69,8 @@ void do_decspecs(register struct decspecs *ds)
} }
if (ds->ds_size) 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) if (ds->ds_typedef)
goto SIZE_ERROR; goto SIZE_ERROR;
@ -78,10 +79,18 @@ void do_decspecs(register struct decspecs *ds)
{ {
if (ds_isshort) if (ds_isshort)
tp = short_type; tp = short_type;
else else if (ds_islong)
tp = long_type; 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; tp = lngdbl_type;
} }
@ -122,6 +131,11 @@ void do_decspecs(register struct decspecs *ds)
if (ds_isunsigned) if (ds_isunsigned)
tp = ulong_type; tp = ulong_type;
} }
else if (tp == lnglng_type)
{
if (ds_isunsigned)
tp = ulnglng_type;
}
else else
{ {
SIGN_ERROR: error("%s with illegal type", SIGN_ERROR: error("%s with illegal type",

View file

@ -133,13 +133,15 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
case '+': case '+':
/* We have the following possibilities : /* We have the following possibilities :
int + int, pointer + int, pointer + long, int + int, pointer + int, pointer + long,
long + long, double + double long + long, long long + long long,
double + double
*/ */
operands(expr, gencode); operands(expr, gencode);
if (gencode) { if (gencode) {
switch (tp->tp_fund) { switch (tp->tp_fund) {
case INT: case INT:
case LONG: case LONG:
case LNGLNG:
if (tp->tp_unsigned) if (tp->tp_unsigned)
C_adu(tp->tp_size); C_adu(tp->tp_size);
else else
@ -165,6 +167,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
switch (tp->tp_fund) { switch (tp->tp_fund) {
case INT: case INT:
case LONG: case LONG:
case LNGLNG:
case POINTER: case POINTER:
C_ngi(tp->tp_size); C_ngi(tp->tp_size);
break; 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: /* else binary; we have the following flavours:
int - int, pointer - int, pointer - long, 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); operands(expr, gencode);
if (!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) { switch (tp->tp_fund) {
case INT: case INT:
case LONG: case LONG:
case LNGLNG:
if (tp->tp_unsigned) if (tp->tp_unsigned)
C_sbu(tp->tp_size); C_sbu(tp->tp_size);
else else
@ -224,6 +229,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
switch (tp->tp_fund) { switch (tp->tp_fund) {
case INT: case INT:
case LONG: case LONG:
case LNGLNG:
case POINTER: case POINTER:
if (tp->tp_unsigned) if (tp->tp_unsigned)
C_mlu(tp->tp_size); 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) { switch (tp->tp_fund) {
case INT: case INT:
case LONG: case LONG:
case LNGLNG:
case POINTER: case POINTER:
if (tp->tp_unsigned) if (tp->tp_unsigned)
C_dvu(tp->tp_size); C_dvu(tp->tp_size);
@ -264,7 +271,8 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
break; break;
case '%': case '%':
operands(expr, gencode); 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 (gencode)
if (tp->tp_unsigned) if (tp->tp_unsigned)
C_rmu(tp->tp_size); 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) { switch (tp->tp_fund) {
case INT: case INT:
case LONG: case LONG:
case LNGLNG:
if (left->ex_type->tp_unsigned) if (left->ex_type->tp_unsigned)
C_cmu(size); C_cmu(size);
else else
@ -736,6 +745,7 @@ void assop(register struct type *type, int oper)
case SHORT: case SHORT:
case INT: case INT:
case LONG: case LONG:
case LNGLNG:
case ENUM: case ENUM:
switch (oper) { switch (oper) {
case PLUSAB: case PLUSAB:
@ -1014,10 +1024,13 @@ void load_val(register struct expr *expr, int rlval)
void load_cst(arith val, arith siz) 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) if ((int)siz <= (int)word_size)
C_loc(val); C_loc(val);
else else
if ((int)siz == (int)dword_size) if ((int)siz == (int)dword_size && (int)dword_size <= 4)
C_ldc(val); C_ldc(val);
else { else {
label datlab; label datlab;

View file

@ -518,6 +518,7 @@ void check_ival(struct expr **expp, register struct type *tp)
case SHORT: case SHORT:
case INT: case INT:
case LONG: case LONG:
case LNGLNG:
case ENUM: case ENUM:
case POINTER: case POINTER:
ch3cast(expp, '=', tp); ch3cast(expp, '=', tp);

View file

@ -57,6 +57,7 @@ arith
dword_size = (2 * SZ_WORD), dword_size = (2 * SZ_WORD),
int_size = SZ_INT, int_size = SZ_INT,
long_size = SZ_LONG, long_size = SZ_LONG,
lnglng_size = SZ_LNGLNG,
float_size = SZ_FLOAT, float_size = SZ_FLOAT,
double_size = SZ_DOUBLE, double_size = SZ_DOUBLE,
lngdbl_size = SZ_LNGDBL, lngdbl_size = SZ_LNGDBL,
@ -67,6 +68,7 @@ int
word_align = AL_WORD, word_align = AL_WORD,
int_align = AL_INT, int_align = AL_INT,
long_align = AL_LONG, long_align = AL_LONG,
lnglng_align = AL_LNGLNG,
float_align = AL_FLOAT, float_align = AL_FLOAT,
double_align = AL_DOUBLE, double_align = AL_DOUBLE,
lngdbl_align = AL_LNGDBL, lngdbl_align = AL_LNGDBL,
@ -227,6 +229,10 @@ static void init(void)
long_type = standard_type(LONG, 0, long_align, long_size); long_type = standard_type(LONG, 0, long_align, long_size);
ulong_type = standard_type(LONG, UNSIGNED, 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); float_type = standard_type(FLOAT, 0, float_align, float_size);
double_type = standard_type(DOUBLE, 0, double_align, double_size); double_type = standard_type(DOUBLE, 0, double_align, double_size);
lngdbl_type = standard_type(LNGDBL, 0, lngdbl_align, lngdbl_size); lngdbl_type = standard_type(LNGDBL, 0, lngdbl_align, lngdbl_size);

View file

@ -159,6 +159,12 @@ next_option: /* to allow combined one-char options */
if (algn != 0) if (algn != 0)
long_align = algn; long_align = algn;
break; break;
case 'q': /* long long */
if (sz != (arith)0)
lnglng_size = sz;
if (algn != 0)
lnglng_align = algn;
break;
case 'f': /* float */ case 'f': /* float */
if (sz != (arith)0) if (sz != (arith)0)
float_size = sz; float_size = sz;

View file

@ -10,6 +10,7 @@
#ifndef NOCROSS #ifndef NOCROSS
extern arith extern arith
short_size, word_size, dword_size, int_size, long_size, short_size, word_size, dword_size, int_size, long_size,
lnglng_size,
float_size, double_size, lngdbl_size, float_size, double_size, lngdbl_size,
pointer_size; pointer_size;
@ -20,6 +21,7 @@ extern arith max_int, max_unsigned; /* cstoper.c */
#define dword_size ((arith)2*SZ_WORD) #define dword_size ((arith)2*SZ_WORD)
#define int_size ((arith)SZ_INT) #define int_size ((arith)SZ_INT)
#define long_size ((arith)SZ_LONG) #define long_size ((arith)SZ_LONG)
#define lnglng_size ((arith)SZ_LNGLNG)
#define float_size ((arith)SZ_FLOAT) #define float_size ((arith)SZ_FLOAT)
#define double_size ((arith)SZ_DOUBLE) #define double_size ((arith)SZ_DOUBLE)
#define lngdbl_size ((arith)SZ_LNGDBL) #define lngdbl_size ((arith)SZ_LNGDBL)

View file

@ -74,9 +74,10 @@ static void adds_db_str(char *s)
static void stb_type(register struct type *tp) static void stb_type(register struct type *tp)
{ {
char buf[128]; char buf[128], *range;
static int stb_count; static int stb_count;
long l; long l;
int uns;
if (tp->tp_dbindex > 0) if (tp->tp_dbindex > 0)
{ {
@ -101,18 +102,26 @@ static void stb_type(register struct type *tp)
break; break;
case INT: case INT:
case LONG: case LONG:
case LNGLNG:
case CHAR: case CHAR:
case SHORT: case SHORT:
l = full_mask[(int) tp->tp_size]; switch ((tp->tp_size << 3) + !tp->tp_unsigned)
if (tp->tp_unsigned)
{ {
adds_db_str(sprint(buf, "r%d;0;%ld", tp->tp_dbindex, l)); #define R(s) range = #s; break
} case 0010: R(0;255);
else case 0011: R(-128;127);
{ case 0020: R(0;65535);
l &= ~(1L << ((int) tp->tp_size * 8 - 1)); case 0021: R(-32768;32767);
adds_db_str(sprint(buf, "r%d;%ld;%ld", tp->tp_dbindex, -l - 1, l)); 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; break;
case FLOAT: case FLOAT:
case DOUBLE: case DOUBLE:

View file

@ -360,6 +360,7 @@ add_field(
case SHORT: case SHORT:
case ENUM: case ENUM:
case LONG: case LONG:
case LNGLNG:
strict("non-portable field type"); strict("non-portable field type");
case INT: case INT:
/* right type; size OK? */ /* right type; size OK? */

View file

@ -61,7 +61,7 @@ void code_startswitch(struct expr **expp)
register label l_break = text_label(); register label l_break = text_label();
register struct switch_hdr *sh = new_switch_hdr(); register struct switch_hdr *sh = new_switch_hdr();
int fund = any2arith(expp, SWITCH); int fund = any2arith(expp, SWITCH);
/* INT, LONG, FLOAT, DOUBLE or LNGDBL */ /* INT, LONG, LNGLNG, FLOAT, DOUBLE or LNGDBL */
switch (fund) { switch (fund) {
case FLOAT: case FLOAT:

View file

@ -104,6 +104,7 @@ struct tokenname tkidf[] = { /* names of the identifier tokens */
#ifdef ____ #ifdef ____
struct tokenname tkfunny[] = { /* internal keywords */ struct tokenname tkfunny[] = { /* internal keywords */
{LNGLNG, "long long"},
{LNGDBL, "long double"}, {LNGDBL, "long double"},
{ULONG, "unsigned long"}, {ULONG, "unsigned long"},

View file

@ -25,6 +25,7 @@
*/ */
struct type *schar_type, *uchar_type, *short_type, *ushort_type, *word_type, struct type *schar_type, *uchar_type, *short_type, *ushort_type, *word_type,
*uword_type, *int_type, *uint_type, *long_type, *ulong_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, *float_type, *double_type, *lngdbl_type, *void_type, *string_type,
*funint_type, *error_type; *funint_type, *error_type;
@ -291,3 +292,20 @@ void completed(struct type *tp)
atp = atp->next; 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;
}

View file

@ -71,6 +71,7 @@ extern struct type
*word_type, *uword_type, *word_type, *uword_type,
*int_type, *uint_type, *int_type, *uint_type,
*long_type, *ulong_type, *long_type, *ulong_type,
*lnglng_type, *ulnglng_type,
*float_type, *double_type, *lngdbl_type, *float_type, *double_type, *lngdbl_type,
*void_type, *void_type,
*string_type, *funint_type, *error_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); arith align(arith pos, int al);
struct type * standard_type(int fund, int sgn, int algn, arith sz); struct type * standard_type(int fund, int sgn, int algn, arith sz);
void completed(struct type *tp); void completed(struct type *tp);
int no_long_long(void);
/* ALLOCDEF "type" 50 */ /* ALLOCDEF "type" 50 */

View file

@ -23,7 +23,8 @@ var CPP_F=-D__unix
var ALIGN=-a0:4 -a1:4 -a2:4 -a3:4 -b0:0x08048054 var ALIGN=-a0:4 -a1:4 -a2:4 -a3:4 -b0:0x08048054
var C_LIB={PLATFORMDIR}/libc-ansi.a var C_LIB={PLATFORMDIR}/libc-ansi.a
# bitfields reversed for compatibility with (g)cc. # 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 OLD_C_LIB={C_LIB}
var MACHOPT_F=-m10 var MACHOPT_F=-m10
var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr var EGO_PLAT_FLAGS=-M{EM}/share/ack/ego/{ARCH}.descr