Add long long literals like 123LL to ACK C.

For now, a long long literal must have the 'LL' or 'll' suffix.  A
literal without 'LL' or 'll' acts as before: it may become unsigned
long but not long long.  (For targets where int and long have the same
size, some literals change from unsigned int to unsigned long.)

Type `arith` may be too narrow for long long values.  Add a second
type `writh` for wide arithmetic, and change some variables from arith
to writh.  This may cause bugs if I forget to use writh, or if a
conversion from writh to arith overflows.  I mark some conversions
with (arith) or (writh) casts.

 - BigPars, SmallPars: Remove SPECIAL_ARITHMETICS.  This feature
   would change arith to a different type, but can't work, because it
   would conflict with definitions of arith in both <em_arith.h> and
   <flt_arith.h>.
 - LLlex.c: Understand 'LL' or 'll' suffix.  Cut size of constant when
   it overflows writh, not only when it overflows the target machine's
   types.  (This cut might not be necessary, because we might cut it
   again later.)  When picking signed long or unsigned long, check the
   target's long type, not the compiler's arith type; the old check
   for `val >= 0` was broken where sizeof(arith) > 4.
 - LLlex.h: Change struct token's tok_ival to writh, so it can hold a
   long long literal.
 - arith.c: Adjust to VL_VALUE being writh.  Don't convert between
   float and integer at compile-time if the integer might be too wide
   for <flt_arith.h>.  Add writh2str(), because writh might be too
   wide for long2str().
 - arith.h: Remove SPECIAL_ARITHMETICS.  Declare full_mask[] here,
   not in several *.c files.  Declare writh2str().
 - ch3.c, ch3bin.c, ch3mon.c, declarator.c, statement.g: Remove
   obsolete casts.  Adjust to VL_VALUE being writh.
 - conversion.c, stab.c: Don't declare full_mask[].
 - cstoper.c: Use writh for constant operations on VL_VALUE, and for
   full_mask[].
 - declar., field.c, ival.g: Add casts.
 - dumpidf.c: Need to #include "parameters.h" before checking DEBUG.
   Use writh2str, because "%ld" might not work.
 - eval.c, eval.h: Add casts.  Use writh when writing a wide constant
   in EM.
 - expr.c: Add and remove casts.  In fill_int_expr(), make expression
   from long long literal.  In chk_cst_expr(), allow long long as
   constant expression, so the compiler may accept `case 123LL:` in a
   switch statement.
 - expr.str: Change struct value's vl_value and struct expr's VL_VALUE
   to writh, so an expression may have a long long value at compile
   time.
 - statement.g: Remove obsolete casts.
 - switch.c, switch.str: Use writh in case entries for switch
   statements, so `switch (ll) {...}` with long long ll works.
 - tokenname.c: Add ULNGLNG so LLlex.c can use it for literals.
This commit is contained in:
George Koehler 2019-09-04 22:14:38 -04:00
parent 007a63d529
commit 15950f9c95
26 changed files with 258 additions and 180 deletions

View file

@ -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 */

View file

@ -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')
{
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)
{
if (val >= 0 && val <= max_int)
else if (!lng_flg && !lnglng_flg && (val & uint_mask) == val)
{
if ((val & (uint_mask >> 1)) == val)
fund = INT;
}
else if (int_size == long_size)
{
fund = UNSIGNED;
}
else if (base == 10 && !uns_flg)
{
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)
{
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 can't be INT */
if (fund == UNSIGNED)
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;
}

View file

@ -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;
};

View file

@ -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 */

View file

@ -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;
@ -420,21 +429,32 @@ void float2int(struct expr **expp, struct type *tp)
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");
#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 = ar;
ex->VL_VALUE = (writh)ar;
cut_size(ex);
} else {
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;
}

View file

@ -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 <em_arith.h> (pulled by <em.h>) and
<flt_arith.h> 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 <em_arith.h> /* obtain definition of "arith" */
#include <flt_arith.h>
#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_ */

View file

@ -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,

View file

@ -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);
}
}

View file

@ -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 ?

View file

@ -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 */

View file

@ -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);

View file

@ -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 */
}

View file

@ -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");

View file

@ -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;
}
}

View file

@ -6,8 +6,8 @@
/* DUMP ROUTINES */
#ifdef DEBUG
#include "parameters.h"
#ifdef DEBUG
#include <ack_string.h>
#include <alloc.h>
#include <flt_arith.h>
@ -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:
{

View file

@ -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);
}

View file

@ -12,6 +12,7 @@
#include <em.h>
#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 */

View file

@ -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;

View file

@ -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);

View file

@ -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);

View file

@ -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)

View file

@ -32,8 +32,6 @@
#include "level.h"
#include "print.h"
extern long full_mask[];
#define INCR_SIZE 64
static struct db_str

View file

@ -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);
}
}

View file

@ -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;

View file

@ -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 */

View file

@ -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"},