From 007a63d52987dcad3719f1bb7dc5a7426789098a Mon Sep 17 00:00:00 2001 From: George Koehler Date: Mon, 2 Sep 2019 11:24:44 -0400 Subject: [PATCH] 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. --- lang/cem/cemcom.ansi/BigPars | 2 + lang/cem/cemcom.ansi/SmallPars | 2 + lang/cem/cemcom.ansi/align.h | 2 + lang/cem/cemcom.ansi/arith.c | 102 ++++++++++++++++++++---------- lang/cem/cemcom.ansi/ch3.c | 4 ++ lang/cem/cemcom.ansi/code.c | 4 ++ lang/cem/cemcom.ansi/conversion.c | 1 + lang/cem/cemcom.ansi/cstoper.c | 6 +- lang/cem/cemcom.ansi/declar.g | 10 ++- lang/cem/cemcom.ansi/decspecs.c | 20 +++++- lang/cem/cemcom.ansi/eval.c | 21 ++++-- lang/cem/cemcom.ansi/ival.g | 1 + lang/cem/cemcom.ansi/main.c | 6 ++ lang/cem/cemcom.ansi/options.c | 6 ++ lang/cem/cemcom.ansi/sizes.h | 2 + lang/cem/cemcom.ansi/stab.c | 27 +++++--- lang/cem/cemcom.ansi/struct.c | 1 + lang/cem/cemcom.ansi/switch.c | 2 +- lang/cem/cemcom.ansi/tokenname.c | 1 + lang/cem/cemcom.ansi/type.c | 18 ++++++ lang/cem/cemcom.ansi/type.str | 2 + plat/linux386/descr | 3 +- 22 files changed, 187 insertions(+), 56 deletions(-) diff --git a/lang/cem/cemcom.ansi/BigPars b/lang/cem/cemcom.ansi/BigPars index bf92e22fe..ad758c8a6 100644 --- a/lang/cem/cemcom.ansi/BigPars +++ b/lang/cem/cemcom.ansi/BigPars @@ -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 diff --git a/lang/cem/cemcom.ansi/SmallPars b/lang/cem/cemcom.ansi/SmallPars index 4ef50e48e..01f7073b1 100644 --- a/lang/cem/cemcom.ansi/SmallPars +++ b/lang/cem/cemcom.ansi/SmallPars @@ -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 diff --git a/lang/cem/cemcom.ansi/align.h b/lang/cem/cemcom.ansi/align.h index 79b9be97b..67bb24265 100644 --- a/lang/cem/cemcom.ansi/align.h +++ b/lang/cem/cemcom.ansi/align.h @@ -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) diff --git a/lang/cem/cemcom.ansi/arith.c b/lang/cem/cemcom.ansi/arith.c index 6504a7305..e1c3311c3 100644 --- a/lang/cem/cemcom.ansi/arith.c +++ b/lang/cem/cemcom.ansi/arith.c @@ -12,6 +12,7 @@ */ #include +#include #include "parameters.h" #include #include @@ -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_sizeex_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: diff --git a/lang/cem/cemcom.ansi/ch3.c b/lang/cem/cemcom.ansi/ch3.c index 3132ccbb9..69c75fed6 100644 --- a/lang/cem/cemcom.ansi/ch3.c +++ b/lang/cem/cemcom.ansi/ch3.c @@ -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: diff --git a/lang/cem/cemcom.ansi/code.c b/lang/cem/cemcom.ansi/code.c index d50700056..cef708cbf 100644 --- a/lang/cem/cemcom.ansi/code.c +++ b/lang/cem/cemcom.ansi/code.c @@ -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"); diff --git a/lang/cem/cemcom.ansi/conversion.c b/lang/cem/cemcom.ansi/conversion.c index 60d4c45b5..13af3cef8 100644 --- a/lang/cem/cemcom.ansi/conversion.c +++ b/lang/cem/cemcom.ansi/conversion.c @@ -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: diff --git a/lang/cem/cemcom.ansi/cstoper.c b/lang/cem/cemcom.ansi/cstoper.c index 774e356d6..61c3fd6e3 100644 --- a/lang/cem/cemcom.ansi/cstoper.c +++ b/lang/cem/cemcom.ansi/cstoper.c @@ -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"); diff --git a/lang/cem/cemcom.ansi/declar.g b/lang/cem/cemcom.ansi/declar.g index 92adefb5f..8bec8e72d 100644 --- a/lang/cem/cemcom.ansi/declar.g +++ b/lang/cem/cemcom.ansi/declar.g @@ -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 ] diff --git a/lang/cem/cemcom.ansi/decspecs.c b/lang/cem/cemcom.ansi/decspecs.c index 42465e213..8af08eacb 100644 --- a/lang/cem/cemcom.ansi/decspecs.c +++ b/lang/cem/cemcom.ansi/decspecs.c @@ -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", diff --git a/lang/cem/cemcom.ansi/eval.c b/lang/cem/cemcom.ansi/eval.c index 352d590b3..338ca51cb 100644 --- a/lang/cem/cemcom.ansi/eval.c +++ b/lang/cem/cemcom.ansi/eval.c @@ -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; diff --git a/lang/cem/cemcom.ansi/ival.g b/lang/cem/cemcom.ansi/ival.g index 398343ed4..995d46248 100644 --- a/lang/cem/cemcom.ansi/ival.g +++ b/lang/cem/cemcom.ansi/ival.g @@ -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); diff --git a/lang/cem/cemcom.ansi/main.c b/lang/cem/cemcom.ansi/main.c index e7988bf66..da5ced81d 100644 --- a/lang/cem/cemcom.ansi/main.c +++ b/lang/cem/cemcom.ansi/main.c @@ -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); diff --git a/lang/cem/cemcom.ansi/options.c b/lang/cem/cemcom.ansi/options.c index 0c37c85d4..2cdfe3835 100644 --- a/lang/cem/cemcom.ansi/options.c +++ b/lang/cem/cemcom.ansi/options.c @@ -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; diff --git a/lang/cem/cemcom.ansi/sizes.h b/lang/cem/cemcom.ansi/sizes.h index 0f38c5668..f943d184b 100644 --- a/lang/cem/cemcom.ansi/sizes.h +++ b/lang/cem/cemcom.ansi/sizes.h @@ -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) diff --git a/lang/cem/cemcom.ansi/stab.c b/lang/cem/cemcom.ansi/stab.c index a7a7928c9..5a002301f 100644 --- a/lang/cem/cemcom.ansi/stab.c +++ b/lang/cem/cemcom.ansi/stab.c @@ -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: diff --git a/lang/cem/cemcom.ansi/struct.c b/lang/cem/cemcom.ansi/struct.c index b69acd206..d8f6ef2a6 100644 --- a/lang/cem/cemcom.ansi/struct.c +++ b/lang/cem/cemcom.ansi/struct.c @@ -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? */ diff --git a/lang/cem/cemcom.ansi/switch.c b/lang/cem/cemcom.ansi/switch.c index 24cb82c6f..7db1f28bd 100644 --- a/lang/cem/cemcom.ansi/switch.c +++ b/lang/cem/cemcom.ansi/switch.c @@ -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: diff --git a/lang/cem/cemcom.ansi/tokenname.c b/lang/cem/cemcom.ansi/tokenname.c index b430abbd8..fb3bae349 100644 --- a/lang/cem/cemcom.ansi/tokenname.c +++ b/lang/cem/cemcom.ansi/tokenname.c @@ -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"}, diff --git a/lang/cem/cemcom.ansi/type.c b/lang/cem/cemcom.ansi/type.c index 750ed9a8a..57a6cd98e 100644 --- a/lang/cem/cemcom.ansi/type.c +++ b/lang/cem/cemcom.ansi/type.c @@ -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; +} diff --git a/lang/cem/cemcom.ansi/type.str b/lang/cem/cemcom.ansi/type.str index b98ffbb6c..ada366231 100644 --- a/lang/cem/cemcom.ansi/type.str +++ b/lang/cem/cemcom.ansi/type.str @@ -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 */ diff --git a/plat/linux386/descr b/plat/linux386/descr index fd033f423..8a7dc5f47 100644 --- a/plat/linux386/descr +++ b/plat/linux386/descr @@ -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