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
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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 ((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-
|
if (convert1 && !shifting) /* ??? */
|
||||||
verted to long int.
|
t1 = int2int(e1p, convert1);
|
||||||
*/
|
if (convert2)
|
||||||
if (t1 == LONG && t2 != LONG)
|
t2 = int2int(e2p, convert2);
|
||||||
t2 = int2int(e2p, long_type);
|
|
||||||
else
|
|
||||||
if (t2 == LONG && t1 != LONG && !shifting) /* ??? */
|
|
||||||
t1 = int2int(e1p, long_type);
|
|
||||||
|
|
||||||
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:
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -123,9 +123,13 @@ single_decl_specifier /* non_empty */ (register struct decspecs *ds;)
|
||||||
}
|
}
|
||||||
|
|
|
|
||||||
[ SHORT | LONG ]
|
[ SHORT | LONG ]
|
||||||
{ if (ds->ds_size)
|
{ if (ds->ds_size == LONG && DOT == LONG)
|
||||||
error("repeated size specifier");
|
ds->ds_size = LNGLNG;
|
||||||
ds->ds_size = DOT;
|
else {
|
||||||
|
if (ds->ds_size)
|
||||||
|
error("repeated size specifier");
|
||||||
|
ds->ds_size = DOT;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
|
||||||
[ SIGNED | UNSIGNED ]
|
[ SIGNED | UNSIGNED ]
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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? */
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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"},
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue