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:
parent
007a63d529
commit
15950f9c95
|
@ -117,11 +117,6 @@
|
||||||
/*#define NOBITFIELD 1 *//* if NOT defined, implement bitfields */
|
/*#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
|
!File: static.h
|
||||||
#define GSTATIC /* for large global "static" arrays */
|
#define GSTATIC /* for large global "static" arrays */
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include "Lpars.h"
|
#include "Lpars.h"
|
||||||
#include "class.h"
|
#include "class.h"
|
||||||
#include "sizes.h"
|
#include "sizes.h"
|
||||||
|
#include "type.h" /* no_long_long() */
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
#include "domacro.h"
|
#include "domacro.h"
|
||||||
#include "specials.h" /* registration of special identifiers */
|
#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_ESEEN 0x01 /* possibly a floating point number */
|
||||||
#define FLG_DOTSEEN 0x02 /* certainly a floating point number */
|
#define FLG_DOTSEEN 0x02 /* certainly a floating point number */
|
||||||
extern arith full_mask[];
|
|
||||||
|
|
||||||
#ifdef LINT
|
#ifdef LINT
|
||||||
extern int lint_skip_comment;
|
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)
|
static void strint2tok(char intbuf[], struct token* ptok)
|
||||||
{
|
{
|
||||||
register char* cp = intbuf;
|
register char* cp = intbuf;
|
||||||
int base = 10;
|
int base = 10, dig;
|
||||||
arith val = 0, dig, ubound;
|
unsigned writh val = 0, ubound;
|
||||||
int uns_flg = 0, lng_flg = 0, malformed = 0, ovfl = 0;
|
int uns_flg = 0, lng_flg = 0, lnglng_flg = 0;
|
||||||
int fund;
|
int malformed = 0, ovfl = 0;
|
||||||
|
unsigned writh uint_mask, ulng_mask, ulnglng_mask;
|
||||||
|
int cut, fund;
|
||||||
|
|
||||||
assert(*cp != '-');
|
assert(*cp != '-');
|
||||||
if (*cp == '0')
|
if (*cp == '0')
|
||||||
|
@ -611,11 +613,8 @@ static void strint2tok(char intbuf[], struct token* ptok)
|
||||||
else
|
else
|
||||||
base = 8;
|
base = 8;
|
||||||
}
|
}
|
||||||
/* The upperbound will be the same as when computed with
|
/* The upperbound checks if val * base would overflow. */
|
||||||
* max_unsigned_arith / base (since base is even). The problem here
|
ubound = ~(unsigned writh)0 / base;
|
||||||
* is that unsigned arith is not accepted by all compilers.
|
|
||||||
*/
|
|
||||||
ubound = max_arith / (base / 2);
|
|
||||||
|
|
||||||
while (is_hex(*cp))
|
while (is_hex(*cp))
|
||||||
{
|
{
|
||||||
|
@ -626,10 +625,10 @@ static void strint2tok(char intbuf[], struct token* ptok)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (val < 0 || val > ubound)
|
if (val > ubound)
|
||||||
ovfl++;
|
ovfl++;
|
||||||
val *= base;
|
val *= base;
|
||||||
if (val < 0 && val + dig >= 0)
|
if (val > val + dig)
|
||||||
ovfl++;
|
ovfl++;
|
||||||
val += dig;
|
val += dig;
|
||||||
}
|
}
|
||||||
|
@ -639,7 +638,16 @@ static void strint2tok(char intbuf[], struct token* ptok)
|
||||||
while (*cp)
|
while (*cp)
|
||||||
{
|
{
|
||||||
if (*cp == 'l' || *cp == 'L')
|
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')
|
else if (*cp == 'u' || *cp == 'U')
|
||||||
uns_flg++;
|
uns_flg++;
|
||||||
else
|
else
|
||||||
|
@ -658,51 +666,83 @@ static void strint2tok(char intbuf[], struct token* ptok)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (lng_flg > 1)
|
if (lng_flg + lnglng_flg > 1)
|
||||||
lexerror("only one long suffix allowed");
|
lexerror("only one long suffix allowed");
|
||||||
if (uns_flg > 1)
|
if (uns_flg > 1)
|
||||||
lexerror("only one unsigned suffix allowed");
|
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)
|
if (ovfl)
|
||||||
{
|
{
|
||||||
lexwarning("overflow in constant");
|
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;
|
fund = INT;
|
||||||
}
|
|
||||||
else if (int_size == long_size)
|
|
||||||
{
|
|
||||||
fund = UNSIGNED;
|
|
||||||
}
|
|
||||||
else if (base == 10 && !uns_flg)
|
else if (base == 10 && !uns_flg)
|
||||||
fund = LONG;
|
{
|
||||||
|
if ((val & (ulng_mask >> 1)) == val)
|
||||||
|
fund = LONG;
|
||||||
|
else
|
||||||
|
fund = ULONG;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
fund = UNSIGNED;
|
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;
|
fund = LONG;
|
||||||
else
|
else
|
||||||
fund = ULONG;
|
fund = ULONG;
|
||||||
}
|
}
|
||||||
else
|
else if (lnglng_flg && (val & ulnglng_mask) == val)
|
||||||
{ /* 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)
|
|
||||||
{
|
{
|
||||||
/* fund can't be INT */
|
if ((val & (ulnglng_mask >> 1)) == val)
|
||||||
if (fund == UNSIGNED)
|
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;
|
fund = ULONG;
|
||||||
|
val &= ulng_mask;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (uns_flg)
|
if (uns_flg)
|
||||||
{
|
{
|
||||||
|
@ -710,7 +750,9 @@ static void strint2tok(char intbuf[], struct token* ptok)
|
||||||
fund = UNSIGNED;
|
fund = UNSIGNED;
|
||||||
else if (fund == LONG)
|
else if (fund == LONG)
|
||||||
fund = ULONG;
|
fund = ULONG;
|
||||||
|
else if (fund == LNGLNG)
|
||||||
|
fund = ULNGLNG;
|
||||||
}
|
}
|
||||||
ptok->tk_fund = fund;
|
ptok->tk_fund = fund;
|
||||||
ptok->tk_ival = val;
|
ptok->tk_ival = (writh)val;
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ struct token {
|
||||||
char *tok_bts; /* row of bytes */
|
char *tok_bts; /* row of bytes */
|
||||||
int tok_len; /* length of row of bytes */
|
int tok_len; /* length of row of bytes */
|
||||||
} tok_string;
|
} tok_string;
|
||||||
arith tok_ival; /* for INTEGER */
|
writh tok_ival; /* for INTEGER */
|
||||||
char *tok_fval; /* for FLOATING */
|
char *tok_fval; /* for FLOATING */
|
||||||
} tok_data;
|
} tok_data;
|
||||||
};
|
};
|
||||||
|
|
|
@ -117,11 +117,6 @@
|
||||||
/*#define NOBITFIELD 1 /* if NOT defined, implement bitfields */
|
/*#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
|
!File: static.h
|
||||||
#define GSTATIC /* for large global "static" arrays */
|
#define GSTATIC /* for large global "static" arrays */
|
||||||
|
|
||||||
|
|
|
@ -371,8 +371,7 @@ int int2int(struct expr **expp, register struct type *tp)
|
||||||
unsigned int x = ~0;
|
unsigned int x = ~0;
|
||||||
unsigned int y = -1;
|
unsigned int y = -1;
|
||||||
*/
|
*/
|
||||||
extern long full_mask[];
|
writh remainder = exp->VL_VALUE &
|
||||||
long remainder = exp->VL_VALUE &
|
|
||||||
~full_mask[(int)(tp->tp_size)];
|
~full_mask[(int)(tp->tp_size)];
|
||||||
|
|
||||||
if (remainder == 0 ||
|
if (remainder == 0 ||
|
||||||
|
@ -389,6 +388,16 @@ int int2int(struct expr **expp, register struct type *tp)
|
||||||
return exp->ex_type->tp_fund;
|
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
|
/* With compile-time constants, we don't set fp_used, since this is done
|
||||||
* only when necessary in eval.c.
|
* only when necessary in eval.c.
|
||||||
*/
|
*/
|
||||||
|
@ -400,10 +409,10 @@ void int2float(register struct expr **expp, struct type *tp)
|
||||||
register struct expr *exp = *expp;
|
register struct expr *exp = *expp;
|
||||||
int uns = exp->ex_type->tp_unsigned;
|
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_type = tp;
|
||||||
exp->ex_class = Float;
|
exp->ex_class = Float;
|
||||||
flt_arith2flt(exp->VL_VALUE, &(exp->FL_ARITH), uns);
|
flt_arith2flt((arith)exp->VL_VALUE, &(exp->FL_ARITH), uns);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
fp_used = 1;
|
fp_used = 1;
|
||||||
|
@ -417,24 +426,35 @@ void float2int(struct expr **expp, struct type *tp)
|
||||||
converted to the integral type tp.
|
converted to the integral type tp.
|
||||||
*/
|
*/
|
||||||
register struct expr *ex = *expp;
|
register struct expr *ex = *expp;
|
||||||
|
|
||||||
if (is_fp_cst(ex)) {
|
if (is_fp_cst(ex)) {
|
||||||
arith ar = flt_flt2arith(&ex->FL_ARITH, tp->tp_unsigned);
|
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)
|
if (flt_status == FLT_OVFL)
|
||||||
expr_warning(ex,"overflow in float to int conversion");
|
expr_warning(ex,"overflow in float to int conversion");
|
||||||
else if (flt_status == FLT_UNFL)
|
else if (flt_status == FLT_UNFL)
|
||||||
expr_warning(ex,"underflow in float to unsigned conversion");
|
expr_warning(ex,"underflow in float to unsigned conversion");
|
||||||
ex->ex_type = tp;
|
#endif /* NOTDEF */
|
||||||
/* The following lines are copied from fill_int_expr */
|
/* Now, we defer the conversion until run time
|
||||||
ex->ex_class = Value;
|
unless it fits in 4 bytes.
|
||||||
ex->VL_CLASS = Const;
|
*/
|
||||||
ex->VL_VALUE = ar;
|
if (flt_status != FLT_OVFL && flt_status != FLT_UNFL &&
|
||||||
cut_size(ex);
|
fit4((writh)ar, tp->tp_unsigned)) {
|
||||||
} else {
|
ex->ex_type = tp;
|
||||||
fp_used = 1;
|
/* The following lines are copied from fill_int_expr */
|
||||||
*expp = arith2arith(tp, FLOAT2INT, ex);
|
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)
|
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));
|
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;
|
||||||
|
}
|
||||||
|
|
|
@ -5,30 +5,25 @@
|
||||||
/* $Id$ */
|
/* $Id$ */
|
||||||
/* COMPILER ARITHMETIC */
|
/* COMPILER ARITHMETIC */
|
||||||
|
|
||||||
/* Normally the compiler does its internal arithmetics in longs
|
/* The compiler uses 2 types, arith and writh, for its internal
|
||||||
native to the source machine, which is always good for local
|
arithmetic. Type arith is normally long, and may be too
|
||||||
compilations, and generally OK too for cross compilations
|
narrow for long long values. We can't change arith to a wider
|
||||||
downwards and sidewards. For upwards cross compilation and
|
type, because both <em_arith.h> (pulled by <em.h>) and
|
||||||
to save storage on small machines, SPECIAL_ARITHMETICS will
|
<flt_arith.h> define arith.
|
||||||
be handy.
|
|
||||||
|
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_
|
#ifndef ARITH_H_
|
||||||
#define ARITH_H_
|
#define ARITH_H_
|
||||||
|
|
||||||
#include "parameters.h"
|
|
||||||
|
|
||||||
#ifndef SPECIAL_ARITHMETICS
|
|
||||||
|
|
||||||
#include <em_arith.h> /* obtain definition of "arith" */
|
#include <em_arith.h> /* obtain definition of "arith" */
|
||||||
#include <flt_arith.h>
|
|
||||||
|
|
||||||
#else /* SPECIAL_ARITHMETICS */
|
#define writh long long
|
||||||
|
/* The compiler also uses "unsigned writh". */
|
||||||
/* All preprocessor arithmetic should be done in longs.
|
|
||||||
*/
|
|
||||||
#define arith long /* dummy */
|
|
||||||
|
|
||||||
#endif /* SPECIAL_ARITHMETICS */
|
|
||||||
|
|
||||||
struct expr;
|
struct expr;
|
||||||
struct type;
|
struct type;
|
||||||
|
@ -37,6 +32,8 @@ struct type;
|
||||||
#define arith_sign ((arith) 1 << (arith_size * 8 - 1))
|
#define arith_sign ((arith) 1 << (arith_size * 8 - 1))
|
||||||
#define max_arith (~arith_sign)
|
#define max_arith (~arith_sign)
|
||||||
|
|
||||||
|
extern writh full_mask[]; /* cstoper.c */
|
||||||
|
|
||||||
void arithbalance(register struct expr **e1p, int oper, register struct expr **e2p);
|
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 relbalance(register struct expr **e1p, int oper, register struct expr **e2p);
|
||||||
void ch3pointer(struct expr **expp, int oper, register struct type *tp);
|
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 any2parameter(register struct expr **expp);
|
||||||
void field2arith(register struct expr **expp);
|
void field2arith(register struct expr **expp);
|
||||||
void switch_sign_fp(register struct expr *expr);
|
void switch_sign_fp(register struct expr *expr);
|
||||||
|
char *writh2str(writh val, int uns);
|
||||||
|
|
||||||
#endif /* ARITH_H_ */
|
#endif /* ARITH_H_ */
|
||||||
|
|
|
@ -320,7 +320,7 @@ void ch3cast(register struct expr **expp, int oper, register struct type *tp)
|
||||||
}
|
}
|
||||||
if (oldtp->tp_up->tp_fund == VOID
|
if (oldtp->tp_up->tp_fund == VOID
|
||||||
&& is_cp_cst(exp)
|
&& is_cp_cst(exp)
|
||||||
&& exp->VL_VALUE == (arith)0)
|
&& exp->VL_VALUE == 0)
|
||||||
break; /* switch */
|
break; /* switch */
|
||||||
}
|
}
|
||||||
/* falltrough */
|
/* falltrough */
|
||||||
|
@ -366,7 +366,7 @@ void ch3cast(register struct expr **expp, int oper, register struct type *tp)
|
||||||
case NOTEQUAL:
|
case NOTEQUAL:
|
||||||
case '=':
|
case '=':
|
||||||
case RETURN:
|
case RETURN:
|
||||||
if (is_cp_cst(exp) && exp->VL_VALUE == (arith)0)
|
if (is_cp_cst(exp) && exp->VL_VALUE == 0)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
expr_strict(exp,
|
expr_strict(exp,
|
||||||
|
|
|
@ -206,7 +206,7 @@ void ch3bin(register struct expr **expp, int oper, struct expr *expr)
|
||||||
where o1 == (*expp)->VL_VALUE;
|
where o1 == (*expp)->VL_VALUE;
|
||||||
and ((oper == AND) || (oper == OR))
|
and ((oper == AND) || (oper == OR))
|
||||||
*/
|
*/
|
||||||
if ((oper == AND) == (ex->VL_VALUE != (arith)0)) {
|
if ((oper == AND) == (ex->VL_VALUE != 0)) {
|
||||||
*expp = expr;
|
*expp = expr;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -224,13 +224,13 @@ void ch3bin(register struct expr **expp, int oper, struct expr *expr)
|
||||||
where o2 == expr->VL_VALUE
|
where o2 == expr->VL_VALUE
|
||||||
and ((oper == AND) || (oper == OR))
|
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;
|
(*expp)->ex_flags |= expr->ex_flags | EX_ILVALUE;
|
||||||
free_expression(expr);
|
free_expression(expr);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (oper == OR)
|
if (oper == OR)
|
||||||
expr->VL_VALUE = (arith)1;
|
expr->VL_VALUE = 1;
|
||||||
ch3bin(expp, ',', expr);
|
ch3bin(expp, ',', expr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,6 @@
|
||||||
|
|
||||||
|
|
||||||
extern char options[];
|
extern char options[];
|
||||||
extern arith full_mask[/*MAXSIZE + 1*/]; /* cstoper.c */
|
|
||||||
char *symbol2str();
|
char *symbol2str();
|
||||||
|
|
||||||
void ch3mon(int oper, register struct expr **expp)
|
void ch3mon(int oper, register struct expr **expp)
|
||||||
|
@ -122,7 +121,7 @@ void ch3mon(int oper, register struct expr **expp)
|
||||||
case '-':
|
case '-':
|
||||||
any2arith(expp, oper);
|
any2arith(expp, oper);
|
||||||
if (is_cp_cst(*expp)) {
|
if (is_cp_cst(*expp)) {
|
||||||
arith o1 = (*expp)->VL_VALUE;
|
writh o1 = (*expp)->VL_VALUE;
|
||||||
|
|
||||||
(*expp)->VL_VALUE = (oper == '-') ? -o1 :
|
(*expp)->VL_VALUE = (oper == '-') ? -o1 :
|
||||||
((*expp)->ex_type->tp_unsigned ?
|
((*expp)->ex_type->tp_unsigned ?
|
||||||
|
|
|
@ -602,7 +602,7 @@ void loc_init(struct expr *expr, struct idf *id)
|
||||||
EVAL(expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
EVAL(expr, RVAL, TRUE, NO_LABEL, NO_LABEL);
|
||||||
vl.vl_class = Name;
|
vl.vl_class = Name;
|
||||||
vl.vl_data.vl_idf = id;
|
vl.vl_data.vl_idf = id;
|
||||||
vl.vl_value = (arith)0;
|
vl.vl_value = 0;
|
||||||
store_val(&vl, tp);
|
store_val(&vl, tp);
|
||||||
}
|
}
|
||||||
#else /* LINT */
|
#else /* LINT */
|
||||||
|
|
|
@ -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
|
if ((int)(to_type->tp_size) < (int)word_size
|
||||||
&& to_cnvtype != T_FLOATING
|
&& to_cnvtype != T_FLOATING
|
||||||
) {
|
) {
|
||||||
extern arith full_mask[];
|
|
||||||
|
|
||||||
if (to_cnvtype == T_SIGNED) {
|
if (to_cnvtype == T_SIGNED) {
|
||||||
C_loc(to_type->tp_size);
|
C_loc(to_type->tp_size);
|
||||||
C_loc(word_size);
|
C_loc(word_size);
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
#include "error.h"
|
#include "error.h"
|
||||||
|
|
||||||
/* full_mask[1] == 0XFF, full_mask[2] == 0XFFFF, .. */
|
/* full_mask[1] == 0XFF, full_mask[2] == 0XFFFF, .. */
|
||||||
arith full_mask[MAXSIZE + 1];
|
writh full_mask[MAXSIZE + 1];
|
||||||
#ifndef NOCROSS
|
#ifndef NOCROSS
|
||||||
arith max_int; /* maximum integer on target machine */
|
arith max_int; /* maximum integer on target machine */
|
||||||
arith max_unsigned; /* maximum unsigned 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
|
expressions *expp(ld) and expr(ct), and the result restored in
|
||||||
*expp.
|
*expp.
|
||||||
*/
|
*/
|
||||||
register arith o1 = (*expp)->VL_VALUE;
|
unsigned writh o1 = (unsigned writh)(*expp)->VL_VALUE;
|
||||||
register arith o2 = expr->VL_VALUE;
|
unsigned writh o2 = (unsigned writh)expr->VL_VALUE;
|
||||||
int uns = (*expp)->ex_type->tp_unsigned;
|
int uns = (*expp)->ex_type->tp_unsigned;
|
||||||
|
|
||||||
assert(is_ld_cst(*expp) && is_cp_cst(expr));
|
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;
|
break;
|
||||||
}
|
}
|
||||||
if (uns)
|
if (uns)
|
||||||
o1 /= (unsigned arith) o2;
|
|
||||||
else
|
|
||||||
o1 /= o2;
|
o1 /= o2;
|
||||||
|
else
|
||||||
|
o1 = (unsigned writh)((writh)o1 / (writh)o2);
|
||||||
break;
|
break;
|
||||||
case '%':
|
case '%':
|
||||||
if (o2 == 0) {
|
if (o2 == 0) {
|
||||||
|
@ -62,9 +62,9 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (uns)
|
if (uns)
|
||||||
o1 %= (unsigned arith) o2;
|
|
||||||
else
|
|
||||||
o1 %= o2;
|
o1 %= o2;
|
||||||
|
else
|
||||||
|
o1 = (unsigned writh)((writh)o1 % (writh)o2);
|
||||||
break;
|
break;
|
||||||
case '+':
|
case '+':
|
||||||
o1 += o2;
|
o1 += o2;
|
||||||
|
@ -78,15 +78,14 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
|
||||||
case RIGHT:
|
case RIGHT:
|
||||||
if (o2 == 0)
|
if (o2 == 0)
|
||||||
break;
|
break;
|
||||||
if (uns) {
|
if (uns)
|
||||||
o1 = (o1 >> 1) & ~arith_sign;
|
o1 >>= o2;
|
||||||
o1 >>= (o2 - 1);
|
else
|
||||||
}
|
o1 = (unsigned writh)((writh)o1 >> (writh)o2);
|
||||||
else o1 >>= o2;
|
|
||||||
break;
|
break;
|
||||||
case '<':
|
case '<':
|
||||||
{
|
{
|
||||||
arith tmp = o1;
|
writh tmp = o1;
|
||||||
|
|
||||||
o1 = o2;
|
o1 = o2;
|
||||||
o2 = tmp;
|
o2 = tmp;
|
||||||
|
@ -94,13 +93,13 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
case '>':
|
case '>':
|
||||||
if (uns)
|
if (uns)
|
||||||
o1 = (unsigned arith) o1 > (unsigned arith) o2;
|
|
||||||
else
|
|
||||||
o1 = o1 > o2;
|
o1 = o1 > o2;
|
||||||
|
else
|
||||||
|
o1 = (writh)o1 > (writh)o2;
|
||||||
break;
|
break;
|
||||||
case LESSEQ:
|
case LESSEQ:
|
||||||
{
|
{
|
||||||
arith tmp = o1;
|
writh tmp = o1;
|
||||||
|
|
||||||
o1 = o2;
|
o1 = o2;
|
||||||
o2 = tmp;
|
o2 = tmp;
|
||||||
|
@ -108,9 +107,9 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
|
||||||
/* Fall through */
|
/* Fall through */
|
||||||
case GREATEREQ:
|
case GREATEREQ:
|
||||||
if (uns)
|
if (uns)
|
||||||
o1 = (unsigned arith) o1 >= (unsigned arith) o2;
|
|
||||||
else
|
|
||||||
o1 = o1 >= o2;
|
o1 = o1 >= o2;
|
||||||
|
else
|
||||||
|
o1 = (writh)o1 >= (writh)o2;
|
||||||
break;
|
break;
|
||||||
case EQUAL:
|
case EQUAL:
|
||||||
o1 = o1 == o2;
|
o1 = o1 == o2;
|
||||||
|
@ -128,7 +127,7 @@ void cstbin(register struct expr **expp, int oper, register struct expr *expr)
|
||||||
o1 ^= o2;
|
o1 ^= o2;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
(*expp)->VL_VALUE = o1;
|
(*expp)->VL_VALUE = (writh)o1;
|
||||||
cut_size(*expp);
|
cut_size(*expp);
|
||||||
(*expp)->ex_flags |= expr->ex_flags;
|
(*expp)->ex_flags |= expr->ex_flags;
|
||||||
(*expp)->ex_flags &= ~EX_PARENS;
|
(*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
|
/* The constant value of the expression expr is made to
|
||||||
conform to the size of the type of the expression.
|
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 uns = expr->ex_type->tp_unsigned;
|
||||||
int size = (int) expr->ex_type->tp_size;
|
int size = (int) expr->ex_type->tp_size;
|
||||||
|
|
||||||
|
@ -159,8 +158,8 @@ void cut_size(register struct expr *expr)
|
||||||
o1 &= full_mask[size];
|
o1 &= full_mask[size];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
int nbits = (int) (arith_size - size) * 8;
|
int nbits = (int) (sizeof(o1) - size) * 8;
|
||||||
arith remainder = o1 & ~full_mask[size];
|
writh remainder = o1 & ~full_mask[size];
|
||||||
|
|
||||||
if (remainder != 0 && remainder != ~full_mask[size])
|
if (remainder != 0 && remainder != ~full_mask[size])
|
||||||
if (!ResultKnown)
|
if (!ResultKnown)
|
||||||
|
@ -173,22 +172,20 @@ void cut_size(register struct expr *expr)
|
||||||
void init_cst(void)
|
void init_cst(void)
|
||||||
{
|
{
|
||||||
register int i = 0;
|
register int i = 0;
|
||||||
register arith bt = (arith)0;
|
unsigned writh bt = 0;
|
||||||
|
|
||||||
/* FIXME arith is insufficient for long long. We ignore
|
while (!((writh)bt < 0)) {
|
||||||
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");
|
||||||
full_mask[i] = bt;
|
full_mask[i] = bt;
|
||||||
}
|
}
|
||||||
if ((int)long_size > arith_size)
|
/* signed comparison; lnglng_size might be -1 */
|
||||||
fatal("sizeof (arith) insufficient on this machine");
|
if (long_size > (arith)sizeof(writh) ||
|
||||||
|
lnglng_size > (arith)sizeof(writh))
|
||||||
|
fatal("sizeof(writh) insufficient on this machine");
|
||||||
#ifndef NOCROSS
|
#ifndef NOCROSS
|
||||||
max_int = full_mask[(int)int_size] & ~(1L << ((int)int_size * 8 - 1));
|
max_int = (arith)((unsigned writh)full_mask[(int)int_size] >> 1);
|
||||||
max_unsigned = full_mask[(int)int_size];
|
max_unsigned = (arith)full_mask[(int)int_size];
|
||||||
#endif /* NOCROSS */
|
#endif /* NOCROSS */
|
||||||
}
|
}
|
||||||
|
|
|
@ -343,7 +343,7 @@ arrayer(arith *sizep;)
|
||||||
constant_expression(&expr)
|
constant_expression(&expr)
|
||||||
{
|
{
|
||||||
check_array_subscript(expr);
|
check_array_subscript(expr);
|
||||||
*sizep = expr->VL_VALUE;
|
*sizep = (arith)expr->VL_VALUE;
|
||||||
free_expression(expr);
|
free_expression(expr);
|
||||||
}
|
}
|
||||||
]?
|
]?
|
||||||
|
@ -430,7 +430,7 @@ enumerator(struct type *tp; arith *lp;)
|
||||||
'='
|
'='
|
||||||
constant_expression(&expr)
|
constant_expression(&expr)
|
||||||
{
|
{
|
||||||
*lp = expr->VL_VALUE;
|
*lp = (arith)expr->VL_VALUE;
|
||||||
free_expression(expr);
|
free_expression(expr);
|
||||||
}
|
}
|
||||||
]?
|
]?
|
||||||
|
@ -548,7 +548,7 @@ bit_expression(struct field **fd;)
|
||||||
':'
|
':'
|
||||||
constant_expression(&expr)
|
constant_expression(&expr)
|
||||||
{
|
{
|
||||||
(*fd)->fd_width = expr->VL_VALUE;
|
(*fd)->fd_width = (arith)expr->VL_VALUE;
|
||||||
free_expression(expr);
|
free_expression(expr);
|
||||||
#ifdef NOBITFIELD
|
#ifdef NOBITFIELD
|
||||||
error("bitfields are not implemented");
|
error("bitfields are not implemented");
|
||||||
|
|
|
@ -118,11 +118,11 @@ void reject_params(register struct declarator *dc)
|
||||||
|
|
||||||
void check_array_subscript(register struct expr *expr)
|
void check_array_subscript(register struct expr *expr)
|
||||||
{
|
{
|
||||||
arith size = expr->VL_VALUE;
|
writh size = expr->VL_VALUE;
|
||||||
|
|
||||||
if (size < 0) {
|
if (size < 0) {
|
||||||
error("array size is negative");
|
error("array size is negative");
|
||||||
expr->VL_VALUE = (arith)1;
|
expr->VL_VALUE = 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
|
@ -131,6 +131,6 @@ void check_array_subscript(register struct expr *expr)
|
||||||
else
|
else
|
||||||
if (size & ~max_unsigned) { /* absolutely ridiculous */
|
if (size & ~max_unsigned) { /* absolutely ridiculous */
|
||||||
expr_error(expr, "overflow in array size");
|
expr_error(expr, "overflow in array size");
|
||||||
expr->VL_VALUE = (arith)1;
|
expr->VL_VALUE = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
/* DUMP ROUTINES */
|
/* DUMP ROUTINES */
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
#include "parameters.h"
|
#include "parameters.h"
|
||||||
|
#ifdef DEBUG
|
||||||
#include <ack_string.h>
|
#include <ack_string.h>
|
||||||
#include <alloc.h>
|
#include <alloc.h>
|
||||||
#include <flt_arith.h>
|
#include <flt_arith.h>
|
||||||
|
@ -442,8 +442,8 @@ static void p1_expr(int lvl, register struct expr *expr)
|
||||||
print("(Unknown) ");
|
print("(Unknown) ");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
print(expr->ex_type->tp_unsigned ? "%lu\n" : "%ld\n",
|
print("%s\n", writh2str(expr->VL_VALUE,
|
||||||
expr->VL_VALUE);
|
expr->ex_type->tp_unsigned));
|
||||||
break;
|
break;
|
||||||
case String:
|
case String:
|
||||||
{
|
{
|
||||||
|
|
|
@ -106,7 +106,7 @@ void EVAL(register struct expr *expr, int val, int code, label true_label, label
|
||||||
case String: /* a string constant */
|
case String: /* a string constant */
|
||||||
if (gencode) {
|
if (gencode) {
|
||||||
string2pointer(expr);
|
string2pointer(expr);
|
||||||
C_lae_dlb(expr->VL_LBL, expr->VL_VALUE);
|
C_lae_dlb(expr->VL_LBL, (arith)expr->VL_VALUE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Float: /* a floating constant */
|
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);
|
NO_LABEL, NO_LABEL);
|
||||||
assert(is_cp_cst(right));
|
assert(is_cp_cst(right));
|
||||||
if (gencode) {
|
if (gencode) {
|
||||||
C_adp(right->VL_VALUE);
|
C_adp((arith)right->VL_VALUE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ',':
|
case ',':
|
||||||
|
@ -858,10 +858,11 @@ void store_val(register struct value *vl, register struct type *tp)
|
||||||
{
|
{
|
||||||
register int inword = 0;
|
register int inword = 0;
|
||||||
register int indword = 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 */
|
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);
|
store_block(tp->tp_size, tp->tp_align);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -930,7 +931,8 @@ void load_val(register struct expr *expr, int rlval)
|
||||||
register struct type *tp = expr->ex_type;
|
register struct type *tp = expr->ex_type;
|
||||||
int rvalue = (rlval == RVAL && expr->ex_lvalue != 0);
|
int rvalue = (rlval == RVAL && expr->ex_lvalue != 0);
|
||||||
register int inword = 0, indword = 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
|
if (expr->ex_type->tp_fund == FLOAT
|
||||||
|| expr->ex_type->tp_fund == DOUBLE
|
|| expr->ex_type->tp_fund == DOUBLE
|
||||||
|
@ -938,11 +940,11 @@ void load_val(register struct expr *expr, int rlval)
|
||||||
fp_used = 1;
|
fp_used = 1;
|
||||||
if (expr->VL_CLASS == Const) {
|
if (expr->VL_CLASS == Const) {
|
||||||
if (rvalue) { /* absolute addressing */
|
if (rvalue) { /* absolute addressing */
|
||||||
load_cst(val, pointer_size);
|
load_cst(wval, pointer_size);
|
||||||
load_block(tp->tp_size, tp->tp_align);
|
load_block(tp->tp_size, tp->tp_align);
|
||||||
}
|
}
|
||||||
else /* integer, unsigned, long, enum etc */
|
else /* integer, unsigned, long, enum etc */
|
||||||
load_cst(val, tp->tp_size);
|
load_cst(wval, tp->tp_size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (rvalue) {
|
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.
|
/* EM can't encode ldc with constant over 4 bytes.
|
||||||
Such a constant must go into rom.
|
Such a constant must go into rom.
|
||||||
|
@ -1036,7 +1038,7 @@ void load_cst(arith val, arith siz)
|
||||||
label datlab;
|
label datlab;
|
||||||
|
|
||||||
C_df_dlb(datlab = data_label());
|
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_lae_dlb(datlab, (arith)0);
|
||||||
C_loi(siz);
|
C_loi(siz);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
|
|
||||||
#include <em.h>
|
#include <em.h>
|
||||||
|
#include "arith.h" /* writh */
|
||||||
|
|
||||||
struct expr;
|
struct expr;
|
||||||
struct value;
|
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 store_val(register struct value *vl, register struct type *tp);
|
||||||
void load_val(register struct expr *expr, int rlval);
|
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 */
|
#endif /* LINT */
|
||||||
|
|
||||||
|
|
|
@ -184,21 +184,21 @@ void idf2expr(register struct expr *expr)
|
||||||
if (def->df_sc == ENUM)
|
if (def->df_sc == ENUM)
|
||||||
{
|
{
|
||||||
expr->VL_CLASS = Const;
|
expr->VL_CLASS = Const;
|
||||||
expr->VL_VALUE = def->df_address;
|
expr->VL_VALUE = (writh)def->df_address;
|
||||||
}
|
}
|
||||||
#ifndef LINT
|
#ifndef LINT
|
||||||
else if (def->df_sc == STATIC && def->df_level >= L_LOCAL)
|
else if (def->df_sc == STATIC && def->df_level >= L_LOCAL)
|
||||||
{
|
{
|
||||||
expr->VL_CLASS = Label;
|
expr->VL_CLASS = Label;
|
||||||
expr->VL_LBL = def->df_address;
|
expr->VL_LBL = def->df_address;
|
||||||
expr->VL_VALUE = (arith) 0;
|
expr->VL_VALUE = 0;
|
||||||
}
|
}
|
||||||
#endif /* LINT */
|
#endif /* LINT */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
expr->VL_CLASS = Name;
|
expr->VL_CLASS = Name;
|
||||||
expr->VL_IDF = idf;
|
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_file = dot.tk_file;
|
||||||
expr->ex_line = dot.tk_line;
|
expr->ex_line = dot.tk_line;
|
||||||
fill_int_expr(expr, ivalue, fund);
|
fill_int_expr(expr, (writh)ivalue, fund);
|
||||||
return expr;
|
return expr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void fill_int_expr(register struct expr *ex,
|
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
|
/* Details derived from ivalue and fund are put into the
|
||||||
constant integer expression ex.
|
constant integer expression ex.
|
||||||
|
@ -294,6 +294,16 @@ arith ivalue, int fund)
|
||||||
case ULONG:
|
case ULONG:
|
||||||
ex->ex_type = ulong_type;
|
ex->ex_type = ulong_type;
|
||||||
break;
|
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:
|
default:
|
||||||
crash("(fill_int_expr) bad fund %s\n", symbol2str(fund));
|
crash("(fill_int_expr) bad fund %s\n", symbol2str(fund));
|
||||||
/*NOTREACHED*/
|
/*NOTREACHED*/
|
||||||
|
@ -406,6 +416,7 @@ void chk_cst_expr(struct expr **expp)
|
||||||
case INT:
|
case INT:
|
||||||
case ENUM:
|
case ENUM:
|
||||||
case LONG:
|
case LONG:
|
||||||
|
case LNGLNG:
|
||||||
if (is_ld_cst(expr))
|
if (is_ld_cst(expr))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
|
|
||||||
struct value {
|
struct value {
|
||||||
int vl_class; /* Const, Name or Label */
|
int vl_class; /* Const, Name or Label */
|
||||||
arith vl_value; /* constant value or offset */
|
writh vl_value; /* constant value or offset */
|
||||||
union {
|
union {
|
||||||
struct idf *vl_idf; /* external name */
|
struct idf *vl_idf; /* external name */
|
||||||
label vl_lbl; /* compiler-generated label */
|
label vl_lbl; /* compiler-generated label */
|
||||||
|
@ -100,8 +100,6 @@ struct expr {
|
||||||
#define ISNAME(e) ((e)->ex_class == Value && (e)->VL_CLASS == Name)
|
#define ISNAME(e) ((e)->ex_class == Value && (e)->VL_CLASS == Name)
|
||||||
#define ISCOMMA(e) ((e)->ex_class == Oper && (e)->OP_OPER == INITCOMMA)
|
#define ISCOMMA(e) ((e)->ex_class == Oper && (e)->OP_OPER == INITCOMMA)
|
||||||
|
|
||||||
extern struct expr *intexpr(), *new_oper();
|
|
||||||
|
|
||||||
/* ALLOCDEF "expr" 20 */
|
/* ALLOCDEF "expr" 20 */
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,7 +111,7 @@ void string2expr(register struct expr **expp, char *str, int len);
|
||||||
void int2expr(struct expr *expr);
|
void int2expr(struct expr *expr);
|
||||||
void float2expr(register struct expr *expr);
|
void float2expr(register struct expr *expr);
|
||||||
struct expr* intexpr(arith ivalue, int fund);
|
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,
|
struct expr *new_oper(struct type *tp, register struct expr *e1, int oper,
|
||||||
register struct expr *e2);
|
register struct expr *e2);
|
||||||
void chk_cst_expr(struct expr **expp);
|
void chk_cst_expr(struct expr **expp);
|
||||||
|
|
|
@ -28,8 +28,6 @@
|
||||||
#include "eval.h"
|
#include "eval.h"
|
||||||
|
|
||||||
|
|
||||||
extern arith full_mask[]; /* cstoper.c */
|
|
||||||
|
|
||||||
/* Eval_field() evaluates expressions involving bit fields.
|
/* Eval_field() evaluates expressions involving bit fields.
|
||||||
The various instructions are not yet optimised in the expression
|
The various instructions are not yet optimised in the expression
|
||||||
tree and are therefore dealt with in this function.
|
tree and are therefore dealt with in this function.
|
||||||
|
@ -136,6 +134,8 @@ void store_field(
|
||||||
register struct expr *leftop,
|
register struct expr *leftop,
|
||||||
arith tmpvar)
|
arith tmpvar)
|
||||||
{
|
{
|
||||||
|
arith high_mask;
|
||||||
|
|
||||||
C_loc(fd->fd_mask);
|
C_loc(fd->fd_mask);
|
||||||
C_and(word_size);
|
C_and(word_size);
|
||||||
if (code == TRUE)
|
if (code == TRUE)
|
||||||
|
@ -145,7 +145,8 @@ void store_field(
|
||||||
C_slu(word_size);
|
C_slu(word_size);
|
||||||
else
|
else
|
||||||
C_sli(word_size);
|
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 */
|
if (leftop->ex_depth == 0) { /* simple case */
|
||||||
load_val(leftop, RVAL);
|
load_val(leftop, RVAL);
|
||||||
C_and(word_size);
|
C_and(word_size);
|
||||||
|
|
|
@ -544,11 +544,11 @@ void check_ival(struct expr **expp, register struct type *tp)
|
||||||
if (idf->id_def->df_type->tp_fund == FUNCTION)
|
if (idf->id_def->df_type->tp_fund == FUNCTION)
|
||||||
C_con_pnam(idf->id_text);
|
C_con_pnam(idf->id_text);
|
||||||
else /* e.g., int a; int *p = &a; */
|
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 {
|
else {
|
||||||
assert(expr->VL_CLASS == Label);
|
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;
|
break;
|
||||||
case FLOAT:
|
case FLOAT:
|
||||||
|
@ -595,7 +595,7 @@ and also to prevent runtime coercions for compile-time constants.
|
||||||
print_expr("init-expr after cast", expr);
|
print_expr("init-expr after cast", expr);
|
||||||
#endif /* DEBUG */
|
#endif /* DEBUG */
|
||||||
if (is_cp_cst(expr))
|
if (is_cp_cst(expr))
|
||||||
put_bf(tp, expr->VL_VALUE);
|
put_bf(tp, (arith)expr->VL_VALUE);
|
||||||
else
|
else
|
||||||
illegal_init_cst(expr);
|
illegal_init_cst(expr);
|
||||||
break;
|
break;
|
||||||
|
@ -701,7 +701,7 @@ void put_bf(struct type *tp, arith val)
|
||||||
field |= (val & fd->fd_mask) << fd->fd_shift;
|
field |= (val & fd->fd_mask) << fd->fd_shift;
|
||||||
if (sd->sd_sdef == 0 || sd->sd_sdef->sd_offset != offset) {
|
if (sd->sd_sdef == 0 || sd->sd_sdef->sd_offset != offset) {
|
||||||
/* the selector was the last stored at this address */
|
/* the selector was the last stored at this address */
|
||||||
exp.VL_VALUE = field;
|
exp.VL_VALUE = (writh)field;
|
||||||
con_int(&exp);
|
con_int(&exp);
|
||||||
field = (arith)0;
|
field = (arith)0;
|
||||||
offset = (arith)-1;
|
offset = (arith)-1;
|
||||||
|
@ -739,11 +739,11 @@ void con_int(register struct expr *ex)
|
||||||
|
|
||||||
assert(is_cp_cst(ex));
|
assert(is_cp_cst(ex));
|
||||||
if (tp->tp_unsigned)
|
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)
|
else if (tp->tp_size == word_size)
|
||||||
C_con_cst(ex->VL_VALUE);
|
C_con_cst((arith)ex->VL_VALUE);
|
||||||
else
|
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)
|
void illegal_init_cst(struct expr *ex)
|
||||||
|
|
|
@ -32,8 +32,6 @@
|
||||||
#include "level.h"
|
#include "level.h"
|
||||||
#include "print.h"
|
#include "print.h"
|
||||||
|
|
||||||
extern long full_mask[];
|
|
||||||
|
|
||||||
#define INCR_SIZE 64
|
#define INCR_SIZE 64
|
||||||
|
|
||||||
static struct db_str
|
static struct db_str
|
||||||
|
|
|
@ -147,7 +147,7 @@ if_statement
|
||||||
/* The comparison has been optimized
|
/* The comparison has been optimized
|
||||||
to a 0 or 1.
|
to a 0 or 1.
|
||||||
*/
|
*/
|
||||||
if (expr->VL_VALUE == (arith)0) {
|
if (expr->VL_VALUE == 0) {
|
||||||
C_bra(l_false);
|
C_bra(l_false);
|
||||||
}
|
}
|
||||||
/* else fall through */
|
/* else fall through */
|
||||||
|
@ -210,7 +210,7 @@ while_statement
|
||||||
{
|
{
|
||||||
opnd2test(&expr, WHILE);
|
opnd2test(&expr, WHILE);
|
||||||
if (is_cp_cst(expr)) {
|
if (is_cp_cst(expr)) {
|
||||||
if (expr->VL_VALUE == (arith)0) {
|
if (expr->VL_VALUE == 0) {
|
||||||
C_bra(l_break);
|
C_bra(l_break);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,11 +264,11 @@ do_statement
|
||||||
{
|
{
|
||||||
opnd2test(&expr, WHILE);
|
opnd2test(&expr, WHILE);
|
||||||
if (is_cp_cst(expr)) {
|
if (is_cp_cst(expr)) {
|
||||||
if (expr->VL_VALUE == (arith)1) {
|
if (expr->VL_VALUE == 1) {
|
||||||
C_bra(l_body);
|
C_bra(l_body);
|
||||||
}
|
}
|
||||||
#ifdef LINT
|
#ifdef LINT
|
||||||
end_do_stmt(1, expr->VL_VALUE != (arith)0);
|
end_do_stmt(1, expr->VL_VALUE != 0);
|
||||||
#endif /* LINT */
|
#endif /* LINT */
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -313,7 +313,7 @@ for_statement
|
||||||
{
|
{
|
||||||
opnd2test(&e_test, FOR);
|
opnd2test(&e_test, FOR);
|
||||||
if (is_cp_cst(e_test)) {
|
if (is_cp_cst(e_test)) {
|
||||||
if (e_test->VL_VALUE == (arith)0) {
|
if (e_test->VL_VALUE == 0) {
|
||||||
C_bra(l_break);
|
C_bra(l_break);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,13 +32,13 @@ extern char options[];
|
||||||
|
|
||||||
int density = DENSITY;
|
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,
|
/* Careful! up - low might not fit in an arith. And then,
|
||||||
the test "up-low < 0" might also not work to detect this
|
the test "up-low < 0" might also not work to detect this
|
||||||
situation! Or is this just a bug in the M68020/M68000?
|
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)));
|
return (nr == 0 || (diff >= 0 && diff / nr <= (density - 1)));
|
||||||
}
|
}
|
||||||
|
@ -117,10 +117,10 @@ void code_endswitch(void)
|
||||||
C_rom_ilb(sh->sh_default);
|
C_rom_ilb(sh->sh_default);
|
||||||
if (compact(sh->sh_nrofentries, sh->sh_lowerbd, sh->sh_upperbd)) {
|
if (compact(sh->sh_nrofentries, sh->sh_lowerbd, sh->sh_upperbd)) {
|
||||||
/* CSA */
|
/* CSA */
|
||||||
register arith val;
|
writh val;
|
||||||
|
|
||||||
C_rom_icon(long2str((long)sh->sh_lowerbd,10), size);
|
C_rom_icon(writh2str(sh->sh_lowerbd, 0), size);
|
||||||
C_rom_icon(long2str((long)(sh->sh_upperbd - sh->sh_lowerbd),10),
|
C_rom_icon(writh2str(sh->sh_upperbd - sh->sh_lowerbd, 0),
|
||||||
size);
|
size);
|
||||||
ce = sh->sh_entries;
|
ce = sh->sh_entries;
|
||||||
for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) {
|
for (val = sh->sh_lowerbd; val <= sh->sh_upperbd; val++) {
|
||||||
|
@ -136,10 +136,10 @@ void code_endswitch(void)
|
||||||
C_csa(size);
|
C_csa(size);
|
||||||
}
|
}
|
||||||
else { /* CSB */
|
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) {
|
for (ce = sh->sh_entries; ce; ce = ce->next) {
|
||||||
/* generate the entries: value + prog.label */
|
/* 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_rom_ilb(ce->ce_label);
|
||||||
}
|
}
|
||||||
C_lae_dlb(tablabel, (arith)0); /* perform the switch */
|
C_lae_dlb(tablabel, (arith)0); /* perform the switch */
|
||||||
|
@ -162,7 +162,7 @@ void code_endswitch(void)
|
||||||
|
|
||||||
void code_case(struct expr *expr)
|
void code_case(struct expr *expr)
|
||||||
{
|
{
|
||||||
register arith val;
|
writh val;
|
||||||
register struct case_entry *ce;
|
register struct case_entry *ce;
|
||||||
register struct switch_hdr *sh = switch_stack;
|
register struct switch_hdr *sh = switch_stack;
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@ struct switch_hdr {
|
||||||
int sh_nrofentries;
|
int sh_nrofentries;
|
||||||
struct type *sh_type;
|
struct type *sh_type;
|
||||||
struct expr *sh_expr;
|
struct expr *sh_expr;
|
||||||
arith sh_lowerbd;
|
writh sh_lowerbd;
|
||||||
arith sh_upperbd;
|
writh sh_upperbd;
|
||||||
struct case_entry *sh_entries;
|
struct case_entry *sh_entries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ struct switch_hdr {
|
||||||
struct case_entry {
|
struct case_entry {
|
||||||
struct case_entry *next;
|
struct case_entry *next;
|
||||||
label ce_label;
|
label ce_label;
|
||||||
arith ce_value;
|
writh ce_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ALLOCDEF "case_entry" 20 */
|
/* ALLOCDEF "case_entry" 20 */
|
||||||
|
|
|
@ -107,6 +107,7 @@ struct tokenname tkfunny[] = { /* internal keywords */
|
||||||
{LNGLNG, "long long"},
|
{LNGLNG, "long long"},
|
||||||
{LNGDBL, "long double"},
|
{LNGDBL, "long double"},
|
||||||
{ULONG, "unsigned long"},
|
{ULONG, "unsigned long"},
|
||||||
|
{ULNGLNG, "unsigned long long"},
|
||||||
|
|
||||||
{ARRAY, "array"},
|
{ARRAY, "array"},
|
||||||
{FUNCTION, "function"},
|
{FUNCTION, "function"},
|
||||||
|
|
Loading…
Reference in a new issue