diff --git a/lang/cem/cemcom.ansi/BigPars b/lang/cem/cemcom.ansi/BigPars index ad758c8a6..882841e64 100644 --- a/lang/cem/cemcom.ansi/BigPars +++ b/lang/cem/cemcom.ansi/BigPars @@ -117,11 +117,6 @@ /*#define NOBITFIELD 1 *//* if NOT defined, implement bitfields */ -!File: spec_arith.h -/* describes internal compiler arithmetics */ -#undef SPECIAL_ARITHMETICS /* something different from native long */ - - !File: static.h #define GSTATIC /* for large global "static" arrays */ diff --git a/lang/cem/cemcom.ansi/LLlex.c b/lang/cem/cemcom.ansi/LLlex.c index d4be03449..da18e42cb 100644 --- a/lang/cem/cemcom.ansi/LLlex.c +++ b/lang/cem/cemcom.ansi/LLlex.c @@ -17,6 +17,7 @@ #include "Lpars.h" #include "class.h" #include "sizes.h" +#include "type.h" /* no_long_long() */ #include "error.h" #include "domacro.h" #include "specials.h" /* registration of special identifiers */ @@ -37,7 +38,6 @@ int LexSave = 0; /* last character read by GetChar */ #define FLG_ESEEN 0x01 /* possibly a floating point number */ #define FLG_DOTSEEN 0x02 /* certainly a floating point number */ -extern arith full_mask[]; #ifdef LINT extern int lint_skip_comment; @@ -594,10 +594,12 @@ static void strflt2tok(char fltbuf[], struct token* ptok) static void strint2tok(char intbuf[], struct token* ptok) { register char* cp = intbuf; - int base = 10; - arith val = 0, dig, ubound; - int uns_flg = 0, lng_flg = 0, malformed = 0, ovfl = 0; - int fund; + int base = 10, dig; + unsigned writh val = 0, ubound; + int uns_flg = 0, lng_flg = 0, lnglng_flg = 0; + int malformed = 0, ovfl = 0; + unsigned writh uint_mask, ulng_mask, ulnglng_mask; + int cut, fund; assert(*cp != '-'); if (*cp == '0') @@ -611,11 +613,8 @@ static void strint2tok(char intbuf[], struct token* ptok) else base = 8; } - /* The upperbound will be the same as when computed with - * max_unsigned_arith / base (since base is even). The problem here - * is that unsigned arith is not accepted by all compilers. - */ - ubound = max_arith / (base / 2); + /* The upperbound checks if val * base would overflow. */ + ubound = ~(unsigned writh)0 / base; while (is_hex(*cp)) { @@ -626,10 +625,10 @@ static void strint2tok(char intbuf[], struct token* ptok) } else { - if (val < 0 || val > ubound) + if (val > ubound) ovfl++; val *= base; - if (val < 0 && val + dig >= 0) + if (val > val + dig) ovfl++; val += dig; } @@ -639,7 +638,16 @@ static void strint2tok(char intbuf[], struct token* ptok) while (*cp) { if (*cp == 'l' || *cp == 'L') - lng_flg++; + { + if (*cp == *(cp + 1)) + { + /* 'll' or 'LL' */ + lnglng_flg++; + cp++; + } + else + lng_flg++; + } else if (*cp == 'u' || *cp == 'U') uns_flg++; else @@ -658,51 +666,83 @@ static void strint2tok(char intbuf[], struct token* ptok) } else { - if (lng_flg > 1) + if (lng_flg + lnglng_flg > 1) lexerror("only one long suffix allowed"); if (uns_flg > 1) lexerror("only one unsigned suffix allowed"); } + + /* Get masks like 0XFFFF, 0XFFFFFFFF as unsigned values. */ + uint_mask = (unsigned writh)full_mask[(int)int_size]; + ulng_mask = (unsigned writh)full_mask[(int)long_size]; + if (lnglng_size < 0) + ulnglng_mask = 0; + else + ulnglng_mask = (unsigned writh)full_mask[(int)lnglng_size]; + + /* If a decimal literal with no suffix is too big for int + and long, then C89 tries unsigned long, but C99 tries + long long (WG14, Rationale for C99, C99RationaleV5.10.pdf, + 6.4.4.1 Integer constants). + This compiler follows C89 when the literal has no + long long suffix. + */ + cut = 0; if (ovfl) { lexwarning("overflow in constant"); - fund = ULONG; + cut = 1; /* cut the size of the constant */ } - else if (!lng_flg && (val & full_mask[(int)int_size]) == val) + else if (!lng_flg && !lnglng_flg && (val & uint_mask) == val) { - if (val >= 0 && val <= max_int) - { + if ((val & (uint_mask >> 1)) == val) fund = INT; - } - else if (int_size == long_size) - { - fund = UNSIGNED; - } else if (base == 10 && !uns_flg) - fund = LONG; + { + if ((val & (ulng_mask >> 1)) == val) + fund = LONG; + else + fund = ULONG; + } else fund = UNSIGNED; } - else if ((val & full_mask[(int)long_size]) == val) + else if (!lnglng_flg && (val & ulng_mask) == val) { - if (val >= 0) + if ((val & (ulng_mask >> 1)) == val) fund = LONG; else fund = ULONG; } - else - { /* sizeof(arith) is greater than long_size */ - assert(arith_size > long_size); - lexwarning("constant too large for target machine"); - /* cut the size to prevent further complaints */ - val &= full_mask[(int)long_size]; - fund = ULONG; - } - if (lng_flg) + else if (lnglng_flg && (val & ulnglng_mask) == val) { - /* fund can't be INT */ - if (fund == UNSIGNED) + if ((val & (ulnglng_mask >> 1)) == val) + fund = LNGLNG; + else + fund = ULNGLNG; + } + else if (lnglng_flg && no_long_long()) + fund = ERRONEOUS; + else + { + assert(sizeof(val) > long_size || + (lnglng_size >= 0 && sizeof(val) > lnglng_size)); + lexwarning("constant too large for target machine"); + cut = 1; + } + if (cut) + { + /* cut the size to prevent further complaints */ + if (lnglng_flg) + { + fund = ULNGLNG; + val &= ulnglng_mask; + } + else + { fund = ULONG; + val &= ulng_mask; + } } if (uns_flg) { @@ -710,7 +750,9 @@ static void strint2tok(char intbuf[], struct token* ptok) fund = UNSIGNED; else if (fund == LONG) fund = ULONG; + else if (fund == LNGLNG) + fund = ULNGLNG; } ptok->tk_fund = fund; - ptok->tk_ival = val; + ptok->tk_ival = (writh)val; } diff --git a/lang/cem/cemcom.ansi/LLlex.h b/lang/cem/cemcom.ansi/LLlex.h index a52f5ed78..921c255dd 100644 --- a/lang/cem/cemcom.ansi/LLlex.h +++ b/lang/cem/cemcom.ansi/LLlex.h @@ -26,7 +26,7 @@ struct token { char *tok_bts; /* row of bytes */ int tok_len; /* length of row of bytes */ } tok_string; - arith tok_ival; /* for INTEGER */ + writh tok_ival; /* for INTEGER */ char *tok_fval; /* for FLOATING */ } tok_data; }; diff --git a/lang/cem/cemcom.ansi/SmallPars b/lang/cem/cemcom.ansi/SmallPars index 01f7073b1..fa3147ea9 100644 --- a/lang/cem/cemcom.ansi/SmallPars +++ b/lang/cem/cemcom.ansi/SmallPars @@ -117,11 +117,6 @@ /*#define NOBITFIELD 1 /* if NOT defined, implement bitfields */ -!File: spec_arith.h -/* describes internal compiler arithmetics */ -#undef SPECIAL_ARITHMETICS /* something different from native long */ - - !File: static.h #define GSTATIC /* for large global "static" arrays */ diff --git a/lang/cem/cemcom.ansi/arith.c b/lang/cem/cemcom.ansi/arith.c index e1c3311c3..21a86faf3 100644 --- a/lang/cem/cemcom.ansi/arith.c +++ b/lang/cem/cemcom.ansi/arith.c @@ -371,8 +371,7 @@ int int2int(struct expr **expp, register struct type *tp) unsigned int x = ~0; unsigned int y = -1; */ - extern long full_mask[]; - long remainder = exp->VL_VALUE & + writh remainder = exp->VL_VALUE & ~full_mask[(int)(tp->tp_size)]; if (remainder == 0 || @@ -389,6 +388,16 @@ int int2int(struct expr **expp, register struct type *tp) return exp->ex_type->tp_fund; } +static int fit4(writh val, int uns) +{ + /* Does this value fit in 4 bytes? */ + unsigned writh u = (unsigned writh)val; + + if (!uns) + u += 0x80000000UL; + return (u & full_mask[4]) == u; +} + /* With compile-time constants, we don't set fp_used, since this is done * only when necessary in eval.c. */ @@ -400,10 +409,10 @@ void int2float(register struct expr **expp, struct type *tp) register struct expr *exp = *expp; int uns = exp->ex_type->tp_unsigned; - if (is_cp_cst(exp)) { + if (is_cp_cst(exp) && fit4(exp->VL_VALUE, uns)) { exp->ex_type = tp; exp->ex_class = Float; - flt_arith2flt(exp->VL_VALUE, &(exp->FL_ARITH), uns); + flt_arith2flt((arith)exp->VL_VALUE, &(exp->FL_ARITH), uns); } else { fp_used = 1; @@ -417,24 +426,35 @@ void float2int(struct expr **expp, struct type *tp) converted to the integral type tp. */ register struct expr *ex = *expp; - + if (is_fp_cst(ex)) { arith ar = flt_flt2arith(&ex->FL_ARITH, tp->tp_unsigned); - +#ifdef NOTDEF + /* Historically, we always did the conversion at + compile time. This is now wrong if type arith is + too narrow for an 8-byte integer. + */ if (flt_status == FLT_OVFL) expr_warning(ex,"overflow in float to int conversion"); else if (flt_status == FLT_UNFL) expr_warning(ex,"underflow in float to unsigned conversion"); - ex->ex_type = tp; - /* The following lines are copied from fill_int_expr */ - ex->ex_class = Value; - ex->VL_CLASS = Const; - ex->VL_VALUE = ar; - cut_size(ex); - } else { - fp_used = 1; - *expp = arith2arith(tp, FLOAT2INT, ex); +#endif /* NOTDEF */ + /* Now, we defer the conversion until run time + unless it fits in 4 bytes. + */ + if (flt_status != FLT_OVFL && flt_status != FLT_UNFL && + fit4((writh)ar, tp->tp_unsigned)) { + ex->ex_type = tp; + /* The following lines are copied from fill_int_expr */ + ex->ex_class = Value; + ex->VL_CLASS = Const; + ex->VL_VALUE = (writh)ar; + cut_size(ex); + return; + } } + fp_used = 1; + *expp = arith2arith(tp, FLOAT2INT, ex); } void float2float(register struct expr **expp, struct type *tp) @@ -640,3 +660,25 @@ void switch_sign_fp(register struct expr *expr) { flt_umin(&(expr->FL_ARITH)); } + +char *writh2str(writh val, int uns) +{ + /* Converts val to a decimal string, like + long2str(val, 10), but allows wider values. + */ + static char buf[NUMSIZE + 1]; + char *cp = &buf[NUMSIZE + 1]; + int negative = (!uns && val < 0); + unsigned writh u = (unsigned writh)val; + + if (negative) + u = -u; + *--cp = '\0'; + do { + *--cp = '0' + (u % 10); + u /= 10; + } while (u != 0); + if (negative) + *--cp = '-'; + return cp; +} diff --git a/lang/cem/cemcom.ansi/arith.h b/lang/cem/cemcom.ansi/arith.h index 65b0003de..a0b7148a7 100644 --- a/lang/cem/cemcom.ansi/arith.h +++ b/lang/cem/cemcom.ansi/arith.h @@ -5,30 +5,25 @@ /* $Id$ */ /* COMPILER ARITHMETIC */ -/* Normally the compiler does its internal arithmetics in longs - native to the source machine, which is always good for local - compilations, and generally OK too for cross compilations - downwards and sidewards. For upwards cross compilation and - to save storage on small machines, SPECIAL_ARITHMETICS will - be handy. +/* The compiler uses 2 types, arith and writh, for its internal + arithmetic. Type arith is normally long, and may be too + narrow for long long values. We can't change arith to a wider + type, because both (pulled by ) and + define arith. + + Type writh (wide arithmetic) is for values that might not fit + in arith. Normally writh is the long long native to the + source machine, which is always good for local compilations, + and generally OK too for cross compilations downwards and + sidewards. */ #ifndef ARITH_H_ #define ARITH_H_ -#include "parameters.h" - -#ifndef SPECIAL_ARITHMETICS - #include /* obtain definition of "arith" */ -#include -#else /* SPECIAL_ARITHMETICS */ - -/* All preprocessor arithmetic should be done in longs. -*/ -#define arith long /* dummy */ - -#endif /* SPECIAL_ARITHMETICS */ +#define writh long long +/* The compiler also uses "unsigned writh". */ struct expr; struct type; @@ -37,6 +32,8 @@ struct type; #define arith_sign ((arith) 1 << (arith_size * 8 - 1)) #define max_arith (~arith_sign) +extern writh full_mask[]; /* cstoper.c */ + void arithbalance(register struct expr **e1p, int oper, register struct expr **e2p); void relbalance(register struct expr **e1p, int oper, register struct expr **e2p); void ch3pointer(struct expr **expp, int oper, register struct type *tp); @@ -57,5 +54,6 @@ void any2opnd(register struct expr **expp, int oper); void any2parameter(register struct expr **expp); void field2arith(register struct expr **expp); void switch_sign_fp(register struct expr *expr); +char *writh2str(writh val, int uns); #endif /* ARITH_H_ */ diff --git a/lang/cem/cemcom.ansi/ch3.c b/lang/cem/cemcom.ansi/ch3.c index 69c75fed6..2f70c0c38 100644 --- a/lang/cem/cemcom.ansi/ch3.c +++ b/lang/cem/cemcom.ansi/ch3.c @@ -320,7 +320,7 @@ void ch3cast(register struct expr **expp, int oper, register struct type *tp) } if (oldtp->tp_up->tp_fund == VOID && is_cp_cst(exp) - && exp->VL_VALUE == (arith)0) + && exp->VL_VALUE == 0) break; /* switch */ } /* falltrough */ @@ -366,7 +366,7 @@ void ch3cast(register struct expr **expp, int oper, register struct type *tp) case NOTEQUAL: case '=': case RETURN: - if (is_cp_cst(exp) && exp->VL_VALUE == (arith)0) + if (is_cp_cst(exp) && exp->VL_VALUE == 0) break; default: expr_strict(exp, diff --git a/lang/cem/cemcom.ansi/ch3bin.c b/lang/cem/cemcom.ansi/ch3bin.c index e692e98fa..d95f5b739 100644 --- a/lang/cem/cemcom.ansi/ch3bin.c +++ b/lang/cem/cemcom.ansi/ch3bin.c @@ -206,7 +206,7 @@ void ch3bin(register struct expr **expp, int oper, struct expr *expr) where o1 == (*expp)->VL_VALUE; and ((oper == AND) || (oper == OR)) */ - if ((oper == AND) == (ex->VL_VALUE != (arith)0)) { + if ((oper == AND) == (ex->VL_VALUE != 0)) { *expp = expr; } else { @@ -224,13 +224,13 @@ void ch3bin(register struct expr **expp, int oper, struct expr *expr) where o2 == expr->VL_VALUE and ((oper == AND) || (oper == OR)) */ - if ((oper == AND) == (expr->VL_VALUE != (arith)0)) { + if ((oper == AND) == (expr->VL_VALUE != 0)) { (*expp)->ex_flags |= expr->ex_flags | EX_ILVALUE; free_expression(expr); } else { if (oper == OR) - expr->VL_VALUE = (arith)1; + expr->VL_VALUE = 1; ch3bin(expp, ',', expr); } } diff --git a/lang/cem/cemcom.ansi/ch3mon.c b/lang/cem/cemcom.ansi/ch3mon.c index a84a141f2..456f25f8a 100644 --- a/lang/cem/cemcom.ansi/ch3mon.c +++ b/lang/cem/cemcom.ansi/ch3mon.c @@ -22,7 +22,6 @@ extern char options[]; -extern arith full_mask[/*MAXSIZE + 1*/]; /* cstoper.c */ char *symbol2str(); void ch3mon(int oper, register struct expr **expp) @@ -122,7 +121,7 @@ void ch3mon(int oper, register struct expr **expp) case '-': any2arith(expp, oper); if (is_cp_cst(*expp)) { - arith o1 = (*expp)->VL_VALUE; + writh o1 = (*expp)->VL_VALUE; (*expp)->VL_VALUE = (oper == '-') ? -o1 : ((*expp)->ex_type->tp_unsigned ? diff --git a/lang/cem/cemcom.ansi/code.c b/lang/cem/cemcom.ansi/code.c index cef708cbf..762124338 100644 --- a/lang/cem/cemcom.ansi/code.c +++ b/lang/cem/cemcom.ansi/code.c @@ -602,7 +602,7 @@ void loc_init(struct expr *expr, struct idf *id) EVAL(expr, RVAL, TRUE, NO_LABEL, NO_LABEL); vl.vl_class = Name; vl.vl_data.vl_idf = id; - vl.vl_value = (arith)0; + vl.vl_value = 0; store_val(&vl, tp); } #else /* LINT */ diff --git a/lang/cem/cemcom.ansi/conversion.c b/lang/cem/cemcom.ansi/conversion.c index 13af3cef8..c2a1071b7 100644 --- a/lang/cem/cemcom.ansi/conversion.c +++ b/lang/cem/cemcom.ansi/conversion.c @@ -112,8 +112,6 @@ void conversion(register struct type *from_type, register struct type *to_type) if ((int)(to_type->tp_size) < (int)word_size && to_cnvtype != T_FLOATING ) { - extern arith full_mask[]; - if (to_cnvtype == T_SIGNED) { C_loc(to_type->tp_size); C_loc(word_size); diff --git a/lang/cem/cemcom.ansi/cstoper.c b/lang/cem/cemcom.ansi/cstoper.c index 61c3fd6e3..769c6940b 100644 --- a/lang/cem/cemcom.ansi/cstoper.c +++ b/lang/cem/cemcom.ansi/cstoper.c @@ -18,7 +18,7 @@ #include "error.h" /* full_mask[1] == 0XFF, full_mask[2] == 0XFFFF, .. */ -arith full_mask[MAXSIZE + 1]; +writh full_mask[MAXSIZE + 1]; #ifndef NOCROSS arith max_int; /* maximum integer on target machine */ arith max_unsigned; /* maximum unsigned on target machine */ @@ -31,8 +31,8 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr) expressions *expp(ld) and expr(ct), and the result restored in *expp. */ - register arith o1 = (*expp)->VL_VALUE; - register arith o2 = expr->VL_VALUE; + unsigned writh o1 = (unsigned writh)(*expp)->VL_VALUE; + unsigned writh o2 = (unsigned writh)expr->VL_VALUE; int uns = (*expp)->ex_type->tp_unsigned; assert(is_ld_cst(*expp) && is_cp_cst(expr)); @@ -49,9 +49,9 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr) break; } if (uns) - o1 /= (unsigned arith) o2; - else o1 /= o2; + else + o1 = (unsigned writh)((writh)o1 / (writh)o2); break; case '%': if (o2 == 0) { @@ -62,9 +62,9 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr) break; } if (uns) - o1 %= (unsigned arith) o2; - else o1 %= o2; + else + o1 = (unsigned writh)((writh)o1 % (writh)o2); break; case '+': o1 += o2; @@ -78,15 +78,14 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr) case RIGHT: if (o2 == 0) break; - if (uns) { - o1 = (o1 >> 1) & ~arith_sign; - o1 >>= (o2 - 1); - } - else o1 >>= o2; + if (uns) + o1 >>= o2; + else + o1 = (unsigned writh)((writh)o1 >> (writh)o2); break; case '<': { - arith tmp = o1; + writh tmp = o1; o1 = o2; o2 = tmp; @@ -94,13 +93,13 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr) /* Fall through */ case '>': if (uns) - o1 = (unsigned arith) o1 > (unsigned arith) o2; - else o1 = o1 > o2; + else + o1 = (writh)o1 > (writh)o2; break; case LESSEQ: { - arith tmp = o1; + writh tmp = o1; o1 = o2; o2 = tmp; @@ -108,9 +107,9 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr) /* Fall through */ case GREATEREQ: if (uns) - o1 = (unsigned arith) o1 >= (unsigned arith) o2; - else o1 = o1 >= o2; + else + o1 = (writh)o1 >= (writh)o2; break; case EQUAL: o1 = o1 == o2; @@ -128,7 +127,7 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr) o1 ^= o2; break; } - (*expp)->VL_VALUE = o1; + (*expp)->VL_VALUE = (writh)o1; cut_size(*expp); (*expp)->ex_flags |= expr->ex_flags; (*expp)->ex_flags &= ~EX_PARENS; @@ -140,7 +139,7 @@ void cut_size(register struct expr *expr) /* The constant value of the expression expr is made to conform to the size of the type of the expression. */ - register arith o1 = expr->VL_VALUE; + writh o1 = expr->VL_VALUE; int uns = expr->ex_type->tp_unsigned; int size = (int) expr->ex_type->tp_size; @@ -159,8 +158,8 @@ void cut_size(register struct expr *expr) o1 &= full_mask[size]; } else { - int nbits = (int) (arith_size - size) * 8; - arith remainder = o1 & ~full_mask[size]; + int nbits = (int) (sizeof(o1) - size) * 8; + writh remainder = o1 & ~full_mask[size]; if (remainder != 0 && remainder != ~full_mask[size]) if (!ResultKnown) @@ -173,22 +172,20 @@ void cut_size(register struct expr *expr) void init_cst(void) { register int i = 0; - register arith bt = (arith)0; + unsigned writh 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) { + while (!((writh)bt < 0)) { bt = (bt << 8) + 0377, i++; if (i > MAXSIZE) fatal("array full_mask too small for this machine"); full_mask[i] = bt; } - if ((int)long_size > arith_size) - fatal("sizeof (arith) insufficient on this machine"); + /* signed comparison; lnglng_size might be -1 */ + if (long_size > (arith)sizeof(writh) || + lnglng_size > (arith)sizeof(writh)) + fatal("sizeof(writh) insufficient on this machine"); #ifndef NOCROSS - max_int = full_mask[(int)int_size] & ~(1L << ((int)int_size * 8 - 1)); - max_unsigned = full_mask[(int)int_size]; + max_int = (arith)((unsigned writh)full_mask[(int)int_size] >> 1); + max_unsigned = (arith)full_mask[(int)int_size]; #endif /* NOCROSS */ } diff --git a/lang/cem/cemcom.ansi/declar.g b/lang/cem/cemcom.ansi/declar.g index 8bec8e72d..abd7263d4 100644 --- a/lang/cem/cemcom.ansi/declar.g +++ b/lang/cem/cemcom.ansi/declar.g @@ -343,7 +343,7 @@ arrayer(arith *sizep;) constant_expression(&expr) { check_array_subscript(expr); - *sizep = expr->VL_VALUE; + *sizep = (arith)expr->VL_VALUE; free_expression(expr); } ]? @@ -430,7 +430,7 @@ enumerator(struct type *tp; arith *lp;) '=' constant_expression(&expr) { - *lp = expr->VL_VALUE; + *lp = (arith)expr->VL_VALUE; free_expression(expr); } ]? @@ -548,7 +548,7 @@ bit_expression(struct field **fd;) ':' constant_expression(&expr) { - (*fd)->fd_width = expr->VL_VALUE; + (*fd)->fd_width = (arith)expr->VL_VALUE; free_expression(expr); #ifdef NOBITFIELD error("bitfields are not implemented"); diff --git a/lang/cem/cemcom.ansi/declarator.c b/lang/cem/cemcom.ansi/declarator.c index 2795bda86..c1ce2d88f 100644 --- a/lang/cem/cemcom.ansi/declarator.c +++ b/lang/cem/cemcom.ansi/declarator.c @@ -118,11 +118,11 @@ void reject_params(register struct declarator *dc) void check_array_subscript(register struct expr *expr) { - arith size = expr->VL_VALUE; + writh size = expr->VL_VALUE; if (size < 0) { error("array size is negative"); - expr->VL_VALUE = (arith)1; + expr->VL_VALUE = 1; } else if (size == 0) { @@ -131,6 +131,6 @@ void check_array_subscript(register struct expr *expr) else if (size & ~max_unsigned) { /* absolutely ridiculous */ expr_error(expr, "overflow in array size"); - expr->VL_VALUE = (arith)1; + expr->VL_VALUE = 1; } } diff --git a/lang/cem/cemcom.ansi/dumpidf.c b/lang/cem/cemcom.ansi/dumpidf.c index 3c866b36b..c8f4e1a60 100644 --- a/lang/cem/cemcom.ansi/dumpidf.c +++ b/lang/cem/cemcom.ansi/dumpidf.c @@ -6,8 +6,8 @@ /* DUMP ROUTINES */ -#ifdef DEBUG #include "parameters.h" +#ifdef DEBUG #include #include #include @@ -442,8 +442,8 @@ static void p1_expr(int lvl, register struct expr *expr) print("(Unknown) "); break; } - print(expr->ex_type->tp_unsigned ? "%lu\n" : "%ld\n", - expr->VL_VALUE); + print("%s\n", writh2str(expr->VL_VALUE, + expr->ex_type->tp_unsigned)); break; case String: { diff --git a/lang/cem/cemcom.ansi/eval.c b/lang/cem/cemcom.ansi/eval.c index 338ca51cb..efe40bad6 100644 --- a/lang/cem/cemcom.ansi/eval.c +++ b/lang/cem/cemcom.ansi/eval.c @@ -106,7 +106,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label case String: /* a string constant */ if (gencode) { string2pointer(expr); - C_lae_dlb(expr->VL_LBL, expr->VL_VALUE); + C_lae_dlb(expr->VL_LBL, (arith)expr->VL_VALUE); } break; case Float: /* a floating constant */ @@ -575,7 +575,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label NO_LABEL, NO_LABEL); assert(is_cp_cst(right)); if (gencode) { - C_adp(right->VL_VALUE); + C_adp((arith)right->VL_VALUE); } break; case ',': @@ -858,10 +858,11 @@ void store_val(register struct value *vl, register struct type *tp) { register int inword = 0; register int indword = 0; - arith val = vl->vl_value; + writh wval = vl->vl_value; + arith val = (arith)wval; if (vl->vl_class == Const) { /* absolute addressing */ - load_cst(val, pointer_size); + load_cst(wval, pointer_size); store_block(tp->tp_size, tp->tp_align); return; } @@ -930,7 +931,8 @@ void load_val(register struct expr *expr, int rlval) register struct type *tp = expr->ex_type; int rvalue = (rlval == RVAL && expr->ex_lvalue != 0); register int inword = 0, indword = 0; - register arith val = expr->VL_VALUE; + writh wval = expr->VL_VALUE; + arith val = (arith)wval; if (expr->ex_type->tp_fund == FLOAT || expr->ex_type->tp_fund == DOUBLE @@ -938,11 +940,11 @@ void load_val(register struct expr *expr, int rlval) fp_used = 1; if (expr->VL_CLASS == Const) { if (rvalue) { /* absolute addressing */ - load_cst(val, pointer_size); + load_cst(wval, pointer_size); load_block(tp->tp_size, tp->tp_align); } else /* integer, unsigned, long, enum etc */ - load_cst(val, tp->tp_size); + load_cst(wval, tp->tp_size); return; } if (rvalue) { @@ -1022,7 +1024,7 @@ void load_val(register struct expr *expr, int rlval) } } -void load_cst(arith val, arith siz) +void load_cst(writh val, arith siz) { /* EM can't encode ldc with constant over 4 bytes. Such a constant must go into rom. @@ -1036,7 +1038,7 @@ void load_cst(arith val, arith siz) label datlab; C_df_dlb(datlab = data_label()); - C_rom_icon(long2str((long)val, 10), siz); + C_rom_icon(writh2str(val, 0), siz); C_lae_dlb(datlab, (arith)0); C_loi(siz); } diff --git a/lang/cem/cemcom.ansi/eval.h b/lang/cem/cemcom.ansi/eval.h index 337b5ac57..53a7f8d12 100644 --- a/lang/cem/cemcom.ansi/eval.h +++ b/lang/cem/cemcom.ansi/eval.h @@ -12,6 +12,7 @@ #include +#include "arith.h" /* writh */ struct expr; struct value; @@ -30,7 +31,7 @@ void assop(register struct type *type, int oper); */ void store_val(register struct value *vl, register struct type *tp); void load_val(register struct expr *expr, int rlval); -void load_cst(arith val, arith siz); +void load_cst(writh val, arith siz); #endif /* LINT */ diff --git a/lang/cem/cemcom.ansi/expr.c b/lang/cem/cemcom.ansi/expr.c index b24c408d0..3dfbc5da5 100644 --- a/lang/cem/cemcom.ansi/expr.c +++ b/lang/cem/cemcom.ansi/expr.c @@ -184,21 +184,21 @@ void idf2expr(register struct expr *expr) if (def->df_sc == ENUM) { expr->VL_CLASS = Const; - expr->VL_VALUE = def->df_address; + expr->VL_VALUE = (writh)def->df_address; } #ifndef LINT else if (def->df_sc == STATIC && def->df_level >= L_LOCAL) { expr->VL_CLASS = Label; expr->VL_LBL = def->df_address; - expr->VL_VALUE = (arith) 0; + expr->VL_VALUE = 0; } #endif /* LINT */ else { expr->VL_CLASS = Name; expr->VL_IDF = idf; - expr->VL_VALUE = (arith) 0; + expr->VL_VALUE = 0; } } @@ -270,12 +270,12 @@ arith ivalue, int fund) expr->ex_file = dot.tk_file; expr->ex_line = dot.tk_line; - fill_int_expr(expr, ivalue, fund); + fill_int_expr(expr, (writh)ivalue, fund); return expr; } void fill_int_expr(register struct expr *ex, -arith ivalue, int fund) +writh ivalue, int fund) { /* Details derived from ivalue and fund are put into the constant integer expression ex. @@ -294,6 +294,16 @@ arith ivalue, int fund) case ULONG: ex->ex_type = ulong_type; break; + case LNGLNG: + ex->ex_type = lnglng_type; + break; + case ULNGLNG: + ex->ex_type = ulnglng_type; + break; + case ERRONEOUS: /* 123LL when no_long_long() */ + ex->ex_type = error_type; + ex->ex_flags |= EX_ERROR; + break; default: crash("(fill_int_expr) bad fund %s\n", symbol2str(fund)); /*NOTREACHED*/ @@ -406,6 +416,7 @@ void chk_cst_expr(struct expr **expp) case INT: case ENUM: case LONG: + case LNGLNG: if (is_ld_cst(expr)) { return; diff --git a/lang/cem/cemcom.ansi/expr.str b/lang/cem/cemcom.ansi/expr.str index 97ac5b1f9..51718ace6 100644 --- a/lang/cem/cemcom.ansi/expr.str +++ b/lang/cem/cemcom.ansi/expr.str @@ -23,7 +23,7 @@ struct value { int vl_class; /* Const, Name or Label */ - arith vl_value; /* constant value or offset */ + writh vl_value; /* constant value or offset */ union { struct idf *vl_idf; /* external name */ label vl_lbl; /* compiler-generated label */ @@ -100,8 +100,6 @@ struct expr { #define ISNAME(e) ((e)->ex_class == Value && (e)->VL_CLASS == Name) #define ISCOMMA(e) ((e)->ex_class == Oper && (e)->OP_OPER == INITCOMMA) -extern struct expr *intexpr(), *new_oper(); - /* ALLOCDEF "expr" 20 */ @@ -113,7 +111,7 @@ void string2expr(register struct expr **expp, char *str, int len); void int2expr(struct expr *expr); void float2expr(register struct expr *expr); struct expr* intexpr(arith ivalue, int fund); -void fill_int_expr(register struct expr *ex,arith ivalue, int fund); +void fill_int_expr(register struct expr *ex, writh ivalue, int fund); struct expr *new_oper(struct type *tp, register struct expr *e1, int oper, register struct expr *e2); void chk_cst_expr(struct expr **expp); diff --git a/lang/cem/cemcom.ansi/field.c b/lang/cem/cemcom.ansi/field.c index d1b014c01..7d7f27726 100644 --- a/lang/cem/cemcom.ansi/field.c +++ b/lang/cem/cemcom.ansi/field.c @@ -28,8 +28,6 @@ #include "eval.h" -extern arith full_mask[]; /* cstoper.c */ - /* Eval_field() evaluates expressions involving bit fields. The various instructions are not yet optimised in the expression tree and are therefore dealt with in this function. @@ -136,6 +134,8 @@ void store_field( register struct expr *leftop, arith tmpvar) { + arith high_mask; + C_loc(fd->fd_mask); C_and(word_size); if (code == TRUE) @@ -145,7 +145,8 @@ void store_field( C_slu(word_size); else C_sli(word_size); - C_loc(~((fd->fd_mask << fd->fd_shift) | ~full_mask[(int)word_size])); + high_mask = (arith)~full_mask[(int)word_size]; + C_loc(~((fd->fd_mask << fd->fd_shift) | high_mask)); if (leftop->ex_depth == 0) { /* simple case */ load_val(leftop, RVAL); C_and(word_size); diff --git a/lang/cem/cemcom.ansi/ival.g b/lang/cem/cemcom.ansi/ival.g index 995d46248..05fcc4881 100644 --- a/lang/cem/cemcom.ansi/ival.g +++ b/lang/cem/cemcom.ansi/ival.g @@ -544,11 +544,11 @@ void check_ival(struct expr **expp, register struct type *tp) if (idf->id_def->df_type->tp_fund == FUNCTION) C_con_pnam(idf->id_text); else /* e.g., int a; int *p = &a; */ - C_con_dnam(idf->id_text, expr->VL_VALUE); + C_con_dnam(idf->id_text, (arith)expr->VL_VALUE); } else { assert(expr->VL_CLASS == Label); - C_con_dlb(expr->VL_LBL, expr->VL_VALUE); + C_con_dlb(expr->VL_LBL, (arith)expr->VL_VALUE); } break; case FLOAT: @@ -595,7 +595,7 @@ and also to prevent runtime coercions for compile-time constants. print_expr("init-expr after cast", expr); #endif /* DEBUG */ if (is_cp_cst(expr)) - put_bf(tp, expr->VL_VALUE); + put_bf(tp, (arith)expr->VL_VALUE); else illegal_init_cst(expr); break; @@ -701,7 +701,7 @@ void put_bf(struct type *tp, arith val) field |= (val & fd->fd_mask) << fd->fd_shift; if (sd->sd_sdef == 0 || sd->sd_sdef->sd_offset != offset) { /* the selector was the last stored at this address */ - exp.VL_VALUE = field; + exp.VL_VALUE = (writh)field; con_int(&exp); field = (arith)0; offset = (arith)-1; @@ -739,11 +739,11 @@ void con_int(register struct expr *ex) assert(is_cp_cst(ex)); if (tp->tp_unsigned) - C_con_ucon(long2str((long)ex->VL_VALUE, -10), tp->tp_size); + C_con_ucon(writh2str(ex->VL_VALUE, 1), tp->tp_size); else if (tp->tp_size == word_size) - C_con_cst(ex->VL_VALUE); + C_con_cst((arith)ex->VL_VALUE); else - C_con_icon(long2str((long)ex->VL_VALUE, 10), tp->tp_size); + C_con_icon(writh2str(ex->VL_VALUE, 0), tp->tp_size); } void illegal_init_cst(struct expr *ex) diff --git a/lang/cem/cemcom.ansi/stab.c b/lang/cem/cemcom.ansi/stab.c index 5a002301f..864201aa1 100644 --- a/lang/cem/cemcom.ansi/stab.c +++ b/lang/cem/cemcom.ansi/stab.c @@ -32,8 +32,6 @@ #include "level.h" #include "print.h" -extern long full_mask[]; - #define INCR_SIZE 64 static struct db_str diff --git a/lang/cem/cemcom.ansi/statement.g b/lang/cem/cemcom.ansi/statement.g index 3d1dcd4f2..d58ec4b6a 100644 --- a/lang/cem/cemcom.ansi/statement.g +++ b/lang/cem/cemcom.ansi/statement.g @@ -147,7 +147,7 @@ if_statement /* The comparison has been optimized to a 0 or 1. */ - if (expr->VL_VALUE == (arith)0) { + if (expr->VL_VALUE == 0) { C_bra(l_false); } /* else fall through */ @@ -210,7 +210,7 @@ while_statement { opnd2test(&expr, WHILE); if (is_cp_cst(expr)) { - if (expr->VL_VALUE == (arith)0) { + if (expr->VL_VALUE == 0) { C_bra(l_break); } } @@ -264,11 +264,11 @@ do_statement { opnd2test(&expr, WHILE); if (is_cp_cst(expr)) { - if (expr->VL_VALUE == (arith)1) { + if (expr->VL_VALUE == 1) { C_bra(l_body); } #ifdef LINT - end_do_stmt(1, expr->VL_VALUE != (arith)0); + end_do_stmt(1, expr->VL_VALUE != 0); #endif /* LINT */ } else { @@ -313,7 +313,7 @@ for_statement { opnd2test(&e_test, FOR); if (is_cp_cst(e_test)) { - if (e_test->VL_VALUE == (arith)0) { + if (e_test->VL_VALUE == 0) { C_bra(l_break); } } diff --git a/lang/cem/cemcom.ansi/switch.c b/lang/cem/cemcom.ansi/switch.c index 7db1f28bd..95da9aabf 100644 --- a/lang/cem/cemcom.ansi/switch.c +++ b/lang/cem/cemcom.ansi/switch.c @@ -32,13 +32,13 @@ extern char options[]; int density = DENSITY; -static int compact(int nr, arith low, arith up) +static int compact(int nr, writh low, writh up) { /* Careful! up - low might not fit in an arith. And then, the test "up-low < 0" might also not work to detect this situation! Or is this just a bug in the M68020/M68000? */ - arith diff = up - low; + writh diff = up - low; return (nr == 0 || (diff >= 0 && diff / nr <= (density - 1))); } @@ -117,10 +117,10 @@ void code_endswitch(void) C_rom_ilb(sh->sh_default); if (compact(sh->sh_nrofentries, sh->sh_lowerbd, sh->sh_upperbd)) { /* CSA */ - register arith val; + writh val; - C_rom_icon(long2str((long)sh->sh_lowerbd,10), size); - C_rom_icon(long2str((long)(sh->sh_upperbd - sh->sh_lowerbd),10), + C_rom_icon(writh2str(sh->sh_lowerbd, 0), size); + C_rom_icon(writh2str(sh->sh_upperbd - sh->sh_lowerbd, 0), size); ce = sh->sh_entries; for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) { @@ -136,10 +136,10 @@ void code_endswitch(void) C_csa(size); } else { /* CSB */ - C_rom_icon(long2str((long)sh->sh_nrofentries,10),size); + C_rom_icon(writh2str(sh->sh_nrofentries, 0), size); for (ce = sh->sh_entries; ce; ce = ce->next) { /* generate the entries: value + prog.label */ - C_rom_icon(long2str((long)ce->ce_value,10),size); + C_rom_icon(writh2str(ce->ce_value, 0), size); C_rom_ilb(ce->ce_label); } C_lae_dlb(tablabel, (arith)0); /* perform the switch */ @@ -162,7 +162,7 @@ void code_endswitch(void) void code_case(struct expr *expr) { - register arith val; + writh val; register struct case_entry *ce; register struct switch_hdr *sh = switch_stack; diff --git a/lang/cem/cemcom.ansi/switch.str b/lang/cem/cemcom.ansi/switch.str index 94a45ca42..3ba693498 100644 --- a/lang/cem/cemcom.ansi/switch.str +++ b/lang/cem/cemcom.ansi/switch.str @@ -22,8 +22,8 @@ struct switch_hdr { int sh_nrofentries; struct type *sh_type; struct expr *sh_expr; - arith sh_lowerbd; - arith sh_upperbd; + writh sh_lowerbd; + writh sh_upperbd; struct case_entry *sh_entries; }; @@ -32,7 +32,7 @@ struct switch_hdr { struct case_entry { struct case_entry *next; label ce_label; - arith ce_value; + writh ce_value; }; /* ALLOCDEF "case_entry" 20 */ diff --git a/lang/cem/cemcom.ansi/tokenname.c b/lang/cem/cemcom.ansi/tokenname.c index fb3bae349..0a86f480e 100644 --- a/lang/cem/cemcom.ansi/tokenname.c +++ b/lang/cem/cemcom.ansi/tokenname.c @@ -107,6 +107,7 @@ struct tokenname tkfunny[] = { /* internal keywords */ {LNGLNG, "long long"}, {LNGDBL, "long double"}, {ULONG, "unsigned long"}, + {ULNGLNG, "unsigned long long"}, {ARRAY, "array"}, {FUNCTION, "function"},